1

I am trying to extract data from one file and add each line to alternating lines. Example .txt file:

123 Main
500
555 Acorn
1500
23 Smithville
1540

I have an address array to hold the strings and amountDue array to hold integers. Ideally address[0] holds "123 Main" and amountDue[0] holds 500, etc.

The function I have made for this uses getline to get the string and works for the first loop but the inputFile >> amountDue[0] recieves more than the 500 integer. It takes 500 555, then the next getline takes "Acorn" and the next inputFile >> amountDue[1] takes 1500 23.

void loadArrays(string address[], double amountDue[], const int SIZE)
{
//Open file for data laoding
ifstream inputFile;
inputFile.open("Prog3Input.txt");

for (int i = 0; i < SIZE; i++)
{
    getline(inputFile,address[i]);
    inputFile >> amounDue[i];
}
}

I expected: string address[0] is "123 Main"
int amountDue[0] is 500
address[1] is "555 Acorn"
amountDue[1] is 1500
ETC.

I am getting: address[0] is "123 Main"
amountDue[0] is 500 555
address[1] is "Acorn"
amountDue[1] is 1500 23
ETC

1 Answers1

1

the inputFile >> amountDue[0] recieves more than the 500 integer. It takes 500 555

No, it doesn't. That it not how the operator>> works. It stops reading on the first character that does not fit in an integer, which includes whitespace and line breaks.

So, it reads just the 500, then the next getline() finishes the integer line and returns a blank string, then the next >> reads the number of the address line, then the next getline() finishes the address line. And so on.

That said, your code is not accounting for the line breaks after each integer. You need to update your code in one of the following ways:

  • use std::istream::ignore() to skip the rest of the line until the line break.

    #include <string>
    #include <fstream>
    #include <limits>
    
    void loadArrays(std::string address[], double amountDue[], const int SIZE)
    {
        //Open file for data loading
        std::ifstream inputFile("Prog3Input.txt");
    
        for (int i = 0; i < SIZE; i++)
        {
            std::getline(inputFile, address[i]);
            inputFile >> amountDue[i];
            inputFile.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
        }
    }
    

    Live demo

  • always use std::getline() to read each line, and then use std::istringstream to parse the integers.

    #include <string>
    #include <fstream>
    #include <sstream>
    
    void loadArrays(std::string address[], double amountDue[], const int SIZE)
    {
        //Open file for data loading 
        std::ifstream inputFile("Prog3Input.txt");
        std::string line;
    
        for (int i = 0; i < SIZE; i++)
        {
            std::getline(inputFile, address[i]);
            std::getline(inputFile, line);
            std::istringstream(line) >> amountDue[i];
        }
    }
    

    Live demo

Remy Lebeau
  • 454,445
  • 28
  • 366
  • 620
  • The second solution here is giving me the right data for the string arrays, but not the intergers. It is filling amountDue with the first integer for each spot (so all are appearing as 500). – computerilliterate Sep 07 '19 at 04:46
  • Why not a while loop validating each with `&&` to prevent a partial? – David C. Rankin Sep 07 '19 at 04:48
  • @computerilliterate that is simply not possible given the data you have shown – Remy Lebeau Sep 07 '19 at 04:48
  • Just tried the first solution and I'm getting the same result. As not possible as it is, that's what it's doing. The same way that even in the integer array it was displaying "500 555". I'm not getting errors that make sense. – computerilliterate Sep 07 '19 at 04:53
  • @computerilliterate I have added links to my answer to prove the code I have showed works properly for the data you have shown. And it is *physically impossible* for `500 555` to be read into a single integer/double in one go. So either the data you have shown here is not the real data you are actually working with, or you are not reading the data correctly. – Remy Lebeau Sep 07 '19 at 04:57
  • Just kidding, found an error in my cout statements. Thank you! The solution you gave worked, but I still don't understand why my code didn't. (I am obviously brand new; this is my second semester in a c++ class) – computerilliterate Sep 07 '19 at 04:58
  • @computerilliterate I explained why your original code did not work, and even linked your question to another question that also explains why. – Remy Lebeau Sep 07 '19 at 05:00
  • Sorry I wasn't getting it at first. Starting to make sense now, just didn't add up to what I was seeing (I'm using larger arrays in the actual code but I'm seeing it pan out now how you explained). Thanks again! – computerilliterate Sep 07 '19 at 05:03
  • 1
    While you are free to read values into two separate arrays, whenever you need to coordinate different data-types as a single-object, you should be thinking `struct` or `class`. That way you can combine both your `string` and `double` as members of the `struct` (or `class`) and then create a single `vector` of struct to handle your data. (it makes things much simpler in the long run) – David C. Rankin Sep 07 '19 at 05:12
  • This is for a homework assignment at the beginning of a level 2 C++ class; we haven't covered those yet but I will definitely look into them! – computerilliterate Sep 07 '19 at 16:28