I am trying to read a list of words from a file in C++. However, the last word is read twice. I cannot understand why it is so. Can someone help me out?
int main () {
ifstream fin, finn;
vector<string> vin;
vector<string> typo;
string word;
fin.open("F:\\coursework\\pz\\gattaca\\breathanalyzer\\file.in");
if (!fin.is_open())
cout<<"Not open\n";
while (fin) {
fin >> word;
cout<<word<<endl;
vin.push_back(word);
}
fin.close();
}
Your loop condition is off by one:
while (fin >> word) {
cout<<word<<endl;
vin.push_back(word);
}
You need to do:
while((fin >> word).good()) {
vin.push_back(word);
}
Because fin >> word fails and you don't check it.
It's not read twice. It's simply the old value, since fin >> word fails.
Use
while(fin >> word)
{
...
}
instead.
It tries to read and stops loop if it fails.
Check these..
How do you read a word in from a file in C++?
http://www.bgsu.edu/departments/compsci/docs/read.html
http://answers.yahoo.com/question/index?qid=20081216024044AAKidaX
Related
I want to make text file, filling him string by string, until empty string. But, somehow I have infinite input, what conidition need I make to escape infinite loop?
Here is my code:
fstream f;
f.open("text1.txt", ios::out);
bool flag = false;
while (!flag) {
char buf[50];
cin >> buf;
if (strlen(buf)!=0 )
f<<buf<<endl;
else {
f.close();
flag = true;
}
}
With cin >> buf you are reading one word at a time. It's easier to use std::getline instead:
fstream f;
f.open("text1.txt", ios::out);
bool flag = false;
while (!flag) {
string str;
getline(cin, str);
if (cin && !str.empty())
f<<str<<endl;
else {
f.close();
flag = true;
}
}
If you are forced to use fixed buffer, you need to search for \n\n occurrence in a data. \n is a new line symbol in C++.
You need to iterate while loop until end of file.
fstream f;
f.open("text1.txt", ios::out);
char buf[50];
while (cin >> buf) // it becomes false when end of file reach. You can test it from keyboard by Ctrl+Z and then Enter
{
f<<buf<<endl;
}
f.close();
I am working on reading in from a file and parsing through data from command line argument for homework. And I ran in a wall and I do not know what's the problem, and I hope I could get some advice on what I am missing.
The data file is composed thusly; on the first line, it has number of total lines. For each line after that, it is a line of string separated by | character. I need the '|' character because I want to split my string into substrings.
Here is an example of input file.
3
league of legends|Teemo|Master Yi|Vayne
apple|samsung|smart phone|smart watch
overwatch|d.va|junkrat|Reinhart
Here is my code.
int main( int argc, char* const argv[] )
{
//change string to char* so I can check through each char to see if the
//thing I read in is '|' character.
String Data = (argv[1]);
ifstream fin (Data.c_str());
//check whether the file is open.
if ( !fin.is_open() )
{
cout << "Could not open file" << endl;
}
else
{
int dataLines;
char dataBuffer[100];
//The first integer I read in will be how many lines I will loop through
fin >> dataLines;
//ignore the new line character and do not include it in the count of
//dataLines.
fin.ignore();
//use noskipws so I can recognize whitespaces.
fin >> noskipws >> dataBuffer;
//TEST CODE: COMMENTED OUT FOR NOW.
//cout<<dataBuffer<<endl;
//loop for the number of lines
for(int i = 0; i < dataLines; i++)
{
fin.getline(dataBuffer, 100);
//print the buffer for checking
cout<<dataBuffer<<endl;
}
}
//close the file.
fin.close();
return 0;
}
The result is supposed to look like this.
league of legends|Teemo|Master Yi|Vayne
apple|samsung|smart phone|smart watch
overwatch|d.va|junkrat|Reinhart
The actual result looks like this
of legends|Teemo|Master Yi|Vayne
apple|samsung|smart phone|smart watch
overwatch|d.va|junkrat|Reinhart
The first word that I read in from buffer is gone. "league" is the one that is missing, and I tried to see what the problem is by inserting the test code at the location specified in my code. With the given test code, my output is
league
of legends|Teemo|Master Yi|Vayne
apple|samsung|smart phone|smart watch
overwatch|d.va|junkrat|Reinhart
So the problem is that between reading in the file with noskipws and the forloop that loops over dataLine. Before the forloop my buffer is league. Yet once I enter the loop it is passed that and goes straight to of.
What am I missing here? What could be a possible solution?
Main problem:
fin >> noskipws >> dataBuffer;
Does two things. 1. >> noskipws turns off automatically skipping whitespace, unnecessary because of how OP is reading the stream. 2. >> dataBuffer reads the first word from the stream, in this case consuming the word "league"
Solution: Don't do this.
Other problems:
fin.ignore();
will ignore exactly one character. But what if someone left a nigh-invisible space after the count? Instead use
fin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
to ensure the rest of the line is consumed in its entirity.
char dataBuffer[100];
Why make yourself suffer? Instead use
std::string dataBuffer;
Recommendation:
Use std::stringstream and std::getline to tokenize the lines on '|'
std::stringstream stream(databuffer);
std::string token;
while (std::getline(stream, token, '|')
{
std::cout << token << ',';
}
You do not need the following line:
fin >> noskipws >> dataBuffer;
Tested with g++ 4.8.3 2 on RHEL 7.1
Thanks User 4581301. It reads in the data correctly and split with '|' character. Now I can work on storing the data into classes.
for anyone who may have same problem, this is the fixed up version of code.
int main( int argc, char* const argv[] )
{
String Data = (argv[1]);
ifstream fin (Data.c_str());
if ( !fin.is_open() )
{
cout << "Could not open file" << endl;
}
else
{
int dataLines;
char dataBuffer[100];
fin >> dataLines;
fin.ignore();
for(int i = 0; i < dataLines; i++)
{
while(fin.getline(dataBuffer, 100, '|'))
{
cout<<dataBuffer<<endl;// check to see if it reads in correctly.
}
}
}
fin.close();
return 0;
}
As the title says I'm trying to read a file into two vectors.
The file would look like this
1 hello
2 how
3 are
4 you
Right now I have this, but it doesn't seem to work
int number;
string word;
std::vector<int> first;
std::vector<string> second;
ifstream inFile(File);
if (inFile.is_open()) {
while (inFile >> number >> word) {
first.push_back(number);
second.push_back(word);
}
}
Change the type of number to int.
Also the is_open() is superfluous (unless you have an else statement that handles the case when the file can't be opened) as the while loop will fail anyway if the file cannot be opened
you could use the atoi() function i believe in the header of the std library.
it will convert an ascii string to and integer. so...
#include<string>
string number, word;
std::vector<int> first;
std::vector<string> second;
ifstream inFile(File);
if (inFile.is_open()) {
while (inFile >> number >> word) {
first.push_back(atoi(number));
second.push_back(word);
}
}
You may need to check to make sure that atoi() did not fail before you push onto the vector but this may work for your situation.
Good Luck
EDIT: based on the comment below stating that atoi() may be a bad choice i will amend my answer. See this link. It's accepted answer recommends using std::stoi()
so to amend my answer...
#include<string>
string number, word;
std::vector<int> first;
std::vector<string> second;
ifstream inFile(File);
if (inFile.is_open()) {
while (inFile >> number >> word) {
first.push_back(std::stoi(number));//changed this line
second.push_back(word);
}
}
I want to read in scores from a txt file. The scores are going into a struct.
struct playerScore
{
char name[32];
int score, difficulty;
float time;
};
the text file looks like this
Seth 26.255 40 7
as one line, where each item is followed by a tab. (Name\t time\t score\t difficulty\n)
When I begin to read in the text, I don't know how to tell the program when to stop. The scores file could be any number of lines or score entries. This is what I have attempted.
hs.open("scores.txt", ios_base::in);
hs.seekg(0, hs.beg);
if (hs.is_open())
{
int currpos = 0;
while (int(hs.tellg()) != int(hs.end));
{
hs>> inScore.name;
hs >> inScore.time;
hs >> inScore.score;
hs >> inScore.difficulty;
hs.ignore(INT_MAX, '\n');
AllScores.push_back(inScore);
currpos = (int)hs.tellg();
}
}
I'm trying to make a loop that will read in a line of code into a temp struct for the data, then push that struct into a vector of structs. Then update the currpos variable with the current location of the input pointer. However, the loop just gets stuck on the condition and freezes.
There are a multitude of ways to do this, but the following is likely what you're looking for. Declare a free-operator for extracting a single-line definition of a player-score:
std::istream& operator >>(std::istream& inf, playerScore& ps)
{
// read a single line.
std::string line;
if (std::getline(inf, line))
{
// use a string stream to parse line by line.
std::istringstream iss(line);
if (!(iss.getline(ps.name, sizeof(ps.name)/sizeof(*ps.name), '\t') &&
(iss >> ps.time >> ps.score >> ps.difficulty)))
{
// fails to parse a full record. set the top-stream fail-bit.
inf.setstate(std::ios::failbit);
}
}
return inf;
}
With that, your read code can now do this:
std::istream_iterator<playerScore> hs_it(hs), hs_eof;
std::vector<playerScore> scores(hs_it, hs_eof);
I dont think that you can just >> from your file. Do you think it will take everything till \t? :)
You can try to take for example token with strtok()
I guess it can use '\t' to split string and take for each variable via this function needed part of string
In case if it strtok() doesnt work that way i guess you can just copy till '\t' in sub-loop
You can do like this
playerScore s1;
fstream file;
file.open("scores.txt", ios::in | ios::out);
while(!file.eof()) //For end of while loop
{
file.read(s1, sizeof(playerScore));//read data in one structure.
AllScores.push_back(s1);
}
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...