Home > front end >  Read arrays of different length from multiple line file in C
Read arrays of different length from multiple line file in C

Time:11-26

I have a file, which looks like this:

0 0 1 4 6 17 43 20 21 7 0 1 6
0 2 1 9 14 16 79 283 35
1 0 1 2 2 0 0 0 0 0 0 1 4 0 3 5 7 9 11 4 1 30
1 1 0 1 5

And more lines which are of different length. I would like to read first line into an array, do something with this array and then read next line into array again (so a loop) and work with this array too. In summary - at one time I would like to have an array of values from one line.

Is it possible to do it with array, not vector?

Code like this works for me, but I have a problem with adding reading next line here

int size = 13;
int arr[SIZE];

string inFileName = "file.txt";
ifstream inFile;
inFile.open(inFileName.c_str());

if (inFile.is_open())  
{
    for (int i = 0; i < size; i  ) 
    {
        inFile>>arr[i];
        cout<<arr[i] << " ";
    }
    inFile.close(); 
}

size is not a problem for me, I can read it from another file, for each line.

Thanks in advance!

CodePudding user response:

Is it possible to do it with array, not vector?

Yes it is possible to do it with array but for that you must know the the exact number of elements in each line and also how many lines are there in the file. A better alternative would be to use std::vector<>.

From your description it seems that you want to process the array/vector after reading the file. For this you can use a 2D std::vector as shown below.

Also your program has two variables one named size and other named SIZE. For specifying the size of the array you have used SIZE instead of size. But from your code we can't infer the type of SIZE but only the type of size. In case you meant to use a single size variable instead of 2 different ones with one in capital and other in small letters, your program will not be a standard C program because in C the size of any array must be a compile time constant. So take for instance:

int SIZE = 13;
int arr[SIZE];//INCORRECT because variable SIZE is not a constant expression

The correct way to write the above would be:

const int SIZE = 13;
int arr[SIZE];//CORRECT

But if want to use array you must know how many rows(lines) and columns(elements) will be there in the input file, which is not suitable.

You can use a std::vector for storing information(like integers values in this case) in 2D manner. After reading all the values from the file you can process the vector according to your needs. The advantage of using std::vector is that you don't have to know the number of rows and columns beforehand in your input file. So you don't have to allocate memory beforehand for rows and columns. You can add the values dynamically. The below program read data(int values) from input.txt and store those in a 2D vector.

#include <iostream>
#include <vector>
#include <string>
#include <sstream>
#include<fstream>
int main() {
    std::string line;
    int word;

    
    std::ifstream inFile("input.txt");
    
    //create/use a std::vector instead of builit in array 
    std::vector<std::vector<int>> vec;
    
    if(inFile)
    {
        while(getline(inFile, line, '\n'))        
        {
            //create a temporary vector that will contain all the columns
            std::vector<int> tempVec;
            
            
            std::istringstream ss(line);
            
            //read word by word(or int by int) 
            while(ss >> word)
            {
                //std::cout<<"word:"<<word<<std::endl;
                //add the word to the temporary vector 
                tempVec.push_back(word);
            
            }      
            
            //now all the words from the current line has been added to the temporary vector 
            vec.emplace_back(tempVec);
        }    
    }
    
    else 
    {
        std::cout<<"file cannot be opened"<<std::endl;
    }
    
    inFile.close();
    //now you can do the whatever processing you want on the vector

    //lets check out the elements of the 2D vector so the we can confirm if it contains all the right elements(rows and columns)
    for(std::vector<int> &newvec: vec)
    {
        for(const int &elem: newvec)
        {
            std::cout<<elem<<" ";
        }
        std::cout<<std::endl;
    }
    
    
    
    return 0;
}

The output of the above program can be seen here. The input file through which int values are read is also given at the above mentioned link.

CodePudding user response:

TLDR:

You could, but you have to know at least a maximum number of elements in each line, and then you create a buffer that would potentially have unused space in it.

PS:

You then could put it inside a vector at once if you fear the repeated emplace_back function.

But you shouldn't fear emplace_back function that much, since std::vector does a smart thing:

It at some point decides, that it will reserve twice as much space it already uses. This approach will minimize the number of reallocations so that on avarage the time it spends doing emplace_back is O(1) (constant speed)

Disclaimer:

There are cases you can screw up the efficiency of a vector (probably not with ints tho), but in most times it can be mitigated. Many cpp conference talks and many blog posts and so on were made on that topic.

  • Related