tags:

views:

55

answers:

3

I have been trying to read in integers from a file do some operations and output them to another file. When I input the integers into an array and then print out the result of come up with random numbers. Is this something to do with ifstream that I don't understand or am I missing something obvious?

#include<iostream>
#include<fstream>
using namespace std;

int main(){
    int i=0, test[100];
    ifstream reader("in.txt");
    while(!reader.eof()){
        reader>>test[i];
        i++;
    }
    for(int x=0; test[x]!=-1; x++)
        cout<<test[x]<<endl;
    return 0;
}

in.txt sample:

1 4 3 2 9 8 18 22 0
2 4 8 10 0
7 5 11 13 1 3 0
-1

the 0 and -1 are sentinels for eol and eof respectively

If there is a much simpler way of doing this I would also like to know that. I am rather new to C++ and am hating the way arrays behave vs other languages.

+1  A: 
sizeof(test)/sizeof(test[0])

This is a compile-time computation: it will always result in 100. If you want to know how many integers you actually read, you need to keep track of that yourself (or use a container that keeps track of it for you, like a std::vector).

In addition, testing .eof() in the loop condition is incorrect and the loop will not terminate at the correct time. If an extraction fails, the fail state on the stream will be set and further extractions will fail. The correct way to do this is:

// make sure to test the array bound and test that the extraction succeeded:
while((i < 100) && (reader >> test[i])) 
{
    i++;
}

You can then test the state of the stream to determine whether the loop ended due to an extraction failure or because EOF was reached. If neither was the case, then i should be 100 and you'll have filled the array.

You can read this article for details as to why this is the correct way to do this.

James McNellis
A: 

Use a vector rather than a array.

vector<int> test

Are there actually 0's and a -1 in the file's text? I may misunderstand you on that point, but they shouldn't literally be in the text file.

So, try this:

#include<iostream>
#include<fstream>
#include<vector>
using namespace std;

int main(){
    int i=0, tmp;
    vector<int> test;
    ifstream reader("in.txt");
    while((i < 100) && (reader >> tmp)) 
    {
        test.push_back(tmp);
        i++;
    }
    for(int x=0; x < test.size(); x++)
        cout<<test[x]<<endl;
    return 0;
}

Your biggest flaw in your code is that you're using the size of the array after you set it to 100. This isn't the same as the number of integers read in, so it'll keep printing all 100 items in the array.

Edit added suggestion from other answer

JoshD
There is no need to limit `i` to 100 if you're using a vector. In fact, you don't even need `i` at all.
Paul
+1  A: 

The obvious simpler way would be to use std::vector:

#include <vector>
#include <iostream>
#include <algorithm>
#include <numeric>
#include <fstream>
#include <iterator>

int main() { 
    std::vector<int> test;
    std::ifstream reader("in.txt");

    // read the data into the vector:
    std::copy(std::istream_iterator<int>(reader), 
              std::istream_iterator<int>(),
              std::back_inserter(test));

    // show the data in the vector:
    std::copy(test.begin(), 
              test.end(), 
              std::ostream_iterator<int>(std::cout, "\t"));

    // Just for fun, display the average of the numbers:
    std::cout << "Mean = " 
              << std::accumulate(test.begin(), test.end(), 0) / test.size();

    return 0;
}
Jerry Coffin
This isn't reading the last line of the file.
cdbitesky
@cdbitesky: It certainly should. My guess is that you've mixed this with some other code that *skips* dealing with that last line that was read, because your original code (with `while (!reader.eof())`) appeared to read the last line twice.
Jerry Coffin