In: Computer Science
extra.cpp. It defines the function extra which will be used in the main program.
extra.h. This is the header file. Notice that is only really provides the declaration of the function.
o In the declaration, the names of the parameters are not required, only their types.
o Note that the function declaration ends in a ; (semicolon). Don't forget!!!
o There are some weird # statements, we'll get to that.
• main.cpp. This is the main program. Notice that it has the following statement in it:
#include "extra.h"
This means that the main program is "including" the declaration of the function so that the compiler may check the type use of extra by main. Notice the quotes. When the include uses quotes, it is assumed that the .h file is in the same directory as the other files. include with <> means get includes from the "standard include place". Since it is our include file, we need to use quotes for it.
Weird # in headers
Anything beginning with # is part of the pre-processor. This
controls aspects of how the
compilation goes. In this case, we are trying to prevent a multiple definition error. What if we wanted to use extra in a more than one file? Your expectation is that every file
that wants to use extra should include the extra.h file for compilation to work, and you would be correct. Sort of. Remember that you cannot declare a variable more than once, and the same goes for a function. You should only declare it once. In making one executable from many files, it is possible that, by including extra.h in multiple files, we would declare the extra function multiple times for this single executable. C++ would complain. However, it would be weird to have to do this in some kind of order where only one file included extra.h and assume the rest would have to assume it is available.
The way around this involves the pre-processor. Basically there are three statements we care about:
#ifndef some_variable_we_make_up #define some_variable_we_make_up
... all the declarations in this .h file
#endif
This means. "If the pre-processor variable we indicate (some_variable_we_make_up) is not defined (#ifndef), go ahead and define it (#define) for this compilation and do everything else up to the #endif, meaning include the declarations in the compilation. If the variable is already defined, skip everything up to the #endif, meaning skip the declarations"
Thus whichever file pulls in the header file first, defines the pre-processor variable and declares the function for the entire compilation. If some other file also includes the header file later in the compilation, the pre-processor variable is already defined so the declarations are not included.
Make a new project called 'splitter'. We want to add three new files to the project: main.cpp functions.cpp functions.h
Make a new file (weird icon next to open) then save as main.cpp
Now make the functions.cpp and the functions.h file.
You should have three file tabs at the top now.
Function split
The split function should take in a string and return a vector<string> of the individual elements in the string that are separated by the separator character (default ' ',
space). Thus
"hello mom and dad" à {"hello", "mom", "and", "dad}
• Open functions.h and store the function declaration of split there. The
declaration should be:
vector<string> split (const string &s, char separator=' ');
As discussed in class, default parameter values go in the header file only. The default does not occur in the definition if it occurred in the declaration.
This header file should wrap all declarations using the #ifndef, #define, #endif as discussed above. Make up your own variable.
Open functions.cpp and write the definition of the function split. Make sure it follows the declaration in functions.h. The parameter names do not matter but the types do. Make sure the function signature (as discussed in class) match for the declaration and definition.
You can compile functions.cpp (not build, at least not yet) to see if functions.cpp is well-formed for C++. It will not build an executable, but instead a .o file. The .o file is the result of compilation but before building an executable, an in-between stage.
Function print_vector
This function prints all the elements of vector<string> v to the ostream out provided as a reference parameter (it must be a reference). Note out and v are passed by reference.
• print_vector : Store the function print-vector in functions.cpp, put its declaration in functions.h It should look a lot like the below:
void print_vector (ostream &out, const vector<string> &v);
• compile the function (not build, compile) to make sure it follows the rules. Function main
The main function goes in main.cpp.
In main.cpp make sure you #include "functions.h" (note the quotes),
making those functions available to main. Write a main function that:
The operation of main is as follows:
o prompts for a string to be split
o prompts for the single character to split the string with
o splits the string using the split function which returns a vector
o prints the vector using the print_vector function
• compile (not build) main to see that it follows the rules
Build the executable
Select the main.cpp tab of geany and now build the project. An executable called main should now be created which you can run.
Assignment Notes
1. Couple ways to do the split function 1. getline
i. getline takes a delimiter character as a third argument. In combination with an input string stream you can use getline to split up the string and push_back each element onto the vector.
ii. example getline(stream, line, delim) gets the string from the stream (istream, ifstream, istringstream, etc.) up to the end of the line or the delim character.
b. string methods find and substr. You can use the find method to find the delim character, extract the split element using substr, and push_back the element onto the vector.
2. Default parameter value. The default parameter value needs to be set at declaration time, which means that the default value for a function parameter should be in the header file (the declaration). If it is in the declaration, it is not required to be in the definition, and by convention should not be.
main.cpp:
/* * File: main.cpp * Author: bill * * Created on October 10, 2013, 2:13 PM */ #include <iostream> #include<string> #include<vector> using std::cout;using std::endl;using std::cin; using std::vector; using std::string; #include"extra.h" /* * */ int main() { string result; vector<string> v{"this", "is", "a", "test"}; result = my_fun(v); cout << "Result:"<<result<<endl; }
extra.cpp:
#include<vector> #include<string> using std::vector; using std::string; string my_fun(const vector<string>& v){ string result=""; for(auto element : v) result += element[0]; return result; }
extra.h:
/* * File: extra.h * Author: bill * * Created on October 10, 2013, 2:14 PM */ #ifndef EXTRA_H #define EXTRA_H #include<string> using std::string; #include<vector> using std::vector; string my_fun(const vector<string>&); #endif /* EXTRA_H */
And finally, save your 'functions.cpp', it will be used next time.
//functions.h
#ifndef FUNCTION_H
#define FUNCTION_H
#include <iostream>
#include <vector>
#include <sstream>
using namespace std;
vector<string> split(const string &s, char
delim);
void print_vector (ostream &out, const vector<string>
&v);
#endif /* FUNCTION_H */
//functions.cpp
#include <iostream>
#include <vector>
#include <sstream>
using namespace std;
vector<string> split(const string &s, char delim)
{
vector<string> elements;
stringstream sst(s);
string item;
while (getline(sst, item, delim))
{
elements.push_back(item);
}
return elements;
}
void print_vector (ostream &out, const vector<string>
&v){
out << "[";
size_t last = v.size() - 1;
for(size_t i = 0; i < v.size(); ++i) {
out << v[i];
if (i != last)
out << ", ";
}
out << "]";
}
//main.cpp
#include <iostream>
#include"functions.h"
int main() {
// your code goes here
vector<string> all_strings;
string input;
string split_char;
cout<<"Enter the string to be split :
";getline(cin,input);
cout<<"Enter the delimeter char:
";getline(cin,split_char);
cout<<"You entered :
["<<input<<"]"<<endl;
cout<<"Delimeter :
["<<split_char[0]<<"]"<<endl;
all_strings=split(input,split_char[0]);
print_vector(cout,all_strings);
cout<<endl;
return 0;
}
Output: