C++ infile.getline(), pointer, char array error

  • (2 Pages)
  • +
  • 1
  • 2

17 Replies - 1429 Views - Last Post: 26 October 2013 - 02:10 PM Rate Topic: -----

#1 mcphersonad21  Icon User is offline

  • New D.I.C Head

Reputation: 0
  • View blog
  • Posts: 10
  • Joined: 14-September 13

C++ infile.getline(), pointer, char array error

Posted 25 October 2013 - 07:26 PM

C++ please...I am having some problems with a code that I know can be done easier but the assignment is specific with the required methods. I have to read in data from a .txt file and use pointers, char array, and 2d array to print original list/sort by last name & print/ sort by avg & print. I cant get past reading in the data to even start the functions for sorting and calculating an average....if someone could take a look and possibly point out what I am doing wrong or just give some insight on why my getline() doesnt seem to work right, that would be GREAT. I have taken the issue to my professor twice, and although she holds the position as dean of the department for CS, she is very limited when it comes to using Mac(Xcode). I can recall her looking at my code for two hours (trying different testing techniques) and telling me to "get a real computer"...that wasnt helpful??

example data:
Bill
Clinton
45.5 56.5 34.6 45.6
George W.
Bush III
80.7 89.6 67.2 61.4
Barrack
Obama
50.6 60.2 47.7 52.4
No
More

my read function:

void  ReadData ( ifstream &infile, char *Fname[], char *Lname[], float score[ ][4], int &REU, int &CEU)

{   
    char *FNptr;
    char TempF[16];
    char *LNptr;
    char TempL[16];
    int i = 0;
    

    infile.getline(TempF, 16);
    infile.getline(TempL, 16);
    
    REU = 0;
    
    cout << TempF;
    cout << TempL;
    
    while(strcmp(TempF,Sentinel) !=0)
    {           
        
        FNptr = new char[16];
        strcpy(FNptr,TempF);
        Fname[REU] = FNptr;
        
        LNptr = new char[16];
        strcpy(LNptr,TempL);
        Lname[REU] = LNptr;
        
        //if(strcmp(*Fname,Sentinel) == 1){break;}
        
        score[REU][CEU] = REU;
            for(i = 0; i < 4; ++i)
            {
                infile >> ws;
                infile >> score[REU][i];
                cout << score[REU][i] << "  ";
            }
        cout << endl;
        //cin.ignore();

        REU++;
 
        infile >> ws;
        infile.getline(TempF, 16);
        infile.getline(TempL, 16);
        
        
        //REU++; 
        
        cout << TempF;
        cout << TempL;
        //cout << Sentinel << '/' << endl;
    }
    CEU = i;
    
    return; 
}



you will notice several cout << lines where i was testing the code while trying to get it to work properly. so far, it will read the lines and place them in the appropriate arrays but it continues after the (sentinel) for unknown reason....here is an example of the error message:

Bill
Clinton
45.5 56.5 34.6 45.6
George W.
Bush III
80.7 89.6 67.2 61.4
Barrack
Obama
50.6 60.2 47.7 52.4
No
More
44 4.57412e-41 8.52868e-14 4.57412e-41
45 4.57412e-41 8.52872e-14 4.57412e-41
46 4.57412e-41 8.52877e-14 4.57412e-41
47 4.57412e-41 8.52881e-14 4.57412e-41
48 4.57412e-41 8.52885e-14 4.57412e-41
49 4.57412e-41 8.5289e-14 4.57412e-41
50 4.57412e-41 8.52894e-14 4.57412e-41

It continues to go until REU reaches 211 then hits a pause and prints out all of the above......

Is This A Good Question/Topic? 0
  • +

Replies To: C++ infile.getline(), pointer, char array error

#2 #define  Icon User is offline

  • Duke of Err
  • member icon

Reputation: 1432
  • View blog
  • Posts: 4,968
  • Joined: 19-February 09

Re: C++ infile.getline(), pointer, char array error

Posted 25 October 2013 - 08:13 PM

Hi, it could be that your stream has failed, basic_ios::good.

What is the value of Sentinel? Does 'No' have a capital N.

Where is CEU initialized?
Was This Post Helpful? 0
  • +
  • -

#3 mcphersonad21  Icon User is offline

  • New D.I.C Head

Reputation: 0
  • View blog
  • Posts: 10
  • Joined: 14-September 13

Re: C++ infile.getline(), pointer, char array error

Posted 25 October 2013 - 08:52 PM

View Post#define, on 25 October 2013 - 08:13 PM, said:

Hi, it could be that your stream has failed, basic_ios::good.

What is the value of Sentinel? Does 'No' have a capital N.

Where is CEU initialized?


sorry for not including that information...I am sure that would have been helpful.
here is my sentinel line

#define Sentinel "No            "


CEU is initialized in main i am attempting to pass by reference

but here is a snippet of main, i created a print function but commented it out to try and figure out where i was going wrong inside my read function... I guess I should have mentioned that eventually I will print to an Outfile named Results but I need to get through this read problem first.

void  ReadData ( ifstream &infile, char *Fname[], char *Lname[], float score[ ][4], int &REU, int &CEU);
void Print(ofstream &Outfile, char *Fname[], char *Lname[], float score[][4], int REU, int CEU);


int main(int argc, const char * argv[])
{
    char *Fname[MAX];
    char *Lname[MAX];
    float score[MAX][4] = {0};
    int REU=0;
    int CEU=0; 
    
    // open data4.txt file to read data from
    ifstream infile;
    infile.open(File,ios::in); 
    // create and open output file to print to... named Results4
    ofstream Outfile("Results5",ios::out);
    
    infile.setf(ios::fixed);
    
    Outfile.setf(ios::fixed); // set my output print to fixed
    Outfile.precision(2);    // set fixed precision of float output to 2 digits after decimal    
    
    ReadData(infile, Fname, Lname, score, REU, CEU);
    
    //Print(Outfile, Fname, Lname, score, REU, CEU);
    

    
    // close the infile
    infile.close();
    // close the outfile
    Outfile.close();     
    
    return 0;
}



Thanks for taking the time to look at it...
Was This Post Helpful? 0
  • +
  • -

#4 #define  Icon User is offline

  • Duke of Err
  • member icon

Reputation: 1432
  • View blog
  • Posts: 4,968
  • Joined: 19-February 09

Re: C++ infile.getline(), pointer, char array error

Posted 25 October 2013 - 09:59 PM

It is likely that the line containing No does not have spaces after it.

In that case you would have Sentinel defined as :

#define Sentinel "No"




You could test that the stream state is good :

while( strcmp(TempF,Sentinel) != 0 && infile.good() )
{
  // ...

}  




CEU looks like it will always be 4.
Was This Post Helpful? 1
  • +
  • -

#5 ccubed  Icon User is offline

  • It's That Guy
  • member icon

Reputation: 162
  • View blog
  • Posts: 1,409
  • Joined: 13-June 08

Re: C++ infile.getline(), pointer, char array error

Posted 25 October 2013 - 10:15 PM

CEU Would always be 3 actually. At the end of the loop it's at 3.

Anyways, your problem is your very specific comparison of Sentinel and TempF. You define Sentinel as a char array with 14 character spots, 15 counting the implicit '\0' that gets added at the end. So you only have 15 characters at most, but you're reading in 16, really 17 with the '\0'. At what point will 15 characters ever compare equally to 17?

This post has been edited by ccubed: 25 October 2013 - 10:16 PM

Was This Post Helpful? 1
  • +
  • -

#6 mcphersonad21  Icon User is offline

  • New D.I.C Head

Reputation: 0
  • View blog
  • Posts: 10
  • Joined: 14-September 13

Re: C++ infile.getline(), pointer, char array error

Posted 25 October 2013 - 10:16 PM

View Post#define, on 25 October 2013 - 09:59 PM, said:

It is likely that the line containing No does not have spaces after it.

In that case you would have Sentinel defined as :

#define Sentinel "No"




You could test that the stream state is good :

while( strcmp(TempF,Sentinel) != 0 && infile.good() )
{
  // ...

}  




CEU looks like it will always be 4.


I actually looked into that and the data.txt file has exactly 12 spaces trailing the "No" before going to next line, as for your test condition... i tried it and you were right! after running it, the end of my output looked like this....

