1

I have a file with lines of integers. I want to read each line into a slot in my array. I have the code below, but it does not work. I'm not sure if I'm on the right track.

void Read_Save() {
    ifstream in;
    int arr[100];
    string line;
    in.open("file.txt");
    while (in.peek() != EOF)
    {
        getline(in, line, '\n');
        strcpy(arr, line.c_str());
    }
    in.clear(); in.close();
}
2
  • 2
    you cannot input an array of integer with strcpy Commented Nov 11, 2016 at 0:32
  • 2
    While while (in.peek() != EOF) will work, and good on you for not falling into the test for EOF before reading EOF trap, you may find while (getline(in, line, '\n')) better because it save you the peek and catches more failure cases than just EOF. Commented Nov 11, 2016 at 0:43

3 Answers 3

2

There are several ways to parse the integer value out of the string.

First, let's fix your loop:

int pos = 0;
while( std::getline(in, line) && pos < 100 )
{
    int value = 0;

    // Insert chosen parsing method here

    arr[pos++] = value;
}

Here is a non-exhaustive list of common options:

  1. Use std::strtol

    // Will return 0 on error (indistinguishable from parsing actual 0)
    value = std::strtol( line.c_str(), nullptr, 10  );
    
  2. Use std::stoi

    // Will throw exception on error
    value = std::stoi( line );
    
  3. Build a std::istringstream and read from it:

    std::istringstream iss( line );
    iss >> value;
    if( !iss ) {
        // Failed to parse value.
    }
    
  4. Use std::sscanf

    if( 1 != std::sscanf( line.c_str(), "%d", &value ) )
    {
        // Failed to parse value.
    }
    

Now, note the bounds-test on the loop checking pos < 100. This is because your array has a storage limit. Actually, you have also overridden the global one with a local one in Read_Save, thus hiding it with a smaller array that will be lost when the function finishes.

You can have an arbitrary-sized "array" (not actually an array) using other container types provided by the standard library. Useful ones that provide random access are std::vector and std::deque. Let's use the vector and change the definition of Read_Save to be a bit more useful:

std::vector<int> Read_Save( std::istream & in )
{
    std::vector<int> values;
    std::string line;

    for( int line_number = 1; getline( in, line ); line_number++ )
    {
        try {
            int value = std::stoi( line );
            values.push_back( value );
        }
        catch( std::bad_alloc & e )
        {
            std::cerr << "Error (line " << line_number << "): Out of memory!" << std::endl;
            throw e;
        }
        catch( std::exception & e)
        {
            std::cerr << "Error (line " << line_number << "): " << e.what() << std::endl;
        }
    }

    return values;
}

And finally, the call becomes:

std::ifstream in( "file.txt" );
std::vector<int> values = Read_Save( in );
Sign up to request clarification or add additional context in comments.

Comments

1

You cannot use strcpy() to convert a string to an integer. You can use std::strtol() or std::stoi(), or even a std::istringstream, eg:

int arr[1000];

void Read_Save() {
    ifstream in;
    string line;
    in.open("file.txt");
    int index = 0;
    while ((index < 1000) && (getline(in, line)))
    {
        if (istringstream(line) >> arr[index])
            ++index;
    }
}

2 Comments

I like the way you did it. I get this error though Error C2027 use of undefined type 'std::basic_istringstream<char,std::char_traits<char>,std::allocator<char Not sure how to fix it.
Did you add the include for istringstream? I mean #include <sstream>
0

The best thing to do in your case is to use std::vector. The code would look like this:

void Read_Save()
{
    std::ifstream in("file.txt");
    int value;
    std::vector<int> arr;

    while (in >> value)
        arr.push_back(value);

    for(int i(0); i < arr.size(); i++)
        std::cout << arr[i] << ", ";

    std::cout << std::endl;
    in.close();
}

1 Comment

Alternatively, you can replace the manual while loop with std::copy() using std::istream_iterator and std::back_inserter as the iterators, eg: std::copy(std::istream_iterator<int>(in), std::istream_iterator(), std::back_inserter(arr));

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.