Error using getline with ifstream - C++ - c++

I need help, I tried googling if I could find a similar problem but the solutions for others didn't work for me.
I'm trying to use getline() to read the file I've opened but it's not accepting the parameters I've given it.
What I'm trying to accomplish at this time (not the entire program) is to open a .csv file and determine how many elements it has inside by using getline() and using the , character as the delimiter. My loop has an index which I could just add 1 to it so that I can get the total number of elements inside the file.
The reason I'm doing this is because I intend to use it for a project at school but so far I've gotten stuck at the getline() error:
no matching function for call to 'std::basic_ifstream::getline(std::string&, int, const char [2])'
My code is here:
void readfile(string a)
{
int i = 0;
ifstream infile;
infile.open(a.c_str());
string temp;
//count how many elements are inside
if(infile.is_open())
{
while(infile.good())
{
infile.getline(temp, 256, ",");
i++;
}
infile.close();
i+=1;
}
else
{
cout<<"Error opening file.";
}
cout<<i;
}

Use the free getline() function:
std::string line;
getline(infile, line);

In addition to the answer by #UlrichEckhardt, I'd handle delimiters like this:
if(infile.is_open())
{
string temp;
// std::getline(std;:istream&, std::string) used below
while(getline(infile, temp)) {
std::stringstream stream(str);
std::string token;
while (std::getline(stream, token, ','))
if (!token.empty()) // it's up to you to decide how to handle empty tokens
i++;
}
}
Note the ','. If it were ".", this would be considered a string by the compiler, which is exactly what you're seeing in the error message: a '\0' is appended automatically, thus producing a char[2].

Related

fstream reading error (only reading first line)

I want to read a file with std::getline. but reads first line only
string FileReader::readLine() {
string line;
string read;
ifstream ReadFile;
ReadFile.open("input.txt");
if (ReadFile.is_open()) {
getline(ReadFile, line);
//ReadFile.close();
}
return line;
}
this is my method. I call this method several time but always reads first line how can i do to read next lines?
You need to change your program flow.
Don't return a string. Use the line within the loop to do whatever it is you want. Ensuring that you either don't leave the method or return to it.
You can't keep coming back to a function like this, as it will keep reading from the beginning.
void FileReader::readLine() {
string line;
string read;
ifstream ReadFile;
ReadFile.open("input.txt");
if (ReadFile.is_open()) {
while(getline(ReadFile, line))
{
//do what you want with that line, but return program flow here.
}
ReadFile.close();
}
}

using getline() while separating comma didn't work