Quote

George
Bush
88.8 87.8 66.6 68.2
Bill
Clinton
45.5 56.5 34.6 45.6
George W.
Bush III
80.7 89.6 67.2 61.4
Barrack
Obama
50.6 60.2 47.7 52.4
No
More
44 0 0 0


so im wondering if it is printing that last bit because it needs to read one line past the sentinel to know its time to stop? or....? but since I update my first name with infile.getline(TempF) before going back into the while loop shouldnt it just not execute? should I also test for the last name being read in like strcmp(TempL, "More")!=0 as well, or does it not matter in the end?
Was This Post Helpful? 0
  • +
  • -

#7 mcphersonad21  Icon User is offline

  • New D.I.C Head

Reputation: 0
  • View blog
  • Posts: 10
  • Joined: 14-September 13

Re: C++ infile.getline(), pointer, char array error

Posted 25 October 2013 - 10:32 PM

View Postccubed, on 25 October 2013 - 10:15 PM, said:

CEU Would always be 3 actually. At the end of the loop it's at 3.

Anyways, your problem is your very specific comparison of Sentinel and TempF. You define Sentinel as a char array with 14 character spots, 15 counting the implicit '\0' that gets added at the end. So you only have 15 characters at most, but you're reading in 16, really 17 with the '\0'. At what point will 15 characters ever compare equally to 17?


so would it be more beneficial for me to remove the #define and just use "No" in my strcmp( , )... or would I run into the same issue? as for reading in the 16 character, it quite interesting because i had to play with those numbers a bit just to get it to read each line accurately. When i had it set to 15, i was never reading in each line successfully even though the data.txt file has exactly 14 (characters) before reaching a new line. its definitely confusing to me, has me wondering what kind of condition when needed for my print function, or how i will test it to get the desired format of my print??

thanks in advance.
Was This Post Helpful? 0
  • +
  • -

#8 #define  Icon User is offline

  • Duke of Err
  • member icon

Reputation: 1432
  • View blog
  • Posts: 4,968
  • Joined: 19-February 09

Re: C++ infile.getline(), pointer, char array error

Posted 25 October 2013 - 11:10 PM

View Postmcphersonad21, on 26 October 2013 - 06:16 AM, said:

I actually looked into that and the data.txt file has exactly 12 spaces trailing the "No" before going to next line, as for your test condition... i tried it and you were right! after running it, the end of my output looked like this....

so im wondering if it is printing that last bit because it needs to read one line past the sentinel to know its time to stop? or....? but since I update my first name with infile.getline(TempF) before going back into the while loop shouldnt it just not execute? should I also test for the last name being read in like strcmp(TempL, "More")!=0 as well, or does it not matter in the end?


The sentinel is not working for some reason, and skips to the eof which means the stream state is not good().

You could try printing the length of TempF, and checking what the value is when it is the sentinel.

You could also try strncmp which checks a number of characters.

#define Sentinel "No "

// ...

 while( strncmp( TempF, Sentinel, strlen(Sentinel)) != 0 )
 {
   // ...
 }



If you are sure there are spaces after No, a space can be added to the sentinel to limit false positives. Checking More would make errors less likely.

Norman
Moreland



Not a president so probably over cautious.
'

This post has been edited by #define: 25 October 2013 - 11:12 PM

Was This Post Helpful? 0
  • +
  • -

#9 ccubed  Icon User is offline

  • It's That Guy
  • member icon

Reputation: 162
  • View blog
  • Posts: 1,409
  • Joined: 13-June 08

Re: C++ infile.getline(), pointer, char array error

Posted 26 October 2013 - 12:27 PM

Sorry, I tottered off to bed. To answer your question, here are some ways you could do what you want. I'm assuming the file structure is first name, last name, score 1, score 2, score 3, score 4 each on its own line with 14 size not counting the newline.

1) Let C++ deal with it
#include <iostream>
#include <fstream>
using namespace std;

int main() {

	char fname[16];
	char lname[16];
	double score = 0.0;
	ifstream infile;
	infile.open("C:\\Users\\Charles\\Documents\\Visual Studio 2013\\Projects\\Project1\\Debug\\test.txt");
	infile >> fname;
	infile >> lname;
	cout << fname << " " << lname << endl;
	infile >> score;
	cout << score << endl;
	infile >> score;
	cout << score << endl;
	cin.get();


}



