Using getline in loop, storing to an array - c++

Using getline to store information, I want to have an array which store a whole column in a text file, using a '/' as the delimiter, but when creating a loop which goes through the first line and stores that in a[i] etc, then moves onto the next line.`
const int MAX = 20;
int main(){
string menuname;
string a[MAX];
string d[MAX];
string b[MAX];
string c[MAX];
string line;
bool error = false;
ifstream openFile;
int counter = 0;
do{
cout << "Please enter the name of the menu you would like to open: ";
cin >> menuname;
menuname += ".txt";
openFile.open(menuname.c_str());
if(openFile.fail()){
cerr << "Unable to open file, please re-enter the name.\n";
error = true;
}
//Determine how many lines long the text file is
while(getline(openFile, line)){
++counter;
}
//Testing the counter
cout << counter;
}while(error == true);
while(! openFile.eof()){
for(int i = 0; i < counter; i++){
getline( openFile, a[i], '/');
getline( openFile, b[i], '/');
getline( openFile, c[i], '/');
getline( openFile, d[i]);
}
}
for(int i = 0; i < counter; i++){
cout << a[i] << b[i];
}
}
There is currently no errors when i run the program, and I have tested the counter variable by just showing an output, which is working correctly, but at the bottom of the program I have created a small test which should print some 2 of the arrays I store, but it prints nothing and the program just ends after displaying the value of counter.

The problem is you are at the end of the file when you go to actually store the data.
while(getline(openFile, line)){
++counter;
}
Reads the file all the way to the end and then sets the EOF flag on the string. Then you get to
while(! openFile.eof()){
for(int i = 0; i < counter; i++){
getline( openFile, a[i], '/');
getline( openFile, b[i], '/');
getline( openFile, c[i], '/');
getline( openFile, d[i]);
}
}
And since the EOF flag is set the while loop is never executed. Since all you really need counter for is the the display loop at the end we can combine the counter loop and the reading loop into one loop like
while(getline( openFile, a[counter], '/') && getline( openFile, b[counter], '/') &&
getline( openFile, c[counter], '/') && getline( openFile, d[counter])){
counter++;
}
And now we read in the full file and get a count of the number of lines read.

Related

Parse (split) a txt file with a string and int in c++

im a Student and new to this site. I want to split my txt file with my highscore data back to my Highscore List.
The txt file stores my Highscore like name:score
My parsing is not working and i dont know why?
I just want to split it to name and score again and then put it in my HighscoreList.
If you have any question about the code just ask :)
#include "highscore.h"
highscore::highscore(){
}
struct highscore::Player{
string spielerName;
int score;
};
void highscore::writeHighscore(string name, int score ,int playerNumberx){
Player HighscoreListe[100];
for(int i=0;i<=99;i++){
HighscoreListe[i].score = {0};
}
for(int i=0;i<=99;i++){
HighscoreListe[i].spielerName = "leer";
}
HighscoreListe[playerNumberx].spielerName = name;
HighscoreListe[playerNumberx].score = score;
int i, j,temp;
string temp1;
ifstream myfile("scores.txt");
string line;
//heres the point where i need help!!
if (myfile.is_open()){
int z=0;
while(getline(myfile, line)){
string name1;
string score1;
int d = 20;
while(line[z] != ':'){
name1 += line[z];
z++;
}
z = z+2;
while(line[z] != '\0'){
score1 += line[z];
z++;
}
HighscoreListe[d].spielerName = name;
HighscoreListe[d].score = score;
d++;
}
myfile.close();
}else cout << "Unable to open file" << endl;
for(i = 0; i<100; i++) {
for(j = i+1; j<100; j++)
{
if(HighscoreListe[j].score < HighscoreListe[i].score) {
temp = HighscoreListe[i].score;
temp1 = HighscoreListe[i].spielerName;
HighscoreListe[i].score = HighscoreListe[j].score;
HighscoreListe[i].spielerName = HighscoreListe[j].spielerName;
HighscoreListe[j].score = temp;
HighscoreListe[j].spielerName = temp1;
}
}
}
ofstream myfilex("scores.txt");
if (myfilex.is_open()){
for(int i = 99;i>89;i--){
myfilex << HighscoreListe[i].spielerName << ":" << HighscoreListe[i].score<<endl;
}
myfilex.close();
}
else cout << "Unable to open file" << endl;
}
void highscore::readHighscore(){
string line;
ifstream myfile("scores.txt");
if (myfile.is_open()){
while(getline(myfile, line)){
cout << line << endl;
}
}
else cout << "Unable to open file" << endl;
}
Make a >> overload for highscore::Player.
In the >> overload
Use std::getline to read a line from the input stream.
Create a std::istringstream out of the line.
Use std::getline to read up to the : from the istringstream into a local string name;.
Use another std::getline to read the rest of the line into a string.
Convert the string into an int with std::stoi and store into a local int score;. Make sure you provide a pos argument.
Ensure that the entire string was converted by comparting the pos argument with the string's length.
If nothing went wrong, store name and score into the highscore::Player passed by the caller. Otherwise, set the failbit on the input stream with setstate
return the input stream.
Now the reading code should be something simple like
int scorecount = 0;
while (myfile >> HighscoreListe[scorecount])
{
scorecount++;
}

print certain number of lines from a file in C++

i am trying to print 10 lines from a text file, and print another 10 based on user input or stop. My code print 10 lines but the first line is blank each time.
cin>>input;
ifstream file("midterm.txt");
while(input != sentinel && file >> output ) {
for(int i = 0; i < 10; i++) {
getline(file, output);
cout<<output<<endl;
}
cout<<"\nEnter any key to continue reading, enter # to stop"<<endl;
cin>>input;
}
file.close();
cout<<"File End";
return 0;
In your code, you should add ios::ate to make the lines working and you should also show what type are the used variables. Try that:
string input;
string sentinel = "#";
string output;
cin>>input;
ifstream file("midterm.txt",ios::ate);
while(input != sentinel && file >> output ) {
for(int i = 0; i < 10; i++) {
getline(file, output);
cout<<output<<endl;
}
cout<<"\nEnter any key to continue reading, enter # to stop"<<endl;
cin>>input;
}
file.close();
cout<<"File End";
return 0;

C++ read the content from two lines of document and store in two variables

I am trying to open a ".txt" file and read the content from the first line and the content from the second line. There are some numbers separated with a simple "space" on both lines of the ".txt" file.
How can I read the content from the first line and save each number in x[100] and read the content from second line and save each number in y[100]?
PS: I am a beginner.
#include<iostream>
#include<fstream>
using namespace std;
int main() {
int x[100], y[100], i=0;
ifstream myfile("something.txt");
while(myfile >> x[i]) {
cout << x[i] << "\n";
i++;
}
return 0;
}
Thank you so much!
As suggested in comments, use std::getline and std::istringstream.
std::string line1;
std::getline( myfile, line1 );
std::istringstream s( line1 );
while( i < 100 && s >> x[i] )
{
cout << x[i] << endl;
++i;
}
// Bail out if i == 100 and s is not empty.
// Same for line2 and y (and different i)
(Remark: Code replaces your while loop.)

Reading text file c++ (not able to display other lines)

char fname[20];
char lname[20];
int grade[10];
double avg=0.00;
fstream infile("C:\\Users\\Hady Zn\\Desktop\\hady.txt", ios::in);
fstream outfile("C:\\Users\\Hady Zn\\Desktop\\hady1.txt", ios::out);
while(infile>>fname>>lname)
{
outfile<<fname<<" "<<lname<<" ";
for(int i=0; i<10; i++)
grade[i]=0;
for(int i=0; i<10; i++)
{
infile>>grade[i];
if(grade[i]>=0 && grade[i]<=100)
{
outfile<<grade[i]<<" ";
avg+=grade[i];
}
}
outfile<<avg/10.00<<endl;
avg=0.00;
}
So the question is that i need to read from a text file a last name(space) first name(space) then 10 quiz grades(space between each grade) and write the same data into an output file with the average of 10 quizzes at each end of a line. The problem that im facing is that if i had less than 10 quizzes on one line it will not display the remaining lines.(I want it to still give me the average of the grades given considering for example if i was given 7 grades 3 will be zeros) I tried solving it but it just won't work. Any ideas that can solve this? Please help. Thank you
In order to perform such checks, it's better to read the text from the input file line by line and process each line to extract the data.
string line
while ( getline(infile, line) )
{
istringstream sstream(line);
sstream >> fname >> lname;
if (!sstream )
{
continue;
}
outfile<<fname<<" "<<lname<<" ";
for(int i=0; i<10; i++)
{
grade[i]=0;
sstream>>grade[i];
if ( !sstream )
{
break;
}
if(grade[i]>=0 && grade[i]<=100)
{
outfile<<grade[i]<<" ";
avg+=grade[i];
}
}
}
Update, in response to comment by OP:
You can avoid reading the input file line by line and processing each line. Here's my suggested changes to the loop.
while(infile>>fname>>lname)
{
outfile<<fname<<" "<<lname<<" ";
for(int i=0; i<10; i++)
{
grade[i]=0;
infile>>grade[i];
if ( !infile )
{
infile.clear();
break;
}
if(grade[i]>=0 && grade[i]<=100)
{
outfile<<grade[i]<<" ";
avg+=grade[i];
}
}
outfile<<avg/10.00<<endl;
avg=0.00;
}

Using getline with CSV

I've spent almost 4 hours trying to get past this issue...
I have a text file with over 100 rows. Each row has 4 values separated by commas. I want to be able to extract each value and save it into a variable (v1...v4).
I have used a for loop, as I won't be reading the entire contents of the file. I'm just trying to get 1 working for now.
So far, I have managed to read a single row. I just need to break the row up now. This is for my Uni assignment, and I am not allowed to use any boost or tokeniser classes. Just getline and other basic commands.
I have this code:
// Read contents from books.txt file
ifstream theFile("fileName.txt");
string v1, v2, v3, v4, line;
for (int i = 0; i < 1; i++) {
getline(theFile, line, '\n');
cout << line << endl; // This part works fine
getline(line, v1, ","); // Error here
cout << v1 << endl;
getline(line, v2, ","); // Error here
cout << v2 << endl;
getline(line, v3, ","); // Error here
cout << v3 << endl;
getline(line, v4, '\n'); // Error here
cout << v4 << endl;
}
theFile.close();
The error I get is - error: no matching function for call to ‘getline(std::string&, std::string&, const char [2])
How can I fix this?
The delimiter for getline is a character. You have used double-quote marks "," which represent a string (hence why the compiler error indicates that you've used char[2] - string literals contain an additional 'nul' character).
Single character values are represented using single quotes instead:
getline(myFile, v1, ',');
edit - I've just noticed you're passing a string as the first parameter, which getline doesn't support (it won't let you retrieve tokens directly from a string). You probably wanted to stuff the string into a stringstream instead
#include <sstream>
// etc ...
std::string csv = "the,cat,sat,on,the,mat";
std::istringstream buffer( csv );
std::string token;
while( std::getline( buffer, token, ',' ) )
{
std::cout << token << std::endl;
}
According to this page, you have to call getline with std::istream as the first parameter.
But line is of type std::string. You should pass a std::istream instead, which can
be done by creating an std::istringstream from line. This could work:
string v1, v2, v3, v4, line;
istringstream line_stream;
for (int i = 0; i < 1; i++) {
getline(theFile, line, '\n');
cout << line << endl;
line_stream.str(line); // set the input stream to line
getline(line_stream, v1, ","); // reads from line_stream and writes to v1
...
If you want to read more about std::istringstream, you can do that here.
Also, according to the above page, the third parameter has to be of type char. But you pass "," which will automatically converted to const char[2], a string. For characters, you use 'c'.
There are two overloads for std::getline:
istream& getline ( istream& is, string& str, char delim );
istream& getline ( istream& is, string& str );
Three of your calls pass a literal string constant as the third parameter, where a single char is required. Use ' rather than " for character constants.
string filename, text, line;
vector<string> v1;
vector<string> v2;
vector<string> v3;
vector<string> v4;
int i = 0, k = 0, n;
cout << "Enter filename." << endl;
cin >> filename;
cout << "How many lines of text are in the file?" << endl;
cin >> n;
cin.ignore(200, '\n');
ifstream file(filename.c_str());
if (!file) {
cerr << "No such file exists." << endl;
exit(1);
}
cin.ignore(200, '\n');
if (file.is_open()) {
while (file.good()) {
for (k = 0; k < n; k++) { //Loops for as many lines as there are in the file
for (i = 0; i < 4; i++) { //Loops for each comma-separated word in the line
getline(cin, text, ',');
if (i == 0)
v1.push_back(text);
else if (i == 1)
v2.push_back(text);
else if (i == 2)
v3.push_back(text);
else if (i == 3)
v4.push_back(text);
}
}
}
}
file.close();
return 0;
}