trouble with getline and input files.

Hi. I have the following code snippet:

1
2
3
4
5
6
7
8
9
10
11
12
ifstream infile;    //Declares variable.
ofstream outfile;    //Declares variable.
while(1==1)    //Always true, therefore infinite loop.
    {
        cout<<"Enter input file name (save excel sheet as a .txt file): ";
        getline(cin,InputFileName);    //Take in whatever the user might type.
        infile.open(InputFileName.c_str());    //Opens input file.
        if(!infile)    //If the file cannot be opened...
            cout<<"\nFile does not exists.\n\n";
        else    //Otherwise...
            break;    //End the loop.
    }


When I run the program and enter the file name correctly the first time, everything works fine. However, if I enter the file name incorrectly the first time, the program will not be able to open the file the next time even if I enter the file name correctly. Why is this?

Also, I thought of doing the following as well:

1
2
3
4
5
6
7
8
9
10
11
ifstream infile;    //Declares variable.
ofstream outfile;    //Declares variable.
DoOver:
cout<<"Enter input file name (save excel sheet as a .txt file): ";
getline(cin,InputFileName);    //Take in whatever the user might type.
infile.open(InputFileName.c_str());    //Opens input file.
if(!infile)    //If the file cannot be opened...
{    
    cout<<"\nFile does not exists.\n\n";
    goto DoOver;    //Jump to another point in the program.
}


But I have the same exact problem.

Furthermore, I have a problem with this code:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
string row;    //Declares variable as a string.
stringstream ss2;    //Declare variable as a stringstream.
int x,z,k,ndatapoints=0;    //Declares variables as integers.
double sumCH4=0,sumCO=0,sumNO=0,sumNO2=0,sumC2H6=0,sumC3H8=0,sumC3H6=0,sumHCHO=0,sumCH3OH=0;
    //Declares variables as doubles.
cout<<"\nEnter row numbers at "<<i<<" \370C one by one. Press 'd' when done:\n\n                        ";
    while(1==1)    //Always true, therefore infinite loop.
    {
        getline(cin,row);    //Take in whatever the user may type.
        cout<<"                        ";
        if(row=="d")    //If the user types 'd' and only 'd'...
            break;    //End the loop.  
        for(k=0;k<row.size();k++)    //For each character in the string...
        {    
            if(isdigit(row[k]))    //If the character is a digit...
                check=check+1;
        }
        if(check==row.size()) //If the string consists only of digits...
        {
            ss2<<row;    //send row into the stringstream.
            ss2>>z;    /*Extract row from the stringstream and assign to the
            integer z.*/
            if(z>(NROWSA+19))
            {
                cout<<"\n            Error: row number exceeds total amount of rows.\n\n                        ";
                check=0;    //Resets value to zero.
            }
            if(z<20)
            {
                cout<<"\n            Error: row number cannot be less than 20.\n\n                        ";
                check=0;
            }
            if(z>=20&&z<=(NROWSA+19))
            {
                ndatapoints=ndatapoints+1;  /*Increase the number of data points
                by one.*/
                k=z-19;
                sumCH4=sumCH4+A[k][4];
                sumCO=sumCO+A[k][5];
                sumNO=sumNO+A[k][6];
                sumNO2=sumNO2+A[k][7];
                sumC2H6=sumC2H6+A[k][10];
                sumC3H8=sumC3H8+A[k][13];
                sumC3H6=sumC3H6+A[k][14];
                sumHCHO=sumHCHO+A[k][15];
                sumCH3OH=sumCH3OH+A[k][17];
                check=0;    //Reset value to zero.
            }
        }
        else    //Otherwise...
        {    
            cout<<"\n                    Invalid Entry.\n\n                        ";
            check=0;    //Resets value to zero.
        }
    }


In particular, the console window will display 'Error: row number cannot be less than 20.' before I even type anything.

Any help is much appreciated.
So much useless comments.

I think that when ifstream::open() fails the object gets in a 'zombie' state. All the operations performed on it will fail. So you must clear() it first.

In the other code, I suppose that 'row' is empty. You read another variable before and left a line break in the buffer.
So much useless comments.


Sorry to have upset you. What constitutes a useful comment to you?

I think that when ifstream::open() fails the object gets in a 'zombie' state. All the operations performed on it will fail. So you must clear() it first.


the clear() suggestion worked. I put an infile.clear() after the error message. Thank you, but could you please explain a bit more what this is actually doing?

In the other code, I suppose that 'row' is empty. You read another variable before and left a line break in the buffer.


I'm not sure exactly what you mean. Do you mean that the' \n' is causing the problem because it's still in the buffer? If it took in an empty line, wouldn't "Invalid Entry." be printed since the elements of the array are not all digits, but spaces instead? What should I do? I saw another forum that talked about cin.clear() and cin.sync() and cin.ignore(), but I am still confused about how to use them, which to use in my case, and what they do. Thanks.
the clear() suggestion worked. I put an infile.clear() after the error message. Thank you, but could you please explain a bit more what this is actually doing?