That results in the output:
Mark Brown
80.4
90.4

You should check for EOF, but i knew the number of lines in this case and just did it the easy way.

2) Use your gets but change them. (from here just including changed code.)
infile.get(fname,14);
infile.ignore(256, '\n');
infile.get(lname,14);
infile.ignore(256, '\n');



Output:
Mark <10 spaces> Brown
80.4
90.4

This is the same thing that happens when you let C++ deal with it. Your char arrays at most need 15 spaces. 14 for your data, 1 for the null terminator bit. However, your title line length is 14 + 2. 14 for your data and 2 for your newline bits. What you were doing was reading in up to the newline but never removing it. Get doesn't actually discard it.
Was This Post Helpful? 1
  • +
  • -

#10 jimblumberg  Icon User is online

  • member icon


Reputation: 4278
  • View blog
  • Posts: 13,439
  • Joined: 25-December 09

Re: C++ infile.getline(), pointer, char array error

Posted 26 October 2013 - 12:40 PM

Please look at the following snippet:
	char fname[16];
	char lname[16];
...
	infile >> fname;
	infile >> lname;

Never use any function that doesn't limit the number of characters it will retrieve when using C-strings. When using the extraction operator you should use the setw() manipulator to limit the number of characters so you don't have a possibility of buffer overruns. Either of the following will limit the number of characters you can retrieve with the extraction operator.

	char fname[16];
	char lname[16];
...
	infile >> setw(16) >> fname;
	infile >> setw(sizeof(lname)) >> lname;


But remember if your strings have spaces you'll have problems. You really should stick with getline() when dealing with C-strings, and start using std::string as soon as possible.

Jim

This post has been edited by jimblumberg: 26 October 2013 - 12:43 PM

Was This Post Helpful? 1
  • +
  • -

#11 mcphersonad21  Icon User is offline

  • New D.I.C Head

Reputation: 0
  • View blog
  • Posts: 10
  • Joined: 14-September 13

Re: C++ infile.getline(), pointer, char array error

Posted 26 October 2013 - 01:29 PM

View Postccubed, on 26 October 2013 - 12:27 PM, said:

Sorry, I tottered off to bed. To answer your question, here are some ways you could do what you want. I'm assuming the file structure is first name, last name, score 1, score 2, score 3, score 4 each on its own line with 14 size not counting the newline.

1) Let C++ deal with it
#include <iostream>
#include <fstream>
using namespace std;

int main() {

	char fname[16];
	char lname[16];
	double score = 0.0;
	ifstream infile;
	infile.open("C:\\Users\\Charles\\Documents\\Visual Studio 2013\\Projects\\Project1\\Debug\\test.txt");
	infile >> fname;
	infile >> lname;
	cout << fname << " " << lname << endl;
	infile >> score;
	cout << score << endl;
	infile >> score;
	cout << score << endl;
	cin.get();


}



That results in the output:
Mark Brown
80.4
90.4

You should check for EOF, but i knew the number of lines in this case and just did it the easy way.

2) Use your gets but change them. (from here just including changed code.)
infile.get(fname,14);
infile.ignore(256, '\n');
infile.get(lname,14);
infile.ignore(256, '\n');



Output:
Mark <10 spaces> Brown
80.4
90.4

This is the same thing that happens when you let C++ deal with it. Your char arrays at most need 15 spaces. 14 for your data, 1 for the null terminator bit. However, your title line length is 14 + 2. 14 for your data and 2 for your newline bits. What you were doing was reading in up to the newline but never removing it. Get doesn't actually discard it.


here is an update of my read in function and print function.... i have changed the strcpy to a strncpy and copy over only 14 character to my actual array that will be used in the print function. it worked great but as you can see im still reading in the lines that should exit the loop??

