I'm having trouble with using getline from an input file

Discussion in 'Mac Programming' started by Stan11, Nov 5, 2008.

  1. Stan11 macrumors newbie

    Joined:
    Oct 17, 2008
    #1
    Hi,

    I'm writing a project for my C++ class that uses an input file. The first line of the file has a city and a state then there are about 100 lines after that. The first item in each line is a string and the second item is an integer.

    I need to bring in the city and state and store it in a variable, then put the rest of the data in an array of structs.

    To bring in the city and state I used 'getline'. For some reason 'getline' is reading the last line of the file and not the first. So when i start to fill in my array of structs it thinks there is no more data in the file.

    This is what the code looks like (variable 'place' is predefined):

    getline(infile, place);
    cout << place << endl;

    The output of this gives me the last line of the input file.

    Just to see if I could bring data in one piece at a time correctly, I wrote this.

    string name;
    infile >> name;
    cout << name << endl;
    getline(infile, place);
    cout << place << endl;

    The output of this gives the first word of the file then on the next line it prints the last line of the file. So I don't think the problem is with 'infile' but rather with 'getline'.

    If anyone could help me with this I'd appreciate it.
     
  2. toddburch macrumors 6502a

    Joined:
    Dec 4, 2006
    Location:
    Katy, Texas
    #2
    It stands to reason that getline() is not broken. Post your code.
     
  3. Stan11 thread starter macrumors newbie

    Joined:
    Oct 17, 2008
    #3
    Here is the code:

    ***************************************
    #include <iostream>
    #include <fstream>
    #include <iomanip>
    #include <string>
    #include <cassert>

    using namespace std;
    const int MAX_LENGTH = 200;
    struct list
    {
    string species;
    int count;
    };

    void fillStruct (ifstream& infile, list matrix[], string& place, int& listSize);

    int main()
    {
    ifstream infile; // variables
    ofstream outfile;
    int size = MAX_LENGTH;
    string inputName, city;

    list birds[size];

    cout << "Enter the input file name: "; // enter file name
    cin >> inputName;
    cout << endl;

    infile.open(inputName.c_str()); // open file 'inputname'
    outfile.open("Output.txt");

    if (!infile)
    {
    cout << "Invalid input file name." << endl;
    return 1;
    }
    fillStruct(infile, birds , city, size); // fill struct

    return 0;
    }

    void fillStruct (ifstream& infile, list matrix[], string& place, int& listSize)
    {
    int index = 0;
    listSize = 0;
    string name;
    infile >> name;
    cout << name << endl;
    getline(infile, name);
    cout << name << endl;
    assert (infile);

    while (infile)
    {
    infile >> matrix[index].species >> matrix[index].count;
    listSize++;
    index++;
    }
    }
    **************************************

    I have attached the input file. It is called two.txt.

    This is the output after the program is run:

    ********************************
    Enter the input file name: two.txt

    Virginia
    House_Sparrow nch 110
    ********************************

    As you can see, the information that I brought in one piece at a time brought in the first item of the input file (as it should). But the info I brought in using 'getline' for some reason got the info in the last line.

    Also if you look at the last line of the input file, it says:

    House_Sparrow 110

    But 'getline' brought in and output:

    House_Sparrow nch 110

    I have no clue where the random 'nch' came from. Maybe you can find the problem, cause I can't.

    Thanks.
     

    Attached Files:

    • two.txt
      File size:
      3.9 KB
      Views:
      63
  4. lee1210 macrumors 68040

    lee1210

    Joined:
    Jan 10, 2005
    Location:
    Dallas, TX
    #4
    Use getline to read the first line, also.
    infile >> name;
    Was only bringing in Virginia when I tried it. Otherwise, when fillStruct returned, birds looked correct to me.

    I wouldn't name a data structure list, though. For one, that struct isn't a list, it represents a single detail about one species. maybe call it speciesInfo, and have an array of speciesInfo called speciesList, etc.

    -Lee

    P.S. What platform are you running this on? The line breaks may not match up with what your platform is expecting, so getline might not work how you're hoping. I had copied the text into a new file, i didn't save yours directly, so my line breaks would have matched no matter what.
     
  5. Stan11 thread starter macrumors newbie

    Joined:
    Oct 17, 2008
    #5
    I've made the corrections you suggested. Here is the new code:
    *******************************************************
    #include <iostream>
    #include <fstream>
    #include <iomanip>
    #include <string>
    #include <cassert>

    using namespace std;
    const int MAX_LENGTH = 200;
    struct speciesInfo
    {
    string species;
    int count;
    };

    void fillStruct (ifstream& infile, speciesInfo matrix[], string& place, int& listSize);

    int main() // main function
    {
    ifstream infile; // variables
    ofstream outfile;
    int size = MAX_LENGTH;
    string inputName, city;

    speciesInfo speciesList[size];

    cout << "Enter the input file name: "; // open file
    cin >> inputName;
    cout << endl;

    infile.open(inputName.c_str());
    outfile.open("Coffey.txt");

    if (!infile)
    {
    cout << "Invalid input file name." << endl;
    return 1;
    }
    fillStruct(infile, speciesList , city, size);
    return 0;
    }

    void fillStruct (ifstream& infile, speciesInfo matrix[], string& place, int& listSize)
    {
    int index = 0;
    listSize = 0;

    getline(infile, place);
    cout << place << endl;
    assert (infile);

    while (infile)
    {
    infile >> matrix[index].species >> matrix[index].count;
    listSize++;
    index++;
    }
    }
    ******************************************************

    After these corrections, this is the output:

    ****************************************************

    Enter the input file name: two.txt

    House_Sparrow nch 110

    ***************************************************

    Again its getting the last line of the file.

    You asked for the platform. I'm using xcode to write the code. Then I'm compiling and running the program through the terminal (Is that the platform you're talking about?).
     
  6. lee1210 macrumors 68040

    lee1210

    Joined:
    Jan 10, 2005
    Location:
    Dallas, TX
    #6
    I was just wanting to know what OS you were using (plenty of people post here with non-OS X questions), as this affects the type of line-breaks used.

    It looks like in your output part of American Goldfinch is in the buffer (nch) as well as the last line. As to WHY that's happening, that is another story. On my machine (not OS X, not at home) the latest example seems to run fine with the copy of the input file you sent.

    I just tried it with the file you sent verbatim and got the same output as you have been getting... so something is going awry with the linebreaks vs. what OS X expects. The first getline is reading up the whole file, it appears. The cout is then printing expecting the local line-break style, and just doing carriage returns when it hits the end of the "lines", so each writes over the last.

    Essentially, it looks like your code is correct if the input is in the format of the local system, but doesn't work with a file that uses \r only for newlines. Where did the input file come from? Must your code work with that file (or will the file be graded on another platform, i.e. windows)?

    -Lee
     
  7. Stan11 thread starter macrumors newbie

    Joined:
    Oct 17, 2008
    #7
    I am running Mac OS X version 10.5.5

    The file I am using is a sample file (given to me by my teacher) to help me write my code. The project will be graded with a different file, but of the same exact format.

    The Project will be graded by my teacher (probably on a windows xp computer). All of the computers on campus use Dev-C++, so this is what my teacher will probably use.

    The due date of this project is November 12th, and the remainder of my code (The code to manipulate the input) has already been written. So after this is fixed my project will be finished.
     
  8. lazydog macrumors 6502a

    Joined:
    Sep 3, 2005
    Location:
    Cramlington, UK
    #8
    Hi

    A bit of a hack but you could try specifying '\r' as the end of line character in getline().

    b e n
     
  9. lee1210 macrumors 68040

    lee1210

    Joined:
    Jan 10, 2005
    Location:
    Dallas, TX
    #9
    The file provided uses only carriage returns at the end of lines... which is a pretty strange format. Most unix systems use a newline character only at the end of lines. Windows and DOS used a carriage return + newline character to end lines. Mac OS 9 and a few others used carriage returns only, as this file has. I would inform your instructor that you are programming on a UNIX system, and are depending on the behavior of getline to read the file.

    If this is not acceptable to the instructor, you'll have to change the input method to match what he or she expects. I can't imagine they are grading on an OS 9 system, or a Commodore, so it seems like, perhaps, this file was authored this way specifically to force you to deal with input yourself instead of using getline.

    As stated, ask the professor. Explain that your code will work with a file that contains newlines on the platform you're using, and ask if the platform the project will be graded on will have a getline implementation that handles the carriage return-only end-of-lines in the example. If so, you just need to reformat the test file in textedit or something, so you have proper newlines for your system, and your code will work when recompiled on the new system that uses carriage returns. If he says "make it work with the file provided" then you have to deal with the input issues yourself.

    -Lee
     
  10. toddburch macrumors 6502a

    Joined:
    Dec 4, 2006
    Location:
    Katy, Texas
    #10
    And here's the proof from Lee's post:
    Code:
    0000: 56 69 72 67 69 6E 69 61 20 42 65 61 63 68 2C 20 	Virginia Beach, 
    0010: 56 41 0D 53 6E 6F 77 5F 47 6F 6F 73 65 20 20 09 	VA.Snow_Goose  .
    0020: 09 33 30 35 20 20 20 20 20 20 20 20 20 20 20 20 	.305            
    0030: 20 20 0D 43 61 6E 61 64 61 5F 47 6F 6F 73 65 20 	  .Canada_Goose 
    0040: 20 09 09 35 36 37 20 20 20 20 20 20 20 20 20 20 	 ..567          
    0050: 20 20 20 20 0D 54 75 6E 64 72 61 5F 53 77 61 6E 	    .Tundra_Swan
    0060: 20 20 09 09 34 20 20 20 20 20 20 20 20 20 20 20 	  ..4           
    0070: 20 20 0D 57 6F 6F 64 5F 44 75 63 6B 20 20 09 09 	  .Wood_Duck  ..
    0080: 33 31 20 20 20 20 20 20 20 20 20 20 20 20 20 20 	31              
    0090: 0D 47 61 64 77 61 6C 6C 20 20 09 09 36 30 20 20 	.Gadwall  ..60  
    00A0: 20 20 20 20 20 20 20 20 20 20 20 20 0D 41 6D 65 	            .Ame
    00B0: 72 69 63 61 6E 5F 57 69 67 65 6F 6E 20 20 09 31 	rican_Wigeon  .1
    00C0: 34 33 20 20 20 20 20 20 20 20 20 20 20 20 20 20 	43              
    00D0: 0D 41 6D 65 72 69 63 61 6E 5F 42 6C 61 63 6B 5F 	.American_Black_
    00E0: 44 75 63 6B 20 20 09 32 20 20 20 20 20 20 20 20 	Duck  .2        
    00F0: 20 20 20 20 20 0D 4D 61 6C 6C 61 72 64 20 20 09 	     .Mallard  .
    
     
  11. Stan11 thread starter macrumors newbie

    Joined:
    Oct 17, 2008
    #11
    I think I'll first try to do what 'Lazydog' suggested and change the 'getline' so that it works with '\r'. Then I can put the final touches on my code. I will change the 'getline' back to the old way and take my code to one of the schools computers to see if it works fine. Since I only need to use 'getline' once in the whole program I will only have one thing to adjust when I move to a school's computer.

    How do you change the 'getline' so that it works with '\r' ?
     
  12. toddburch macrumors 6502a

    Joined:
    Dec 4, 2006
    Location:
    Katy, Texas
    #12
    Or, perhaps the instructor was wanting the students to use the alternate form of getline() that specifies the delimiter to use:

    http://www.cppreference.com/wiki/io/getline

    In which case, the X'0D' could be used as the delimiter.

    Todd
     
  13. Stan11 thread starter macrumors newbie

    Joined:
    Oct 17, 2008
    #13
    So instead of using:

    getline(infile, place);

    I should try using:

    infile.getline(place, '\r');
     
  14. toddburch macrumors 6502a

    Joined:
    Dec 4, 2006
    Location:
    Katy, Texas
    #14
    Or, you could use

    getline(infile, place, '\r') ;

    The getline() function is kind of a "switch hitter" in C++. It can stand on its own, like you have been using it, or it can be a method of a file.
     
  15. Stan11 thread starter macrumors newbie

    Joined:
    Oct 17, 2008
    #15
    I LOVE YOU!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!

    It works. IT WORKS.

    Thank you very much. I've been trying to solve this problem for three days.
     

Share This Page