I'm using getline to get input and I want to store every line input to an array so that I can recall specific array content for further processing. Any ideas? Thanks in advance
string line;
while (true) {
getline(cin, line);
if (line.empty()) {
break;
}
// code
}
EDIT/ADD
Does anyone know why I cannot use cin before the while loop? When for example I put
cin >> var1; before the loop it won't go inside the loop at all!
ANSWERING MYSELF
I found this that solves it!
The simplest solution is to use vector container:
std::vector<std::string> arr;
and then:
arr.push_back(line);
Use vector<string> vec;
Better way to read from file would be as below
string line;
while (getline(cin, line)) {
if (line.empty()) {
break;
}
vec.push_back(line);
// code
}
once EOF is reached loop will break...
Related
I am a beginner in C++ and just started learning vectors.
Can someone suggest me a better way to take in values for a vector ? Or is this method good enough ? Thanks in advance :')
vector<int> vec;
int temp;
bool condition=true;
while(condition){
cin >> temp;
vec.push_back(temp);
if(cin.get()=='\n') condition = false;
}
A more C++ish way would probably be to use std::getline to read the line into a std::string. Then put that string into an std::istringstream, from which you then use std::istream_iterator to fill the vector.
Perhaps something like
// Somewhere to put the text we read
std::string line;
// Read the actual text
std::getline(std::cin, line);
// A stream to parse the integers from
std::istringstream iss(line);
// Define the vector, initializing it from stream iterators
// This is a more succinct version of a loop which extracts (with `>>`)
// integers and pushes them into the vector
std::vector<int> vec(std::istream_iterator<int>(iss), std::istream_iterator<int>());
After this vec is filled with integers from a single line of input.
May be you can use C++ stream functions to check whether input stream is good enough to take input from,
while(cin.good())
{
int i;
cin >> i;
vec.push_back(i);
}
That's it!
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].
I would like some help understanding how to deal with isstringstream objects.
I am trying to tokenize each line of a file so I can re-write it in another format after checking certain data values in the tokens. I am loading each line in a tokenVector and iterating through the vector. My code works, but what concerns me is that I have to instantiate a isstringstrem object for each iteration otherwise it does not work. That does not feel right. Her is my code:
std::string line;//each file line
std::ifstream myFile (info.txt.c_str());
if(myFile.is_open()){
getline(myFile, line);
std::vector<std::string> tokenVector;
//create a isstringstream object for tokenizing each line of the file
std::istringstream hasTokens(line);
while(hasTokens)
{
std::string substring;
if(! getline(hasTokens, substring,','))
break;
tokenVector.push_back(substring);
}
//look for some known header names for validation
if(!tokenVector.empty()){
if(!(tokenVector[0]=="Time")&&(tokenVector[1] == "Group")&&(tokenVector[2]=="Perception")&&(tokenVector[3] == "Sign")){
setErrorMesssage("Invalid Header in myFile");
return false;
}
tokenVector.clear();
}
//clear the isstringstream object
hasTokens.str(std::string());
//if header validates, do rest of file
while(myFile.good()){
getline(myFile , line);
//break line into tokens using istringstream
std::istringstream hasTokens(line);
//reload the vector of tokens for each line
while(hasTokens)
{
std::string substring;
if(! getline(hasTokens, substring,','))
break;
tokenVector.push_back(substring);
}
otherFileWritingFunction(tokenVector[0], tokenVector[2], tokenVector[4]);
tokenVector.clear();
hasTokens.str(std::string());
}//end while
}//end if is_open
This code works, but its not correct because I should only have to instantiate isstringstream once (I think). If I try "hasTokens.str(line)" for each iteration using just the original instantiation of hasTokens, as some example have suggested, it does not work, so I would really appreciate a suggestion.
Thanks
Nope, your worries are misplaced. Create a new stream object when you need it, and dispose of it when you're done. That's the spirit of C++. An object for each purpose, and a purpose for each object (misquoting Frank Herbert). There's nothing "expensive" about constructing a string stream that wouldn't also happen when you reassign the string data of an existing string stream.
Your code is very noisy and redundant, though. The standard idiom goes like this:
std::string line;
while (std::getline(infile, line))
{
std::istringstream iss(line);
std::string token;
while (iss >> token) { /* do stuff */ }
}
Compressed version (some would call this abuse):
for (std::string line; std::getline(infile, line); )
{
std::istringstream iss(line);
for (std::string token; iss >> token; ) { /* ... */ }
}
The second std::istringstream declaration has an entirely different scope and is being constructed in each iteration so hasTokens.str(std::string()); has no effect.
You could reuse the same object if you did hasTokens.str(line) in the while loop instead.
I am using the following loop to read an unknown number of lines from the console, but it is not working. After I have fed the input I keeping pressing enter but the loop does not stop.
vector<string> file;
string line;
while(getline(cin,line)
file.push_back(line);
Because getline will evaluate to true even if you push only enter.
You need to compare the read string to the empty string and break if true.
vector<string> file;
string line;
while(getline(cin,line))
{
if (line.empty())
break;
file.push_back(line);
}
Try:
vector<string> file;
string line;
while( getline(cin,line))
{
if( line.empty())
break;
file.push_back(line);
}
For getline is easy, as it is suggested by other answers:
string line;
while(getline(cin,line))
{
if (line.empty())
break;
file.push_back(line);
}
But to cin objects, I found a way to without the need for any breaking character. You have to use the same variable to cin all of the objects. After usage, you need to set it to a default exit value. Then check if your variable is the same after the next cin. Example:
string o;
while(true){
cin>>o;
if (o.compare("tmp")==0)
break;
// your normal code
o="tmp";
}
You should signal the end of file to your application. On Linux it is Ctrl-D, and it might be Ctrl-Z on some Microsoft systems
And your application should test of end of file condition using eof()
While reading a file (ifstream), is there any way to direct it to make a new line?
For instance, I would like for THIS to happen:
myfile>>array[1]>>array[2]>>endl;
Obviously, the "endl" just isn't allowed. Is there another way to do this?
Edit---thanks for the quick responses guys!
From a text file, I'm trying to store two strings from that file into arrays and then do the same with the next line (or until I desire, using a for loop)
Using strings is important to me as it will make my future program a lot more flexible.
Several options:
You can use ignore.
myfile >> array[1] >> array[2];
myfile.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
Or you can read each line into as string stream
std::string line;
std::getline(myfile,line);
std::stringstream stream(line);
stream >> array[1] >> array[2];
Please note: Array indexing starts at 0.
Use std::getline to read a line into a memory stream, then get the two strings from that.
while (cin)
{
string line;
getline(cin, line);
stringstream stream;
stream << line;
stream >> array[1]>>array[2];
}
Read your two items, then call myfile.ignore(8192, '\n')
I have no idea what this question means. Here's a simple way to read all the lines of a file into a vector of strings. It might be easier to do what you want to do if you do this first.
std::vector<std::string> lines;
std::string line;
while (std::getline(myFile, line))
lines.push_back(line);
Now you can say lines[4] to get the fifth line, or lines.size() to find out how many lines there were.
This should work:
stringstream stream;
string sLine;
int iLine;
while (cin)
{
getline(cin, sLine);
stream << sLine;
stream >> data[iLine][0] >> data[iLine][1];
}
Customized version of an earlier answer.