Jaden
Jaden

Reputation: 375

Reading data from a file and storing each line in an array?

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();
}

Upvotes: 1

Views: 1183

Answers (3)

paddy
paddy

Reputation: 63481

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 );

Upvotes: 2

Remy Lebeau
Remy Lebeau

Reputation: 598001

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;
    }
}

Upvotes: 1

Raindrop7
Raindrop7

Reputation: 3911

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();
}

Upvotes: 0

Related Questions