trying to do a project for class, but keep getting the error: no instance of overloaded function matches argument list relating to the implementation of the rows vector. the area that is specifically highlighted is the . operator before push_back and insert.
void holdLines(ifstream in, vector<string> rows) {
string line;
string prevLine;
vector<string> rows;
int lineNumber = 0;
int vectorNumber = 0;
while(true) {
getline(in, line);
if(in.fail()) {
break;
}
lineNumber++;
vectorNumber = lineNumber - 1;
rows.push_back(lineNumber);
rows.insert(prevLine, line);
}
}
You are trying to pass an integer to push_back when a string is required.
It also looks like your local variable "rows" is named the same as your parameter "rows".
http://www.cplusplus.com/reference/vector/vector/push_back/
Your compiler is correct: there is no overload of std::vector<std::string>::push_back that accepts an int, because a std::vector<std::string> stores std::strings, not ints.
It's quite unclear from code alone what you are trying to do, due to the myriad mistakes, but start by replacing your push_back call with something sensible.
There is no method insert with two parameters of type std::string as you are trying to call
rows.insert(prevLine, line);
Also it is not clear what you are trying to do in this statement.
Edit: After you updated yor code nevertheless this statemenet
rows.push_back(lineNumber);
also is wrong because the rows is declared as a vecto of strings. It is not a vector of int and moreover class std::string does not have an appropriate constructor.
But in any case the function does not make sense because you declared a local variable with the same name as the second parameter and tried to fill this local vector that will be deleted after exiting the function
void holdLines(ifstream in, vector<string> rows) {
^^^^^^^^^^^^^^^^^^
string line;
string prevLine;
vector<string> rows;
^^^^^^^^^^^^^^^^^^^^
//..
I think the function should be declared either like
void holdLines(ifstream in, vector<string> &rows);
^^^
or like
vector<string> holdLines(ifstream in);
Take into account that instead of this statements
while(true) {
getline(in, line);
if(in.fail()) {
break;
}
//...
you could write
while ( getline( in, line ) )
{
//...
If you need simply to fill the vector that is passed as the argument then the function can look the following way
void holdLines( std::ifstream &in, std::vector<std::string> &rows )
{
std::string line;
while ( std::getline( in, line ) ) rows.push_back( line );
}
Related
i have a class which named class nameAndLastname and it has a
class nameAndLastname
{
private:
vector<string> Names_Lastname();
public:
void get();
void Delete();
string search();
};
private:vector<string> Names_Lastnames(); and at first i got some names from another function and put them in vector<string> Names_Lastnames()
void nameAndLastname::get()
{
int SizeOFNames;
cout<<"enter number of the names and last names";
cin>>SizeOFNames;
vector<string> Names_Lastnames(SizeOFNames);
ifstream inFile;
ofstream outFile;
string fileName,Line;
cout<<"whats the file name?:";
cin>>fileName;
inFile.open(fileName);
getline(inFile,Line);
cout<<"the first line of the file is:"<<endl;
cout<<Line<<endl;
cout<<"outputfilename?"<<endl;
cin>>fileName;
outFile.open(fileName);
outFile<<Line<<endl;
cout<<"now enter the names and last names";
for (int i=0; i<=SizeOFNames; i++) {
getline(cin,Names_Lastnames[i]);
outFile<<Names_Lastnames[i]<<endl;
}
inFile.close();
outFile.close();
}
and now i want to delete one of the names that user want to delete and i write this
void nameAndLastname::Delete(){
string rname;
cin>>rname;
auto itr = find(Names_Lastnames.begin(), Names_Lastnames.end(), rname);
if (itr != Names_Lastnames.end()) Names_Lastnames.erase(itr);
//error~>Reference to non-static member function must be called; did you mean to call it with no arguments?
//Use of undeclared identifier 'Names_Lastnames'
}
but i have this error "Reference to non-static member function must be called" .
i want to know how can i access to my vector from class named class nameAndLastname with reference
You have declared Names_Lastnames as a function that takes no parameters and returns a vector<string>.
(You did not put anything into it - if it looks like you did, you put your names into a vector with the same name.)
Remove the parentheses to make it a vector<string>.
Like this
class nameAndLastname
{
private:
vector<string> Names_Lastname; // <--- no ()
public:
void get();
void Delete();
string search();
};
void nameAndLastname::get()
{
int SizeOFNames;
cout<<"enter number of the names and last names";
cin>>SizeOFNames;
Names_Lastname.resize(SizeOFNames); // <--- resize class vector
...
}
void nameAndLastname::Delete(){
string rname;
cin>>rname;
auto itr = find(Names_Lastname.begin(), Names_Lastname.end(), rname);
if (itr != Names_Lastname.end())
Names_Lastname.erase(itr);
}
As is common for newbies you had multiple mistakes and misunderstandings ganging up on you.
This version declares the vector (correctly without ()) in the class where all methods can access it, and resizes that vector (instead of redeclaring it) in the get method
void nameAndLastname::get()
{
//...
vector<string> Names_Lastnames(SizeOFNames);
//..
} // the scope of Names_Lastnames ends here.
It seems like, you are referring a member variable with a similar name:Names_Lastname. If yes, correct it. Then if Names_Lastname is the variable, it is declared like a function in the class body. The parenthesis is not required. Hope you will try and repost the question if required.
I have the following parser class that works in Visual C++
class Parser
{
private:
const char* filename;
std::ifstream filestream;
std::vector<std::string> tokens;
unsigned int linect;
public:
Parser(const char* filename);
bool readline();
std::string getstrtoken(unsigned int i) const { return tokens[i]; }
int getinttoken(unsigned int i) const { return atoi(tokens[i].c_str()); }
};
Parser::Parser(const char* filename) :
filename(filename),
linect(0)
{
filestream = ifstream(filename); // OK in VC++, not with GCC?
}
bool Parser::readline()
{
std::string line;
getline(filestream, line);
std::stringstream ss(line);
std::string token;
tokens.clear();
while(getline(ss, token, ' ')){ if(token != "") tokens.push_back(token); }
linect++;
return (filestream != NULL);
}
But when I try to compile it with GCC 4.8.2, I get errors saying that I cannot assign to filestream. From what I read elsewhere on this site, you can do
std::ifstream filestream(filename);
but you cannot do
std::ifstream filestream;
filestream = ifstream(filename);
which is essentially what I need to do if I want to declare filestream as a member of the Parser class and initialize it in the constructor.
I would like to have the file stream kept within the Parser class so that those who use the parser don't need to declare and keep track of it. It seems to me that this should be self-contained in the Parser class since its internal methods (e.g. readline()) are the only ones that use it.
Is there a way to achieve this that works with both platforms?
Thanks.
edit: My fix was to explicitly call the open() method of ifstream. My parser class constructor now looks like:
Parser::Parser(const char* filename) :
filename(filename),
linect(0)
{
filestream.open(filename);
// Do some checking to make sure the file exists, etc.
}
You can't, since std::ifstream has deleted copy constructor and copy assignment. You may get around by doing
filestream.swap(ifstream(filename)).
The fact that it compiles on visual studio is mostly because it gets inlined into either move assignment or move constructor(I'm not so good to tell you which exactly). If you try
std::ifstream myF;
filestream = myF;
it won't compile.
However you may try to do the move I wrote, or you can just call .open(http://en.cppreference.com/w/cpp/io/basic_ifstream/open)
I think a better solution would be for you to:
Construct a ifstream first.
Construct a Parser using the ifstream object.
Change Parser to store a reference to an istream object. This allows you the flexibility of being able parse the contents of a file, stdin, and a string.
class Parser
{
private:
std::istream& str;
std::vector<std::string> tokens;
unsigned int linect;
public:
Parser(std::istream& s) : str(s) ... {}
...
};
std::ifstream don't have a copy constructor, probably one of the many extensions of VC++. Correct code is:
Parser::Parser(const char* filename) :
filename(filename),
linect(0),
filestream(filename)
{
}
Please take note of member variable and parameter filename. Use this-> or change name (recommended, normally prefix is used for member variables _ or m_)
I'm trying to parse a file which is in Key<whitespace>Value format. I'm reading the file lines in an std::istringstream object, and I'm extracting a Key string from it. I want to avoid accidentally changing the value of this Key string by making it const.
My best attempt was initializing a temporary VariableKey object, and then making a constant one out of it.
std::ifstream FileStream(FileLocation);
std::string FileLine;
while (std::getline(FileStream, FileLine))
{
std::istringstream iss(FileLine);
std::string VariableKey;
iss >> VariableKey;
const std::string Key(std::move(VariableKey));
// ...
// A very long and complex parsing algorithm
// which uses `Key` in a lot of places.
// ...
}
How do I directly initialize a constant Key string object?
It's arguably better to separate file I/O from processing, and instead of creating a const Key inside the same function - call a line-processing function that takes a const std::string& key parameter.
That said, if you want to continue with your current model, you can simply use:
const std::string& Key = VariableKey;
There's no need to copy or move anything anywhere. Only const std::string members functions will be accessible via Key.
You can avoid the "scratch" variable by extracting the input into a function:
std::string get_string(std::istream& is)
{
std::string s;
is >> s;
return s;
}
// ...
while (std::getline(FileStream, FileLine))
{
std::istringstream iss(FileLine);
const std::string& Key = get_string(iss);
// ...
(Binding the function's result to a const reference extends its lifetime.)
I have the following parser class that works in Visual C++
class Parser
{
private:
const char* filename;
std::ifstream filestream;
std::vector<std::string> tokens;
unsigned int linect;
public:
Parser(const char* filename);
bool readline();
std::string getstrtoken(unsigned int i) const { return tokens[i]; }
int getinttoken(unsigned int i) const { return atoi(tokens[i].c_str()); }
};
Parser::Parser(const char* filename) :
filename(filename),
linect(0)
{
filestream = ifstream(filename); // OK in VC++, not with GCC?
}
bool Parser::readline()
{
std::string line;
getline(filestream, line);
std::stringstream ss(line);
std::string token;
tokens.clear();
while(getline(ss, token, ' ')){ if(token != "") tokens.push_back(token); }
linect++;
return (filestream != NULL);
}
But when I try to compile it with GCC 4.8.2, I get errors saying that I cannot assign to filestream. From what I read elsewhere on this site, you can do
std::ifstream filestream(filename);
but you cannot do
std::ifstream filestream;
filestream = ifstream(filename);
which is essentially what I need to do if I want to declare filestream as a member of the Parser class and initialize it in the constructor.
I would like to have the file stream kept within the Parser class so that those who use the parser don't need to declare and keep track of it. It seems to me that this should be self-contained in the Parser class since its internal methods (e.g. readline()) are the only ones that use it.
Is there a way to achieve this that works with both platforms?
Thanks.
edit: My fix was to explicitly call the open() method of ifstream. My parser class constructor now looks like:
Parser::Parser(const char* filename) :
filename(filename),
linect(0)
{
filestream.open(filename);
// Do some checking to make sure the file exists, etc.
}
You can't, since std::ifstream has deleted copy constructor and copy assignment. You may get around by doing
filestream.swap(ifstream(filename)).
The fact that it compiles on visual studio is mostly because it gets inlined into either move assignment or move constructor(I'm not so good to tell you which exactly). If you try
std::ifstream myF;
filestream = myF;
it won't compile.
However you may try to do the move I wrote, or you can just call .open(http://en.cppreference.com/w/cpp/io/basic_ifstream/open)
I think a better solution would be for you to:
Construct a ifstream first.
Construct a Parser using the ifstream object.
Change Parser to store a reference to an istream object. This allows you the flexibility of being able parse the contents of a file, stdin, and a string.
class Parser
{
private:
std::istream& str;
std::vector<std::string> tokens;
unsigned int linect;
public:
Parser(std::istream& s) : str(s) ... {}
...
};
std::ifstream don't have a copy constructor, probably one of the many extensions of VC++. Correct code is:
Parser::Parser(const char* filename) :
filename(filename),
linect(0),
filestream(filename)
{
}
Please take note of member variable and parameter filename. Use this-> or change name (recommended, normally prefix is used for member variables _ or m_)
My code is already working, seen here: http://pastebin.com/mekKRQkG
Right now, my functions work but utilizing information that I've declared globally, I guess, and I want to convert them so that they are in the format as seen on lines 11-15, but I'm unsure of how to convert them to do so. Simply put, I'm trying to convert my function of
"void add_county_election_file"
to be in the format of
"void add_county_election_file(const string, const vector &, const vector &, const vector &, const vector &)"
and I have no idea where to begin or how to even start.
Could someone please help me out and show me how I'd do this for the first function, so I can implement it across the board?
Thanks guys!
Your function declaration should look something like this:
void add_county_election_file(const string, vector<int>&, vector<string>..);
Make sure that your argument list for the vector template is correct(that's the type you put between <>)
Then match the implementation of you function to the declaration:
void add_county_election_file(const string, vector<int>&, vector<string>..){...}
Now call your function with apppropriate arguemtns in main:
string s;
vector<int> arg;
vector<string> sv;
void someFunction (s, arg, sv ...);
I think you are doing correct as the function you have declared
void add_county_election_file(const string, vector<int>&, vector<int>&,..);
so you just have to call the above function with the required arguments, as right now you are not passing the argument and your current definition doesn't accepts any arguments.
And as a good practice, in your int main() function you can use switch rather than going for if else.
Store your variables and functions in a class, overload operators and create functions to access these variables.
Declare all variables in int main() and set parameters to be passed into each function e.g.
void print_results() is modified to become
void print_results(std::vector<int> vec, int nCount, etc..)
Similar to the first one, create a struct to hold all data members, then pass the struct(by ref) into each function.
struct CountryTracker
{
std::vector<int> ID;
std::string name;
//etc...
}
`void print_results(CountryTracker& Obj) //pass single struct into functions`
The OOP way to do this is to create a class called perhaps ElectionInfo, where:
These would be its member fields:
vector <string> countyNameVector;
vector <int> countyNCount;
vector <int> countyFCount;
vector <int> countyOCount;
int NCount;
int FCount;
int OCount;
int NTotal;
int FTotal;
int OTotal;
and these would be its member functions:
void add_county_election_file(const string);
void search_county(const string);
void print_results();
This way you don't have to pass the references to the vectors around at all, instead you can just do:
ElectionInfo an_elect_info;
char selection = get_menu_choice();
// some if-statements to decide which of the following to call:
an_elect_info.add_county_election_file(county_name);
an_elect_info.search_county(county_name);
an_elect_info.print_results();
But if you'd prefer to stay with the current functional approach:
Declare and initialize the following inside your main method:
vector <string> countyNameVector;
vector <int> countyNCount;
vector <int> countyFCount;
vector <int> countyOCount;
int NCount;
int FCount;
int OCount;
int NTotal;
int FTotal;
int OTotal;
The syntax for the commented out function declarations should be tweaked to look like this:
void add_county_election_file(const string, vector<string>&, vector<int>&, vector<int&, vector<int>&);
(Of course, the definition should follow suit)
You would invoke it like this:
add_county_election_file(countyname, countyNameVector, countyNCount, countyFCount, countyOCount);
Objects are automatically passed-by-reference.
The basic process of refactoring should at the first step involve only code grouping and placement and should only minimally involve writing new logic. Using this as a principle you can go about modifying the code in the following way at first.
string ReadInputString(const char* title)
{
string s
cout << title;
cin >> s;
}
void add_county_election_file(const std::string& filename
, std::vector<string>& countyNameVector
, std::vector<int>& countyNCount
, std::vector<int>& countyFCount
, std::vector<int>& countyOCount
)
{
int NCount = 0;
int FCount = 0;
int OCount = 0;
int NTotal = 0;
int FTotal = 0;
int OTotal = 0;
char vote;
std::ifstream input((filename).c_str());
string countyName;
if(input.is_open())
{
input >> countyName;
countyNameVector.push_back(countyName);
while(input >> vote)
{
if(vote == 'N' || vote == 'n')
{
NCount = NCount + 1;
}
else if(vote == 'F' || vote == 'f')
{
FCount = FCount + 1;
}
else
{
OCount = OCount + 1;
}
}
countyNCount.push_back(NCount);
countyFCount.push_back(FCount);
countyOCount.push_back(OCount);
}
cout << countyName << endl;
}
void add_county_election_file()
{
string fn = ReadInputString("Enter the county file to process: ");
add_county_election_file(fn,g_countyNameVector,g_countyNCount,g_countyFCount,g_countyOCount);
}
As you can see I have just extracted your code and moved them to individual functions and changed names to make some significance. Like in the function ReadInputString - the line "cin >> s" was originally "cin >> filename". The abstract name "s" is to signify that the ReadInputString has no knowledge or doesn't care what the semantic meaning of the string it is reading from console.
In order to not change your main function - I have added a overloaded add_county_election_file that calls one function followed by another. The idea is that you should keep something unchanged and change others (for good) and then alternate if need be.
And I have changed names of your global variable to differentiate them from the local variable using "g_" - the point is that "g_" should only be found at very few places in your code.