struct data
{
int record;
string fName;
string lName;
string phoneNum;
};
string line, lastname, firstname, phone;
vector<data> readContent()
{
inFile.open("data.txt");
vector<data> myData;
char recordstring[4];
data datas;
inFile.clear();
while(inFile >> recordstring)
{
int records;
records = atoi(recordstring);
datas.record = records;
getline(inFile, firstname, ' ');
datas.fName = firstname;
getline(inFile, lastname, ' ');
datas.lName = lastname;
getline(inFile, phone, '\n');
datas.phoneNum = phone;
myData.push_back(datas);
}
inFile.close();
return myData;
}
This is the input file (data.txt):
1000 q q 1
1001 w w 2
1002 e e 3
1003 r r 4
1004 t t 5
This is what the debugger shows for the first line in the file:
http://i.imgur.com/uRGeuvj.png
Can anyone see what is wrong with it?
It should be 1000 being the record, q for fname, q for lname and 1 for phonenum (for the first line). All I am doing is storing each line in an struct instance (data) and then store that into a vector to be used later.
If you want to read from a file word by word, then stay with >>. If you want to read it line by line then use std::getline, but don't mix these two in this manner.
Also note that you have:
declared char recordstring[4]
tried to initialize it using std::cin >> recordstring
tried to convert it to int using atoi
...while simple >> used to fill a variable of type int would do. Note that the size of recordstring is 4, which is big enough to hold 3 characters + null-terminating '\0'
Actually the whole reading could be simple as:
vector<data> myData;
data d;
while(inFile >> d.record >> d.fName >> d.lName >> d.phoneNum) {
myData.push_back(d);
}
inFile >> recordstring does not consume the trailing whitespace, so the first getline() call returns an empty string because the first character it consumes is the whitespace.
If the file format is fixed as shown, simply do following :-
while(inFile >> datas.record >> datas.fName >> datas.lName >> datas.phoneNum)
myData.push_back(datas);
Your logic seems to skip white space for recordstring
Related
I have read the data like the following
7
1 Jesse 20
1 Jess 12
1 Jess 18
3 Jess
3 Jesse
2 Jess
3 Jess
Here the 7 is the number of input lines and i have to read the space separated input in c++, How can i read those input where we don't know how to separate them. this line contains string and integers.
Here is one example, that uses operator>> and std::string:
int x;
std::string name;
int y;
int quantity;
std::cin >> quantity;
for (int i = 0; i < quantity; ++i)
{
std::cin >> x;
std::cin >> name;
std::cin >> y;
}
The above will work for all lines that have 3 fields, but not with the lines without the last field. So, we'll need to augment the algorithm:
std::string text_line;
for (i = 0; i < quantity; ++i)
{
std::getline(std::cin, text_line); // Read in the line of text
std::istringstream text_stream(text_line);
text_line >> x;
text_line >> name;
// The following statement will place the text_stream into an error state if
// there is no 3rd field, but the text_stream is not used anymore.
text_line >> y;
}
The root cause is that the missing 3rd field elements will cause the first example to be out of sync because it will read the 1st column of the next line for the 3rd field.
The second sample of code makes the correction by reading a line at a time. The input operations are restricted to the text line and will not go past the text line.
If I have a file containing 10 rows, where each row contain information about the following object,
class student
{
public:
string name;
int age;
int rollnum;
int year;
string father;
string mother;
string category;
string region;
char sex;
string branch;
int semester;
};
How can I read all the 10 objects information from a file? ( I am guessing I will have to take an array of 10 objects for this )
istream& operator >>(istream& in, student& val) {
return in >> name >> age >> rollnum >> year; // ...
}
Then you can do this:
for (string line; getline(infile, line); ) {
istringstream stream(line);
student person;
stream >> person;
}
Now person is being populated once per line. I do it this way rather than directly streaming from the file because this way is safer: if a line has the wrong number of tokens it won't misunderstand what the columns are, whereas without getline() you might naively parse 10 tokens of an 11 token line, then think that the 11th token on the line is the first token of the next record. Just a typical mistake that happens in beginner C++ text parsing code.
I have a file that is opened filled like this:
STRING
INT
INT
INT
filename.txt
STRING
INT
INT
INT
filename1.txt
etcetera
I have code that is supposed to read from the file, pull the string, the integers, and the file names. It is able to pull the string and the integers, but it won't pull the file name.
Here is the code:
while( !input.eof() )
{
string name;
int type = UNKNOWN;
int pages;
float ounces;
getline( input, name );
input >> type >> pages >> ounces;
getline(input, reviewFile); //reviewFile is a static string called in the header file
input.ignore(INT_MAX, '\n');
}
It should work if you put the ignore before the getline, to eat the newline after the ounces:
while( !input.eof() )
{
string name;
int type = UNKNOWN;
int pages;
float ounces;
getline( input, name );
input >> type >> pages >> ounces;
input.ignore(INT_MAX, '\n');
getline(input, reviewFile); //reviewFile is a static string called in the header file
}
The operator>> will read words, not taking end of line into account that much.
Therefore, I would write something like this (As Massa wrote in a comment):
input >> type >> pages >> ounces >> ws;
Also, please note that "eof" checks are suboptimal. Try to avoid them. Moreover, you do not check after the reads within the loop if there is anything more to read.
I'm new to C++ and I'm having a little trouble when it comes to reading lines of data from a text file. Let's say I have an unknown number of lines in a text file, with each line in the same format: int string double . The only thing that will be definite is a space will separate each piece of data on a given line. I'm using an array of structs to store the data. The code below works great except that it skips a line of input after each loop. I've tried inserting various ignore() statements and still can't get it to read each line, only every other line. If I rewrite some of the getline statements at the end, then the wrong data starts getting stored for the variables after the first loop.
Text file might look like this:
18 JIMMY 71.5
32 TOM 68.25
27 SARAH 61.4
//code
struct PersonInfo
{
int age;
string name;
double height;
};
//..... fstream inputFile; string input;
PersonInfo *people;
people = new PersonInfo[50];
int ix = 0;
getline(inputFile, input, ' ');
while(inputFile)
{
people[ix].age = atoi(input.c_str());
getline(inputFile, input, ' ');
people[ix].name = input;
getline(inputFile, input, ' ');
people[ix].height = atof(input.c_str());
ix++;
getline(inputFile, input, '\n');
getline(inputFile, input, ' ');
}
I'm sure there are more advanced ways to do this, but like I said I'm pretty new to C++ so if there are just some slight modifications to the code above, that would be great. Thanks!
You can do the file reading as follows:
int ix = 0;
int age = 0;
string name ="";
double height = 0.0;
ifstream inputFile.open(input.c_str()); //input is input file name
while (inputFile>> age >> name >> height)
{
PersonInfo p ={age, name, height};
people[ix++] = p;
}
You've made this whole code ridiculously complicated.
struct PersonInfo
{
int age;
string name;
double height;
};
std::vector<PersonInfo> people;
PersonInfo newPerson;
while(inputFile >> newPerson.age >> newPerson.name >> newPerson.height)
people.push_back(std::move(newPerson));
Your problem is because first your read each bit of data one at a time from the file, then a whole line from teh file, then each bit of data one at a time from the file again. Maybe what you intended was more like this?
std::string fullline;
while(std::getline(inputFile, fullline)) {
std::stringstream linestream(fullline);
std::getline(linestream, datawhatever);
....
}
By the way, more idiomatic code might look like more like this:
std::istream& operator>>(std::istream& inputFile, PersonInfo& newPerson)
{return inputFile >> newPerson.age >> newPerson.name >> newPerson.height;}
{ //inside a function
std::ifstream inputFile("filename.txt");
typedef std::istream_iterator<PersonInfo> iit;
std::vector<PersonInfo> people{iit(inputFile), iit()}; //read in
}
Proof it works here
I am having some trouble with my lab assignment for my CMPT class...
I am trying to read a text file that has two words and a string of numbers per line, and the file can be as long as anyone makes it.
An example is
Xiao Wang 135798642
Lucie Chan 122344566
Rich Morlan 123456789
Amir Khan 975312468
Pierre Guertin 533665789
Marie Tye 987654321
I have to make each line a separate "student", so I was thinking of using struct to do so, but I don't know how to do that as I need the first, last, and ID number to be separate.
struct Student{
string firstName;
string secondName;
string idNumber;
};
All of the tries done to read in each word separately have failed (ended up reading the whole line instead) and I am getting mildly frustrated.
With the help from #Sylence I have managed to read in each line separately. I am still confused with how to split the lines by the whitespace though. Is there a split function in ifstream?
Sylence, is 'parts' going to be an array? I saw you had indexes in []'s.
What exactly does the students.add( stud ) do?
My code so far is:
int getFileInfo()
{
Student stdnt;
ifstream stdntFile;
string fileName;
char buffer[256];
cout<<"Please enter the filename of the file";
cin>>filename;
stdntFile.open(fileName.c_str());
while(!stdFile.eof())
{
stdFile.getLine(buffer,100);
}
return 0;
}
This is my modified and final version of getFileInfo(), thank you Shahbaz, for the easy and quick way to read in the data.
void getFileInfo()
{
int failed=0;
ifstream fin;
string fileName;
vector<Student> students; // A place to store the list of students
Student s; // A place to store data of one student
cout<<"Please enter the filename of the student grades (ex. filename_1.txt)."<<endl;
do{
if(failed>=1)
cout<<"Please enter a correct filename."<<endl;
cin>>fileName;
fin.open(fileName.c_str());// Open the file
failed++;
}while(!fin.good());
while (fin >> s.firstName >> s.lastName >> s.stdNumber)
students.push_back(s);
fin.close();
cout<<students.max_size()<<endl<< students.size()<<endl<<students.capacity()<<endl;
return;
}
What I am confused about now is how to access the data that was inputted! I know it was put into a vector, but How to I go about accessing the individual spaces in the vector, and how exactly is the inputted data stored in the vector? If I try to cout a spot of the vector, I get an error because Visual Studio doesn't know what to output I guess..
The other answers are good, but they look a bit complicated. You can do it simply by:
vector<Student> students; // A place to store the list of students
Student s; // A place to store data of one student
ifstream fin("filename"); // Open the file
while (fin >> s.firstName >> s.secondName >> s.idNumber)
students.push_back(s);
Note that if istream fails, such as when the file finishes, the istream object (fin) will evaluate to false. Therefore while (fin >> ....) will stop when the file finishes.
P.S. Don't forget to check if the file is opened or not.
Define a stream reader for student:
std::istream& operator>>(std::istream& stream, Student& data)
{
std::string line;
std::getline(stream, line);
std::stringstream linestream(line);
linestream >> data.firstName >> data.secondName >> data.idNumber;
return stream;
}
Now you should be able to stream objects from any stream, including a file:
int main()
{
std::ifstream file("data");
Student student1;
file >> student1; // Read 1 student;
// Or Copy a file of students into a vector
std::vector<Student> studentVector;
std::copy(std::istream_iterator<Student>(file),
std::istream_iterator<Student>(),
std::back_inserter(studentVector)
);
}
Simply read a whole line and then split the string at the spaces and assign the values to an object of the struct.
pseudo code:
while( !eof )
line = readline()
parts = line.split( ' ' )
Student stud = new Student()
stud.firstName = parts[0]
stud.secondName = parts[1]
stud.idNumber = parts[2]
students.add( stud )
end while