Hi,

i have the following text file and i need to put inside a 2D array without knowing number of rows and columns in the text file. (i want C to count this also)

i've tried something like that:

for (int r = 0; r<2; r++)
{
for (int c = 0; c < 4; c++)
{
    myFile >> spaceLayout[r][c];
}
}

but in this case the array should be preallocated. what i want is an automatically allocated array depending on the size of the text file.

the file contain something like that:

 1859 1974 726 1684 3048 6243
1853 1896 763 1738 3298 6250
2011 1715 877 1647 3548 6250
2125 1769 648 1685 4213 6227
2047 1858 661 1681 4463 6247
2272 1839 486 1653 4713 6250
2219 1843 497 1616 4963 6175
1679 1420 1234 1901 5648 6234
1522 1851 1060 1817 5898 6250

thank you for your help

You'd have to resize your 2-dimensional array as you read the file. Initially you should allocate the array dynamically using malloc(). Then read from the file and when you run into array boundaries expand it using realloc().

Then read from the file and when you run into array boundaries expand it using realloc().

An alternative would be a two pass algorthm that counts the number of lines and maximum number of columns for the first pass, then allocates the array and populates it in the second pass. That way you avoid expensive calls to realloc(). Whether this is more efficient would need to be tested though, as reading from a file can be expensive as well. ;)

I think the two pass solution is cleaner and would be easier to understand for a beginner.

i tried this to count the number of rows but it's just printing in an infinite loop
at least it should print the number of rows in a sequence.

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


using namespace std;

int main()
{   
    string line;    
    int i=0;
    ifstream inputFile;
    inputFile.open("output/alignskewresultsgenesnormal.txt", ios::in);

    while(!inputFile.eof())
    {
    i++;
    getline(inputFile, line, '\n');
    cout<<i;
    cout<<line;

    }

}

but it's not prining the line nor the line number. why ??

Try this instead:

#include <fstream>
#include <iostream>
#include <string>

using namespace std;

int main()
{
    ifstream in("output/alignskewresultsgenesnormal.txt");

    if (in) {
        string line;
        int n = 0;

        while (getline(in, line)) {
            cout << line << '\n';
            ++n;
        }

        cout << n << " lines detected" << endl;
    }
    else {
        cout << "Error opening file" << endl;
    }
}

I want to rule out issues with the broken use of eof() as a loop condition and make sure that errors are properly checked.

p.s. Your code is C++. Should I move this thread to the C++ forum, or are you really trying to write C?

Edited 4 Years Ago by deceptikon

no i'm really trying to write in C, but this is my first time i try to do it.

I think the two pass solution is cleaner and would be easier to understand for a beginner.

Probably. Not sure about performance though especially if you want to consider rows not necessarily have the same amount of items. (You'd have to allocate every row size to the size of the row containing most elements. You'd then have to track the amount of occupied slots per row or work with sentinal values which might not also be possible. (although he does only mention positive integers)

To keep it simple, here's example code you can use to read in a file with the folowing format:

1859 1974 726 1684 3048 6243
1853 1896 763 1738 3298 6250
2011 1715 877 1647 3548 6250
2125 1769 648 1685 4213 6227
2047 1858 661 1681 4463 6247
2272 1839 486 1653 4713 6250
2219 1843 497 1616 4963 6175
1679 1420 1234 1901 5648 6234
1522 1851 1060 1817 5898 6250

More specifically the code assumes the following for correct functioning:

  • Every row contains an equal amount of numbers.
  • Every line ends with a newline. (to be more realistic I allowed the last line to not end in a newline)
  • Values are seperated by a single whitespace. (space or newline)

I did not assume the amount of rows is equal to the amount of columns as this is not the case in your example either. Many of these points are easy to adjust but they would make the code more complex which I didn't want to do for this example.

Taking these contraints it would look somewhat like the following:

#include <stdio.h>
#include <ctype.h>

int main(void)
{
    FILE *file  = NULL;
    int symbol  = 0,
        columns = 0,
        rows    = 0;

    // Attempt to open the file "file.txt" with reading persmissions.
    file = fopen("file.txt", "r");

    // It succeeded!
    if (file != NULL)
    {
        do
        {
            // Obtain a single character from the file.
            symbol = fgetc(file);

            // Read character by character to determine the amount of columns on the first row.
            // Because every number is followed by a whitespace this equals the amount of items on a row.
            if (rows == 0 && (isspace(symbol) || feof(file)))
            {
                columns++;
            }

            // Every row is followed by a newline. But the last one needn't be.
            if (symbol == '\n' || feof(file))
            {
                rows++;
            }
        }
        while (symbol != EOF);

        // Some error occurred during reading.
        if (ferror(file))
        {
            printf("Error on reading from file.\n");
        }
        // No errors occurred, print the results.
        else
        {
            printf("The file contains %d row(s) and %d column(s).\n", rows, columns);
        }

        // Close the file.
        fclose(file);
    }
    // Opening the input file failed.
    else
    {
        perror("Error on opening the input file");
    }

    return 0;
}

There's alternatives, for example reading whole lines. The problem with that is not knowing beforehand how big your buffer should be. (that's what you're trying to find out in the first place) This problem doesn't occur when reading character by character.

Edited 4 Years Ago by Gonbe

Hi, usually the files i'm dealing with have the same number of columns but different number of rows, so i think your approach will work good. but some of them are tab-separated. so i think i should only change some if in the code and it will work correctly. but now my problem is how to include the file inside a 2D array. i've tried

for (k = 0; k <rows+1; k++)
      {
          for (i = 0; i <columns+1; i++)
          {
            myarr[k][i] = fscanf(file);
          }
          //file >> endl;
      }

but i don't know which parameters i should give to fscanf other the file in order to creatre the 2D array from the file.

so i think i should only change some if in the code and it will work correctly

No change should be needed as I check for whitespaces, not for spaces. If multiple whitespaces may occur in a row you will have to adjust the code although it's minor. If you need help let me know.

but now my problem is how to include the file inside a 2D array.

You're going in the right direction. You should however watch out with how many times your loops iteratie. They both iterate one time too many now. You either have to replace '<' with '<=' or remove "+1".

As far as fscanf() goes, it requires a format string and memory addresses to place data in. The function description I linked contains information about character combinations possible and what they do. In your case you'll want:

fscanf(file, "%d", &(myarr[k][i]));

Edited 4 Years Ago by Gonbe

thank you, it's working. but when i try to print the array, it's printing number like this :

i used this :

 int myarr [rows] [columns];

    for (k = 0; k <rows; k++)
      {
          for (i = 0; i <columns; i++)
          {
            fscanf(file, "%d", &(myarr[k][i]));
            printf("%d\n", myarr[k][i]);
          }
          //file >> endl;
      }

but it's printing something like this :

 0
0
bfe68148
44c91a90
0
44e4dff4
0
0
bfe67cf0

and i also tried to use this outside the for loop :

 printf("%x\n", &myarr);

and i get this : bfad2d60
and even if i change the printf to %d or without & it still the same soem weird numbers.. what's the problem??

This article has been dead for over six months. Start a new discussion instead.