When a stream has an error it sets its error flags. infile.clear() clears these error flags so I/O operations can once again be performed.
See http://www.cplusplus.com/reference/iostream/ios/clear/ for more info.
Last edited on
Thanks, I get that now. But I am still having trouble with my code, which is shown below. If I type a wrong temperature while the Check function is running, the console window prints "Invalid Entry." no matter what I type from then on. I thought adding a cin.sync() before calling the data function would work since it would get rid of any newline characters left behind in the buffer stream from the Check function, which is where I use cin>>. But I am still having no luck.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
/*This program finds averages for concentrations of compounds at certain
temperatures, and then organizes the data in a matrix that is sent to an output
file.*/

#include<iostream>    //Allows for the use of cout/cin commands.
#include<fstream>//Enables one to load data from files and output data to files.
#include<cstdlib>    /*Needed for checking that the file was loaded correctly 
and also to convert strings to integers.*/
#include<cstring>    //Needed to find string lengths.
#include<cctype>    /*Allows for the use of isdigit function to check that an
array element is a digit*/
#include<sstream>    //Needed to insert and extract data from a stringstream.
using namespace std;    //Allows for basic C++ functions.  
const int NCOLSA=22,NCOLSB=9;
int NROWSA=-1,i,check=0,MaxTemp,MinTemp; //Declare global variables as integers.
double A[1000][NCOLSA],B[15][NCOLSB]; /*Declare global variables as doubles.*/                   
int main()    //Begins main function.
{
    string InputFileName,OutputFileName,line;   //Declare variable as a string.
    int NROWSB,j,T;    //Declare variables as integers.
    int Check(char a[]); /*Declare an integer function with a strings as the 
    only input.*/
    void data();    //Declare a void function with no input or output.
    ifstream infile;    //Declare variable.
    ofstream outfile;    //Declare variable.
    while(1==1)    //Always true, therefore infinite loop.
    {
        cout<<"Enter input file name (save excel sheet as a .txt file): ";
        getline(cin,InputFileName);    //Take in whatever the user might type.
        infile.open(InputFileName.c_str());    //Opens input file.
        if(!infile)    //If the file cannot be opened...
        {    
            cout<<"\nFile does not exists.\n\n";
            infile.clear();    //Clears error state.
        }
        else    //Otherwise...
            break;    //End the loop.
    }
    cout<<"\nEnter output file name (use a .csv extension): ";
    getline(cin,OutputFileName);
    outfile.open(OutputFileName.c_str());    //Creates output file.
    DoOver:
    MaxTemp=Check("maximum");   //Calls function and assigns output to MaxTemp.
    MinTemp=Check("minimum");   //Calls function and assigns output to MinTemp.
    if(MinTemp>MaxTemp)
    {
        cout<<"\n        Error: minimum temperature cannot be higher than maximum temperature.\n";
        goto DoOver;    //Jump to another point in the program.
    }
    NROWSB=(MaxTemp-MinTemp)/50+1;
    for(i=0;i<19;i++)
        getline(infile,line);
    A[0][0]=1;
    for(i=1;A[i-1][0]==1;i++)
    {    
         NROWSA=NROWSA+1;
         for(j=0;j<NCOLSA;j++)
            infile>>A[i][j];
    }
    cin.sync();
    for(i=MaxTemp;i>=MinTemp;i=i-50) /*For every 50 degree increment of the
    temperature starting at MaxTemp and ending at MinTemp...*/
        data();
    outfile<<"Temp (°C),CH4 (ppm),CO (ppm),NO (ppm),NO2 (ppm),C2H6 (ppm),C3H8 (ppm),C3H6 (ppm),HCHO (ppm),CH3OH (ppm)"<<endl;
    for(i=0;i<NROWSB;i++)    //For each successive row...
    {
        T=MinTemp+50*i;
        outfile<<T;
        for(j=0;j<NCOLSB;j++)    //For each successive column in a given row...
            outfile<<","<<B[i][j];    /*Send the element in that position to
            the output file.*/
        outfile<<endl;
    }
    cout<<endl;
    infile.close();    //Close input file. 

Last edited on
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
    outfile.close();    //Close output file.
    system("pause");    //Pause console window.
    return 0;
}    //Ends main function.

int Check(char a[]) /*This function checks to see that a character input 
consists only of digits, and if so, returns the string as a double.*/
{
    char b[100],c[100];    //Declare variables as strings.
    int y;    //Declare variable as an integer.
    stringstream ss1;    //Declare variable as a stringstream.
    double n1,n2;    //Declare variables as doubles.
    cout<<"\nEnter the "<<a<<" temperature: ";
    while(1==1)    //Always true, therefore infinite loop.
    {  
        cin>>b;    //Take in whatever user may type.
        for(i=0;i<strlen(b);i++)    //For each character in the string...
        {
            if(isdigit(b[i]))    //If the character is a digit...
                check=check+1;
        }
        if(check==strlen(b))    //If the string consists only of digits...
        {
            check=0;
            n1=atof(b);    //Convert the string to a double and assign to n1.
            n2=n1/50;    
            ss1<<n2;    //Send n2 into the stringstream.
            ss1>>c;    /*Extract n2 from the stringstream and assign to the
            string c.*/
            for(i=0;i<strlen(c);i++)
            {
                if(c[i]=='.')
                    check=check+1;
            }
            if(check==0)
            {
                y=atoi(b);    //Convert the string to an integer
                check=0;    //Reset value to zero.
                return y;    //Return y as a double.
                break;    //End the loop.
            }
            else
            {
                cout<<"\n                    Invalid Entry.\n\n"<<"Enter the "<<a<<" temperature: ";
                check=0;
            }
        }
        else //Otherwise...
            cout<<"\n                    Invalid Entry.\n\n"<<"Enter the "<<a<<" temperature: ";
            check=0;    //Reset value to zero.
    }
}    //Ends function.