I have read a CSV file that has line ending character as '\r', the reading operation done successfully, but the problem started when i pass the read line in to the while(getline(ss,arr2,',')) for separating comma..it does work properly for the first line but all the next iterations are empty(i.e)it has been failing to separate the comma in the string.
int main()
{
cout<<"Enter the file path :";
string filename;
cin>>filename;
ifstream file;
vector<string>arr;
string line,var;
stringstream content;
file.open(filename.c_str(),ios::in );
line.assign((std::istreambuf_iterator<char>(file)),
std::istreambuf_iterator<char>());
file.close();
string arr2;
stringstream ss;
content<<line;
//sqlite3 *db;int rc;sqlite3_stmt * stmt;
int i=0;
while (getline(content,var,'\r'))
{
ss.str(var);//for each read the ss contains single line which i could print it out.
cout<<ss.str()<<endl;
while(getline(ss,arr2,','))//here the first line is neatly separated and pushed into vector but it fail to separate second and further lines i was really puzzled about this behaviour.
{
arr.push_back(arr2);
}
ss.str("");
var="";
arr2="";
for(int i=0;i<arr.size();i++)
{
cout<<arr[i]<<endl;
}
arr.clear();
}
getch();
}
what went wrong in the above...I see nothing right now:(
The stringstream::str method does not reset / clear the internal state of the stream. After the first line, the internal state of ss is EOF (ss.eof() returns true).
Either use a local variable inside the while loop:
while (getline(content,var,'\r'))
{
stringstream ss(var);
Or clear the stream before ss.str:
ss.clear();
ss.str(var);

Parsing a string of numbers into an integer array

I have a text file with numbers ranging from 0-255 separated by commas. I want to be able to store each of these numbers into an integer array. An example of what the text file might contain is;
"32,51,45,12,5,2,7,2,9,233,132,175,143,33..." etc
I have managed to get my program to store the data from the text file as a string and output them on the screen. What I need to do next is store the values of that string in an integer array, separating the numbers by the commas.
Here is the code I have written so far, which I am having problems getting it working;
int _tmain(int argc, _TCHAR* argv[])
{
string line;
ifstream myfile ("example.txt");
if (myfile.is_open())
{
while ( myfile.good() )
{
getline (myfile,line);
cout << line << endl;
}
myfile.close();
}
else cout << "Unable to open file";
//STRING CONVERSION
std::string str = line;
std::vector<int> vect;
std::stringstream ss(str);
int i = 0;
while (ss >> i)
{
vect.push_back(i);
if (ss.peek() == ',')
ss.ignore();
}
system("pause");
return 0;
It looks like your code for tokenizing your string is bit off. In particular you need to make sure you call atoi() on the string of your integer to get an integer. I'll focus on the parsing of the string though.
One thing you could use is C's strtok. I recommend this mainly because your case is rather simple, and this is probably the simplest way to go about it.
The code you'd look for is essentially this:
char* numStr = strtok(str.c_str(), ",");
while (numStr)
{
vect.push_back(atoi(numStr));
numStr = strtok(NULL, ",");
}
strtok() takes two arguments: a pointer to the C-style string (char*) you're tokenizing, and the string of delimiters (note that each character in the delimiter string is treated as its own delimiter).
I should mention that strtok is not thread-safe, and you also have to ensure that the string you extract from the file ends with a null character \0.
The answers to this question provide many alternatives to my solution. If you'd prefer to use std::stringstream then I suggest you look at the 5th answer on that page.
Regarding your trouble with PDBs, what is the exact error you're getting?

Read from a file with blank spaces in C++

I am reading from a file and passing the front of the array(pointer) back into my main function. The problem I am having is that it is not copying the blank spaces in between the words. For example Hello Hello comes out as HelloHello.
I started by using getLine instead and ran into the problems of size of the file. I set it to 500 because no files will be larger than 500, however most files will be below 500 and I am trying to get the exact size of the file.
Here is my code:
char infile()
{
const int SIZE=500;
char input[SIZE];
char fromFile;
int i=0;
ifstream readFile;
readFile .open("text.txt");
while(readFile>>fromFile)
{
input[i]=fromFile;
i++;
}
cout<<endl;
returnArray=new char[i];//memory leak need to solve later
for(int j=0;j<i;j++)
{
returnArray[j]=input[j];
cout<<returnArray[j];
}
cout<<endl;
}
return returnArray[0];
}
Depending on what your file format is, you may want to use ifstream::read() or ifstream::getline() instead.
operator >> will attempt to 'tokenize' or 'parse' the data stream as it is being read, using whitespace as separators between tokens. You're interested in getting the raw data from the file with whitespace intact, therefore you should avoid using it. If you want to read data in one line at a time, using linefeeds as separators, you should use getline(). Otherwise use read().
Use std::string, std::vector and std::getline and you can still return a char. That will solve your memory leak and skipping whitespace problem.
Example:
char infile()
{
std::ifstream readFile("text.txt");
std::vector<std::string> v;
std::string line;
while(std::getline(readFile, line))
{
v.push_back(line);
}
for(auto& s : v)
{
std::cout << s << std::endl;
}
return (v[0])[0];
}
You are asking it to read while delimiting where there is whitespace.
You can use getline() to preserve the whitespace.

Why is this IO operation looping infinitely?

I am trying to read from a text file and tokenize the input. I was getting a segmentation fault until I realized I forgot to close my ifstream. I added the close call and now it loops infinitely. I'm just trying to learn how to use strtok for now, that is why the code doesn't really look complete.
void loadInstructions(char* fileName)
{
ifstream input;
input.open(fileName);
while(!input.eof());
{
string line;
getline (input,line);
char * lineChar = &line[0];
//instruction cmd; //This will be used later to store instructions from the parse
char * token;
token = strtok (lineChar," ");
// just trying to get the line number for now
int lineNumber = atoi(token);
cout << lineNumber << "\n";
}
input.close();
}
input file:(one line)
5 +8 0 0 25
This while(input.good()); is probably not what you intended...
Use this:
string line;
while(getline (input,line))
{
If the getline() works then the loop is entered.
If you try and read past the EOF then it will fail and the loop will exit.
So this should word as expected.
Rather than using strtok() (which damages the string) and atoi() which is non portable.
Use std::stringstream
std::stringstream linestream(line);
int lineNumber;
linestream >> lineNumber; // reads a number from the line.
Don't explicitly close() the stream (unless you want to detect and correct for any problems). The file will be closed when the object goes out of scope at the end of the function.
You want to use eof() not good().
Avoid strtok. There are other ways to tokenize a string that do not require the called function to modify your string. The fact that it modifies the string it tokenizes could also be what causes the loop here.
But more likely, the good() member is not the right one. Try !input.eof() or similar, depending on what you need.
While you've already gotten some answers to the question you asked, perhaps it's worth answering some you should have about the code that you didn't ask:
void loadInstructions(char* fileName)
Since the function isn't going to modify the file name, you almost certainly want to change this to:
void loadInstructions(char const *fileName)
or
void loadInstructions(std::string const &fileName)
ifstream input;
input.open(fileName);
It's much cleaner to combine these:
ifstream input(fileName);
or (if you passed a string instead):
ifstream input(fileName.c_str());
while(!input.eof());
This has already been covered.
string line;
getline (input,line);
char * lineChar = &line[0];
//instruction cmd; //This will be used later to store instructions from the parse
char * token;
token = strtok (lineChar," ");
// just trying to get the line number for now
int lineNumber = atoi(token);
Most of this is just extraneous. You can just let atoi convert directly from the original input:
string line;
getline(input, line);
int lineNumber = atoi(line);
If you're going to tokenize more later, you can use strtol instead:
char *end_ptr;
int lineNumber = strtol(line, &end_ptr, 10);
This will set end_ptr to point just past the end of the part that strtol converted.
I'd also consider an alternative though: moving your code for reading and parsing a line into a class, and define operator>> to read those:
struct line {
int number;
operator int() { return number; }
};
std::istream &operator>>(std::istream &is, line &l) {
// Just for fun, we'll read the data in an alternative fashion.
// Instead of read a line into a buffer, then parse out the first number,
// we'll read a number from the stream, then ignore the rest of the line.
// I usually prefer the other way, but this is worth knowing as well.
is >> l.number;
// When you're ready to parse more, add the extra parsing code here.
is.ignore(std::numeric_limits<std::istream::pos_type>::max, '\n');
return is;
}
With this in place, we can print out the line numbers pretty easily:
std::copy(std::istream_iterator<line>(input),
std::istream_iterator<line>(),
std::ostream_iterator<int>(std::cout, "\n"));
input.close();
I'd usually just let the stream close automatically when it goes out of scope.