//*********************** Function Header ****************************
void  ReadData ( ifstream &infile, char *Fname[], char *Lname[], float score[ ][4], int &REU, int &CEU)
{   
    char *FNptr;
    char TempF[16];
    char *LNptr;
    char TempL[16];
    int i = 0;
    

    infile.getline(TempF, 16);
    infile.getline(TempL, 16);
    
    
    REU = 0;
    
    //cout << TempF;
    //cout << TempL;
    
    while( strcmp(TempF,"No ") != 0 && infile.good() )
    {           
        
        FNptr = new char[16];
        strncpy(FNptr,TempF,14);
        Fname[REU] = FNptr;
        
        LNptr = new char[16];
        strncpy(LNptr,TempL,14);
        Lname[REU] = LNptr;
        
        
        score[REU][CEU] = REU;
        CEU = 0;
        for(i = 0; i < 4; ++i)
        {
            infile >> ws;
            infile >> score[REU][i];
            //cout << score[REU][i] << "  ";
        }
        
        //cout << endl;
        //cin.ignore();
        
        REU++;
            
        infile >> ws;
        infile.getline(TempF, 16);
        infile.getline(TempL, 16);
        
        
        //REU++; 
        
        //cout << TempF;
        //cout << TempL;
        //cout << Sentinel << '/' << endl;
    }
    CEU = i;
    
    return; 
}
//************************ Print Function *******************************
void Print(ofstream &Outfile, char *Fname[], char *Lname[], float score[][4], int REU, int CEU)
{
    int i;
    int j;
    
    for(i = 0; i < REU; i++)
    {
        cout << Fname[i] << Lname[i] << "|";        
        {
            for( j= 0; j < 4; j++)
            {
                cout << setw(7) << score[i][j];
            }
            
            cout << endl;
        }
    }
}



this is was then end of my print out currently looks like....

Quote

Calvn Coolidge | 75.8 89.9 78.2 80.3
Herbert Hoover | 66.8 90.9 58.4 69.4
Franklin D. Roosevelt | 89.9 68.7 60.2 77.5
Harry S. Truman | 77.9 71.2 76.7 75.3
Dwight D. Eisenhower | 82.2 81.9 72.6 75.6
John F. Kennedy | 68.3 87.3 63.7 79.2
Lyndon B. Johnson | 57.3 66.3 64.8 30.6
Richard M. Nixon | 76.2 67.3 72.1 75.6
Gerald Ford | 88.8 59.2 67.7 80.5
Jimmy Carter | 55.5 36.6 54.5 39.9
Ronald Reagan | 97.8 98.2 93.3 96.5
George Bush | 88.8 87.8 66.6 68.2
Bill Clinton | 45.5 56.5 34.6 45.6
George W. Bush III | 80.7 89.6 67.2 61.4
Barrack Obama | 50.6 60.2 47.7 52.4
No
More | 44.0 0.0 0.0 0.0


used the " | " to test for number of spaces being read in and they all lined up perfectly expect for the No More line??? why is it still reading in that line??

thanks again
Was This Post Helpful? 0
  • +
  • -

#12 ccubed  Icon User is offline

  • It's That Guy
  • member icon

Reputation: 162
  • View blog
  • Posts: 1,409
  • Joined: 13-June 08

Re: C++ infile.getline(), pointer, char array error

Posted 26 October 2013 - 01:29 PM

@jim - Very correct. This was a very basic example to demonstrate the idea. That's why I warned him he should be doing other error checking when he uses that method. I was under the impression he could not use std::string or Getline but in case he can.

Here is a getline example.

//only changed code
#include <string>

string fname;
string lname;

getline(infile,fname);
getline(infile,lname);

cout << fname << endl << lname << endl;


Output:
Mark
Brown

Getline will remove the newline from the stream (or delimiter if specified) so you don't need to remove it yourself with ignore or some other method.

View Postmcphersonad21, on 26 October 2013 - 02:29 PM, said:

used the " | " to test for number of spaces being read in and they all lined up perfectly expect for the No More line??? why is it still reading in that line??


You're now comparing 17 with 4. You're still comparing two separate length arrays. You should either use strncmp as suggested or make sure your two arrays are the same length.

strncmp(fname,sentinel,2)



The above will only look at the first two chars in each array which should be No for both.

This post has been edited by ccubed: 26 October 2013 - 01:40 PM

Was This Post Helpful? 1
  • +
  • -

