Error Using std::vector<std::string> myString - c++

Hi it's a little bit hard for me to understand what the compiler is saying:
[BCC32 Error] frmNew.cpp(333): E2285 Could not find a match for 'std::getline<_Elem,_Traits,_Alloc>(ifstream,std::vectorstd::string,std::allocator<std::string >)'
Full parser context
frmNew.cpp(303): parsing: void _fastcall TFrmNewPeta::showDefaultRute()
I'm using std::vector<std::string>mystring to store my strings file, but
while (std::getline(ifs_Awal, mystring)) throws the error.
This is my complete code:
void __fastcall TFrmNewPeta::showDefaultRute()
{
std::string mystring;
std::ifstream ifs_Awal;
int tempIndexAwal = 0;
ifs_Awal.open("DefaultDataAwal");
while (std::getline(ifs_Awal, mystring)) {++tempIndexAwal;}
std::vector<std::string> mystring(tempIndexAwal);
while (std::getline(ifs_Awal, mystring)) // error
{
mystring.push_back(mystring); // error
}
ifs_Awal.close();
}
I'm using C++ Builder 2010.
In many tutorials they prefer to using std::vector to store a string to a dynamic array. So I did the same thing, but the error occurred when I tried using std::vector<>.

second parameter of std::getline could be std::string but not std::vector<std::string>. It's quite clear as error message shows.
update
std::vector<std::string> mystring(tempIndexAwal);
to:
std::string mystring;
You do not post how you declare myline, I suppose it's std::vector<std::string>.

billz and tomi rights your passing wrong argument so I change your code. should be
void __fastcall TFrmNewPeta::showDefaultRute() {
std::string lines;
std::ifstream ifs_Awal;
int tempIndexAwal = 0;
ifs_Awal.open("DefaultDataAwal");
/*get the strings and counting the lines*/
while(std::getline(ifs_Awal,lines)){++tempIndexAwal;}
std::vector<std::string> mystring(tempIndexAwal);
while(std::getline(ifs_Awal,lines)) //put your 'lines' here
{
mystring.push_back(lines); // theres no error again :)
}
ifs_Awal.close();
}

Your passing wrong argument to getline.
mystring is not a std::string as it should be, but a std::vector. Thus line
std::getline(ifs_Awal,mystring) causes an error since the second argument is not std::string.
Also, line
myline.push_back(mystring)
does not work because myline is probably a vector of string, and you try to push an element of vector<string> to it.
So, as suggested already, changing myline to std::string is the answer.

Related

Reading from CSV and storing in a Vector

Consider I have the following csv file:
10.0.0.26
10.0.0.30
10.0.0.34
10.0.0.38
...
...
Consider I have a vector:
std::vector<L3Address> destAddresses;
I want a piece of code the will read the above csv file till the very last address and store each of that address in the above vector.
std::ifstream data("data.csv");
while(//till the end of file){
//read from csv
//write to vector
}
I have tried the following:
std::ifstream data("data.csv");
while(std::getline(data,std::string value){
destAddresses.push_back(value);
}
But this isn't working somehow.
Let's go look at the documentation of L3Address (note 1). Here we can see a function bool L3Address::tryParse(const char * str), which will try to interpret a C-string as an address, and tell you if it succeded.
std::ifstream data("data.csv");
std::string line;
while (std::getline(data, line) {
L3Address addr;
if (addr.tryParse(line.c_str())) {
destAddresses.push_back(addr);
}
else
{
// TODO: handle malformed address
}
}
Note 1: The tooling that generated this documentation is formatting it very badly, so it is excusable that you couldn't get here yourself.
Your example doesn't seem to compile. Besides the missing parenthesis the getline function you are using requires a variable reference as the second argument. Hence, you should fix your code by defining the value variable before use.
Additionally to construct the L3Address you can benefit from the constructor accepting const char*.
std::ifstream data("data.csv");
std::string value;
while(std::getline(data,value))
{
destAddresses.emplace_back(value.c_str());
}

ifstream as class member [duplicate]

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_)

Taking a pointer passed to a function, then putting it into another function

I'm writing a password generator that can read and write to a file. I have a function that takes an empty string, then modifies it. The function would look something like this:
void password_create(string *passwd)
Inside that function, I call a write function that writes out to a file with the password, it would look something like this:
void write_out(string file_name, string *passwd)
Then the total code looks like this:
void password_create(string *passwd) {
*passwd = "something";
write_out(&passwd);
}
The compile complains that I can't convert std::basic_string<char>** to std::basic_string<char>*.
I'm relatively new to C++, and this program is just to help me get acquainted with the language. I can pass passwd into the write_out() function without a * or & to denote a pointer or reference just fine. It won't give me an error if I type:
*passwd = "something";
write_out(passwd);
It doesn't affect the overall completion of the program, I was just curious as to why I get that error.
The variable passwd is already a pointer to a std::string, therefore taking the address of it via &passwd will give you something of type std::string** - so if write_out expects a parameter of type std::string* but receives the std::string** then the compiler will give you an error as you saw. So don't use & when passing passwd to write_out():
write_out(passwd);
But all that aside, you should just pass the std::string variables by reference rather than by pointer, as mentioned in the comments and the other answer.
Don't use pointers, in c++ prefer using pass by reference:
void password_create(std::string &passwd) {
passwrd = "something";
...
Then ensure that you create the string as you intend:
std::string myString;
password_create(myString);
That way you will have the memory you expect and you dont need to worry about pointer semantics.
No need to overcomplicate things. I dont see where pointers are needed in this case at all. Just make a function to generate a password and return it.
#include <string>
#include <fstream>
using namespace std;
string password_create() {
return "generated password";
}
void write_password_to_file(string file, string password) {
ofstream stream(file);
stream << password;
stream.close();
}
int main() {
auto password = password_create();
write_password_to_file("pathtofile.txt", password);
return 0;
}
As mentioned in the other answers you should actually take the std::string parameter by reference instead of a pointer.
Well assuming that the write_out() has some signature like
write_out(char* passwd);
or
write_out(const char* passwd);
you can pass std::string::operator[]():
void password_create(string *passwd) {
*passwd = "something";
write_out(&(*passwd)[0]);
}

no instance of overloaded function

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 );
}

How to have a file stream as a class member

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_)