void data() /*This function asks the user to input row numbers or type 'd' to
finish, averages the concentrations of all compounds once the user is finished,
and then puts the averages into appropriate array elements.*/
{
    string row;    //Declare variable as a string.
    stringstream ss2;    //Declare variable as a stringstream.
    int x,z,k,ndatapoints=0;    //Declare variables as integers.
    double sumCH4=0,sumCO=0,sumNO=0,sumNO2=0,sumC2H6=0,sumC3H8=0,sumC3H6=0,sumHCHO=0,sumCH3OH=0;
    //Declare variables as doubles.
    cout<<"\nEnter row numbers at "<<i<<" \370C one by one. Press 'd' when done:\n\n                        ";
    cin.sync();    //Clears the stream of any remaining input.
    while(1==1)    //Always true, therefore infinite loop.
    {
        getline(cin,row);    //Take in whatever the user may type.
        cout<<"                        ";
        if(row=="d")    //If the user types 'd' and only 'd'...
            break;    //End the loop.  
        for(k=0;k<row.size();k++)    //For each character in the string...
        {    
            if(isdigit(row[k]))    //If the character is a digit...
                check=check+1;
        }
        if(check==row.size()) //If the string consists only of digits...
        {
            ss2<<row;    //send row into the stringstream.
            ss2>>z;    /*Extract row from the stringstream and assign to the
            integer z.*/
            if(z>(NROWSA+19))
            {
                cout<<"\n            Error: row number exceeds total amount of rows.\n\n                        ";
                check=0;    //Resets value to zero.
            }
            if(z<20)
            {
                cout<<"\n            Error: row number cannot be less than 20.\n\n                        ";
                check=0;
            }
            if(z>=20&&z<=(NROWSA+19))
            {
                ndatapoints=ndatapoints+1;  /*Increase the number of data points
                by one.*/
                k=z-19;
                sumCH4=sumCH4+A[k][4];
                sumCO=sumCO+A[k][5];
                sumNO=sumNO+A[k][6];
                sumNO2=sumNO2+A[k][7];
                sumC2H6=sumC2H6+A[k][10];
                sumC3H8=sumC3H8+A[k][13];
                sumC3H6=sumC3H6+A[k][14];
                sumHCHO=sumHCHO+A[k][15];
                sumCH3OH=sumCH3OH+A[k][17];
                check=0;    //Reset value to zero.
            }
        }
        else    //Otherwise...
        {    
            cout<<"\n                    Invalid Entry.\n\n                        ";
            check=0;    //Resets value to zero.
        }
    }
    x=(i-MinTemp)/50;
    B[x][0]=sumCH4/ndatapoints;    //Finds the average and inputs it into array.
    B[x][1]=sumCO/ndatapoints;
    B[x][2]=sumNO/ndatapoints;
    B[x][3]=sumNO2/ndatapoints;
    B[x][4]=sumC2H6/ndatapoints;
    B[x][5]=sumC3H8/ndatapoints;
    B[x][6]=sumC3H6/ndatapoints;
    B[x][7]=sumHCHO/ndatapoints;
    B[x][8]=sumCH3OH/ndatapoints;
}    //Ends function. 
What constitutes a useful comment to you?
Pseudocode (but I prefer to write function names), suppositions about the data, purpose of the class.

About your other post, tl dr.
tl dr

Awesome.

To sum up the code, I am using getline(cin,str_name) in the beginning. Then I call a function, Check, that uses cin>> in a loop and which will either propagate or end depending on what the user enters . Then I call another function, data, that uses getline(cin, str_name) in a loop which will either propagate, perform mathematical operations, or end depending on what is entered.

I believe the problem has to do with the mixing of getline(cin,str_name) and cin>>. Since you are not willing to read my entire code (I don't blame you), I guess we have to assume this is the problem. So...here are my questions based on what I've gathered from research:

1.) using cin>> leaves terminating characters in the buffer, right?
2.) Will cin.ignore() or cin.sync() erase these terminating characters?
3.) Is there any difference between cin.ignore() and cin.sync()?
4.) Where should I include cin.ignore() or cin.sync()? After the Check function and before the data function? In the loops themselves?
5.) Should I include any arguments in the parentheses of cin.ignore() or cin.sync()?

EDIT: Nevermind, I figured out what was wrong. It turns out that I needed to declare the stringstreams inside the loops and not outside. Is that because there was input left over in the stringstream, and by putting the declaration inside the loop, the stringstream is being recreated without any input?
Last edited on
Topic archived. No new replies allowed.