#13 jimblumberg  Icon User is online

  • member icon


Reputation: 4278
  • View blog
  • Posts: 13,439
  • Joined: 25-December 09

Re: C++ infile.getline(), pointer, char array error

Posted 26 October 2013 - 01:39 PM

In the following snippet:
    while( strcmp(TempF,"No ") != 0 && infile.good() 

Have you tried using strncp() instead?
    while( strncmp(TempF,"No",2) != 0 && infile.good() 


Jim

This post has been edited by jimblumberg: 26 October 2013 - 01:39 PM

Was This Post Helpful? 1
  • +
  • -

#14 mcphersonad21  Icon User is offline

  • New D.I.C Head

Reputation: 0
  • View blog
  • Posts: 10
  • Joined: 14-September 13

Re: C++ infile.getline(), pointer, char array error

Posted 26 October 2013 - 01:40 PM

View Postccubed, on 26 October 2013 - 12:27 PM, said:

Sorry, I tottered off to bed. To answer your question, here are some ways you could do what you want. I'm assuming the file structure is first name, last name, score 1, score 2, score 3, score 4 each on its own line with 14 size not counting the newline.

1) Let C++ deal with it
#include <iostream>
#include <fstream>
using namespace std;

int main() {

	char fname[16];
	char lname[16];
	double score = 0.0;
	ifstream infile;
	infile.open("C:\\Users\\Charles\\Documents\\Visual Studio 2013\\Projects\\Project1\\Debug\\test.txt");
	infile >> fname;
	infile >> lname;
	cout << fname << " " << lname << endl;
	infile >> score;
	cout << score << endl;
	infile >> score;
	cout << score << endl;
	cin.get();


}



That results in the output:
Mark Brown
80.4
90.4

You should check for EOF, but i knew the number of lines in this case and just did it the easy way.

2) Use your gets but change them. (from here just including changed code.)
infile.get(fname,14);
infile.ignore(256, '\n');
infile.get(lname,14);
infile.ignore(256, '\n');



Output:
Mark <10 spaces> Brown
80.4
90.4

This is the same thing that happens when you let C++ deal with it. Your char arrays at most need 15 spaces. 14 for your data, 1 for the null terminator bit. However, your title line length is 14 + 2. 14 for your data and 2 for your newline bits. What you were doing was reading in up to the newline but never removing it. Get doesn't actually discard it.


This was a huge help... i realized what was going on during the transfer of data between the first name pointer, the new char[], and the strcpy... setting it equal to my array for first names... i was copying over the /r or new line character but i changed it to a strncpy and only specified (14) even though my original getline( ) temp array is set for 16 as well as the new char[]

thanks for pointing it out.
Was This Post Helpful? 0
  • +
  • -

#15 mcphersonad21  Icon User is offline

  • New D.I.C Head

Reputation: 0
  • View blog
  • Posts: 10
  • Joined: 14-September 13

Re: C++ infile.getline(), pointer, char array error

Posted 26 October 2013 - 01:55 PM

View Postjimblumberg, on 26 October 2013 - 01:39 PM, said:

In the following snippet:
    while( strcmp(TempF,"No ") != 0 && infile.good() 

Have you tried using strncp() instead?
    while( strncmp(TempF,"No",2) != 0 && infile.good() 


Jim


alright.... that actually worked, however, (this is so confusing) it now skips over that No More line and reads in a line the the professor intentionally placed after the sentinel line??? here is the example data.txt file ...

Quote

Bush III
80.7 89.6 67.2 61.4
Barrack
Obama
50.6 60.2 47.7 52.4
No
More
C R
Van Dyke
80.0 80.0 80.0 80.0


and here is what my print out looks like after using the strncmp(Fname,"No",2)

Quote

Ronald Reagan | 97.8 98.2 93.3 96.5
George Bush | 88.8 87.8 66.6 68.2
Bill Clinton | 45.5 56.5 34.6 45.6
George W. Bush III | 80.7 89.6 67.2 61.4
Barrack Obama | 50.6 60.2 47.7 52.4
C R Van Dyke | 80.0 80.0 80.0 80.0

Was This Post Helpful? 0
  • +
  • -

  • (2 Pages)
  • +
  • 1
  • 2