Reading an arbitrary array of any size

The following code works fine when reading two .txt files containing two 5X5 arrays.

    #include <iostream>
    #include <string>
    #include <fstream>
    #include <sstream>
    #include <stdio.h>
    #include <vector>
    #include <sstream>

    using namespace std;

    int main()
    {
        string myFile, mysecondFile, mystring;
        string DIR;
        string extension;
        int total = 0;

        int number_of_lines = 0;
        string line;

        extension = ".txt";
        DIR = "H:\\Year2\\EE273\\EE273\\Week6\\";

        cout << "Enter the name of the file: \t";
        cin >> myFile;
        cout << "Enter the name of the second file: \t";
        cin >> mysecondFile;

        myFile = DIR + myFile + extension;
        mysecondFile = DIR + mysecondFile + extension;

        ifstream inFile;
        ifstream inFile2;

    int i=5;
    int j=5;
    int i2=5;
    int j2=5;
    int i3=5;
    int j3=5;
    int k;
    int l;

int Array[5][5];
int Array2[5][5];
int Array3[5][5];
string attempt1,attempt2;
int row = 0;
int col = 0;
int row2 = 0;
int col2 = 0;//i = row
                    //y = column

inFile.open(myFile.c_str());


if (!inFile) {
    cout <<"Error opening file"<<myFile<<endl;
    return -1;
}

while (!inFile.eof())
{
    getline(inFile, attempt1);
    stringstream iss( attempt1 );
    string result;
    col = 0;
    while (getline( iss, result, ','))
    {
        //cout << result << endl;
        Array[row][col] = atoi(result.c_str());
        //j = j + 1;
        col = col + 1;

    }
    row = row + 1;
}
inFile.close();

inFile2.open(mysecondFile.c_str());
if (!inFile2) {
    cout <<"Error opening file"<<mysecondFile<<endl;
    return -1;
}
while (!inFile2.eof())
{
    getline(inFile2, attempt2);
    stringstream iss( attempt2 );
    string result2;
    col2 = 0;
    while (getline( iss, result2, ','))
    {   
        //cout << result2 << endl;
        Array2[row2][col2] = atoi(result2.c_str());
        col2 = col2 + 1;
    }
    row2 = row2 + 1;
}
inFile2.close();

/*for (int i=0;i<5;i++){
    for (int j=0; j<5; j++){
        cout<<Array[i][j]<<endl;}}
for (int i2=0;i2<5;i2++){
    for (int j2=0; j2<5; j2++){
        cout<<Array2[i2][j2]<<endl;
    }}

      

Here I am performing a multiplication between two matrices and writing the resulting values ​​into a third matrix.

int Total=0;
i=0;
j2=0;
j=0;
j3=0;
for (i3=0; i3<5; i3++) {
    while(j3<5){
            while (j<5){
            for (i2=0;i2<5;i2++){
            Total += Array[i][j]*Array2[i2][j2];
            j++;
            Array3[i3][j3]=Total;

            }}
            j=0;
            j2++;
            j3++;
            Total=0;
            }
    i++;
    j=0;
    j2=0;
    j3=0;
    Total=0;
}

      

My question is, what's the simplest way to change the code so that it can read two .txt files containing an array of any size , and then multiply successfully?

EDIT I ​​have to do this only using arrays, unfortunately I cannot use vectors.

Did I understand correctly that the new operator is involved ?

+3


source to share


3 answers


The "easiest" way is to do something naive, like reading the file completely to get the number of rows / columns, and then reading the file again to actually store the values ​​in the matrix:

unsigned int rows = 0;
unsigned int cols = 0;

std::string line;
while (std::getline(inFile, line)) {
    rows++;
    std::stringstream ss(line);

    std::string col;
    while (std::getline(ss, col, ',')) {
        cols++;
    }
}

// Now allocate the rows*cols matrix
int** matrix = new int*[rows];
for (int i = 0; i < rows; i++) {
    matrix[i] = new int[cols];
}

// and read your values into the matrix ...
// matrix[m][n] = xxx

      

It is rather inefficient to read the file twice; and there are other ways to get the size in advance. For example, you might have a convention in your input file to include the width / height of the matrix before the data:

[infile.txt]
3,3
1,2,3
4,5,6
7,8,9

      



Now you can read the first line of the file and you will realize that the rest of this file contains a 3x3 matrix. Highlight your matrix with new

(similar to the example above), then continue reading the rest of the file.

Remember to clean up dynamically allocated matrices using delete[]

. There new

must be 1 call for each call delete

.

for (int i = 0; i < rows; i++) {
    delete[] matrix[i];
}
delete[] matrix;

      

+3


source


Use std::vector

raw arrays instead. For example. you can push_back

element on a vector. And more importantly, you can create it with a size only known at runtime, for example. from the information in the file.



+1


source


The simplest approach requires that the file contains the size of the matrix as the first records. That being said, you can opt out of using C (C ++ does not carry dynamically sized matrices) and do the following:

  • Read the dimension of the matrix in variables width

    and heigh

    .

  • Highlight the matrix with

    int (*dynamicMatrix)[width] = malloc(height*sizeof(*dynamicMatrix));
    
          

  • Reuse your code to populate the matrix.

If you can't go back to C and can't use std::vector<>

, you only have to use a double pointer:

int**dynamicMatrix = new int*[height];
for(size_t i = width; i--; ) dynamicMatrix[i] = new int[width];

      

Again, this is easiest if you can define the first two numbers in the file to contain the width and height of the matrix in the file. If you cannot encode these two numbers into your file, then you need to increase the dynamic arrays:

size_t lines = 0, allocatedLines = 8;
int** dynamicMatrix = new int*[allocatedLines];
while(/* can read a line */) {
    if(lines == allocatedLines) {
        int** temp = new int*[allocatedLines *= 2];
        for(size_t i = lines; i--; ) temp[i] = dynamicMatrix[i];
        delete[] dynamicMatrix;
        dynamicMatrix = temp;
    }

    //add one line
    size_t curLineLength = 0, allocatedLineLength = 8;
    dynamicMatrix[lines++] = new int[allocatedLineLength];

    //fill the line
    ...
}

      

A similar block for redistributing a line should go into a loop in which you read the elements of one line. It's tiresome; but the only way to get better is to use material that you are not allowed to use.


Btw: even redistributing stuff is easier in C since it provides a function realloc()

:

size_t lines = 0, allocatedLines = 8;
int** dynamicMatrix = malloc(allocatedLines * sizeof(*dynamicMatrix));
while(/* can read a line */) {
    if(lines == allocatedLines) {
        //realloc takes care of copying the data to a new location (if that is necessary):
        allocatedLines *= 2;
        dynamicMatrix = realloc(dynamicMatrix, allocatedLines * sizeof(*dynamicMatrix));
    }

    //add one line
    size_t curLineLength = 0, allocatedLineLength = 8;
    dynamicMatrix[lines++] = malloc(allocatedLineLength * sizeof(**dynamicMatrix));

    //fill the line
    ...
}

      

Since there is no equivalent to work with new

/ , you need to either use in C ++ or copy as above.delete

realloc()

std::vector<>

+1


source







All Articles