Resolved Trouble reading a .txt file in Xcode with C++

Discussion in 'Mac Programming' started by rayonix, Jan 4, 2014.

  1. rayonix, Jan 4, 2014
    Last edited: Jan 4, 2014

    rayonix macrumors newbie

    Joined:
    Jan 4, 2014
    #1
    Hello,

    I am new to programming, and I am working my way through the C++ Primer Plus developers library to learn C++ independently.

    I just reached the point where I am learning File I/O, and I have covered and understand the file output portion, but I am having trouble with the file input section. I have the following code for reading numbers from a file. At the end, the program reports the count of numbers read, the sum of the numbers, and the average of the numbers:

    Code:
    // sumafile.cpp -- reading file input
    
    #include <iostream>
    #include <cstdlib>      // included for the exit() method
    #include <fstream>      // included for file I/O
    
    const int Size = 60;    // declares Size constant outside of main()
    
    int main()
    {
        using std::ifstream;    // allows us to create ifstream objects
        using std::cin;
        using std::cout;
        using std::endl;
        
        char array_of_char_filename[Size];      // creates an array of char to input a file name
        ifstream fin;       // declares an ifstream object fin
        
        // prompts the user to enter the name of a file and assigns fin to the user-determined file
        cout << "Enter the name of a data file: ";
        cin.getline(array_of_char_filename, Size);
        fin.open(array_of_char_filename);
        
        // used to determine whether or not the file has successfully been opened
        if (!fin.is_open())
        {
            cout << "Could not open the file " << array_of_char_filename << endl;
            cout << "Program terminating.\n";
            exit(EXIT_FAILURE);
        }
        
        // declares all variables necessary to perform arithmetic actions below
        double double_value;
        double double_sum = 0.0;
        int int_count = 0;
        
        fin >> double_value;    // gets value from the file
        
        // this loop runs while the most recent input is accepted, as determined by good()
        while (fin.good())
        {
            int_count++;        // keeps count of the number of elements read
            double_sum += double_value;     // running sum of those values
            fin >> double_value;        // reads another value while input is acceptable
        }
        
        // this if else construct displays the reasons why the file input was terminated
        // the eof() method is used first because the fail() method checks for EOF as well
        // as other reasons, so if we execute the first if statement we know that the
        // file simply reached the EOF and did not terminate for another reason
        if (fin.eof())
        {
            cout << "End of file reached.\n";
        }
        else if (fin.fail())
        {
            cout << "Input terminated by data mismatch.\n";
        }
        else
        {
            cout << "Input terminated for unknown reason.\n";
        }
        
        // displays to the user the results of reading the file
        if (int_count == 0)
        {
            cout << "No data processed.\n";
        }
        else
        {
            cout << "Items read: " << int_count << endl;
            cout << "Sum: " << double_sum << endl;
            cout << "Average: " << double_sum / double(int_count) << endl;
        }
        
        fin.close();    // close the file once finished
        
        return 0;
    }
    The file I am using for input is a .txt file, shown here:

    This is the output I get from running the program in Xcode:

    And this is the output I get from running the program in Terminal:

    What this tells me is that the program is successfully opening the file, but is not reading information. I have made sure the file is a .txt file and not .rtf.

    I am running Xcode 5.0.2 on OSX 10.9.1 on a MacBook Pro. Any help would be appreciated.
     
  2. chown33, Jan 4, 2014
    Last edited: Jan 4, 2014

    chown33 macrumors 604

    Joined:
    Aug 9, 2009
    #2
    Please post the complete URL of the specific section you're working on.


    If you print the running sum in your while loop, what is the output?
    What does this output tell you about exactly when the error is encountered?


    If the file is at EOF after reading a number, will fin.good() be true or false?
    If a read is attempted while already at EOF, will fin.good() be true or false?

    I suggest using some carefully constructed input files, and adding some diagnostic code to your while loop. The 1st file should contain no data at all (zero length). What happens when you run the program? The 2nd file should contain exactly one double number, such as 4.2 and no other characters, not even a newline. Again, what happens? The 3rd file should contain two numbers separated by a single space, and terminated by at least one newline. What happens?

    You should be able to identify what happens at each point data is read from the file, and what the values of fin.good() and fin.eof() are after each read. You may have to use the debugger or add diagnostic print statements to obtain the necessary evidence.

    Note that I'm implying two questions for each question I asked:
    1. What do you expect to happen for the given conditions?
    2. What actually happens for the given conditions?

    Debugging is the process of confirming expectations. The error could lie in the expectation or in the actual result.

    Debugging is also a process of breaking things down, so you have small enough and visible enough parts that you can confirm a specific expectation. Confirmation requires evidence, so break things down and pick out all the necessary pieces to do that. If the part isn't small enough, break it down further.


    EDIT
    The only way I can get output like this:
    Code:
    Enter the name of a data file: test.txt
    Input terminated by data mismatch.
    No data processed.
    
    is when the input file starts with a non-numeric series of characters. The data I used to produce that output:
    Code:
    badnum 18 19 18.5 13.5 14
    
    which is your first line of data, preceded by the string "badnum". The badnum won't convert as a number for the first read, so it stops with an error and no data processed. Other test data I tried did not produce the same output.

    So you need to apply the debugging principles to your data file. What app are you editing the data file with? How did you confirm it's plain text and not some other format like RTF? Break it down, and be specific.

    I used the cat command in Terminal:
    Code:
    cat testbad.txt
    
    There were times I also used the hexdump command:
    Code:
    hexdump -C testX.txt
    
    Here's the man page for hexdump:
    https://developer.apple.com/library/mac/documentation/Darwin/Reference/ManPages/man1/hexdump.1.html
     
  3. rayonix, Jan 4, 2014
    Last edited: Jan 4, 2014

    rayonix thread starter macrumors newbie

    Joined:
    Jan 4, 2014
    #3
    Thank you for your help, I figured out my problem.

    There were no issues with the code, although I did try several variations of diagnostic code to find exactly where the problem was. Per your suggestion, I included

    Code:
    cout << double_sum << endl;
    in my while loop, as well as

    Code:
    cout << "First number: " << double_value << endl;
    immediately after the first value is read. Then, I tried to read several files: one with no text; one with 1 number; one with 2 numbers and a newline; one with 1 number and a newline. In each case, the code deemed the first number to be 0, and the running sum was never printed as execution never reached the while loop.

    My problem was with the file: I needed to go to Format > Make Plain Text within the TextEdit menu. I had previously saved the file as test.txt, thinking this would make the file plain text, but I was mistaken. After this change, the program worked just fine.

    One minor note: In my original .txt file,

    Code:
    18 19 18.5 13.5 14
    16 19.5 20 18 12 18.5
    17.5
    I needed to include a newline character after 17.5 in order to read the final number. Without the newline, it only read the first 11 numbers and reports the count as 11, the sum of the first 11 numbers, and the average of the first 11 numbers, leaving off the 12th and final number.

    And you are right, the only way to get the output I originally got (with a correct .txt file) is to have the first data input be incompatible with the type double, like a character as in your case with badnum.

    Thanks again for your help!
     

Share This Page