How I put in a 2D array data from a file?

Greetings.
I want to put the data from a file of 10 rows with 5 data each row in an 2D array of the same size (30X15) but I don't know how, I would appreciate any help.
I have this:
1
2
3
4
5
6
7
8
9
10

FILE *READ;
READ=fopen("wctt.dat","r");
char s1[10][5];
for(int i=0; i<10; i++){
for(int k=0; k<5; k++){

fscanf( READ,"%s", s1[i][k]);
}
}

The file looks like this:
1 2 3 4 5
6 7 8 9 10
11 12 13 14 15
16 17 18 19 20
21 22 23 24 25
26 27 28 29 30
31 32 33 34 35
36 37 38 39 40
41 42 43 44 45
46 47 48 49 50

PD: The original file data is actually decimal.
Last edited on
We need to see a sample of the data to understand its format.
you have s when you mean i for the read. but you can unravel this one to a 1-d loop. If you prefer not to do that, the i vs s thing is all you needed.

char* cp = &(s1[0][0]);
for(int j = 0; j < 50; j++)
fscanf(READ, "%i", cp[j]);

if you meant s, and wanted the text of the numbers ("50" is very different from 50) you need a 3-d array of char (1d for rows, 1d for cols, and 1-d for c-strings)
Last edited on
@jonnin, best make that an int array if you're reading integers (since scanf will write an int's worth of bytes to the given address). If he really wants to store small ints into chars then you could read it into an int and assign it to the char element. Alternatively, you could use one of the fancy newer format specs (SCNd8 in <inttypes>).

It's also probably best to use %d instead of %i since the latter will interpret a value starting with a zero as octal, generally not what people expect.
Last edited on
Cleaning up the variable names as well, here is the advice given to you as a complete code snippet:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
const int ROWS = 10;
const int COLS = 5;
int data[ROWS][COLS];
{
  FILE * f = fopen("wctt.dat","r");
  if (!f) fooey();  // always check for failure!
  for (int row=0; row<ROWS; row++)
  {
    for (int col=0; col<COLS; col++)
    {
      if (fscanf( f, "%d", &(data[row][col]) ) != 1)
      {
        fclose( f );
        fooey();
      }
    }
  }
  fclose( f );
}
// Ta-da! data[][] is loaded from file! 

The magic “fooey()” function should be replaced by whatever you wish to do to handle an error reading from file.

If you wish to load the data as strings, make sure to provide sufficient space for those strings. In your example, you need at minimum three characters for each string, and your scanf() should specify a maximum string size:

 
char data[ROWS][COLS][3];
 
      if (fscanf( f, "%2s", data[row][col] ) != 1))

Notice that there is space for three characters (two for the one- or two-digit number, and a third for the terminating null character), and that the scanf() asks to read 2 characters (the terminating null will be written in addition to the maximum 2 characters read).

It is always a really good idea to read the documentation for the functions you are using, especially tricky ones link the scanf() family:
https://en.cppreference.com/w/cpp/io/c/fscanf

Hope this helps.
To read the integer values and store them in a char array, use a temporary. Modifying your original code:
1
2
3
4
5
6
7
8
9
10
FILE *READ;
READ=fopen("wctt.dat","r");
char s1[10][5];
for(int i=0; i<10; i++){
    for(int k=0; k<5; k++){
        int tmp;
        fscanf( READ,"%i", &tmp);
        s1[i][k] = tmp;
    }
}
I have tried to execute several codes already compiled and I get in the terminal: "segmentation fault ('core' dumped)"
Last edited on
lll wrote:
PD: The original file data is actually decimal.

What do you mean by that?


lll wrote:
a file of 10 rows with 5 data each row in an 2D array of the same size (30X15)

I'm clearly missing something there, too.
Last edited on
A “segmentation fault” is the OS’s way of informing you that you tried to access memory that you are not allowed to touch.

Notice that in everyone’s code here we have used the & to get the address of the object you are trying to read with fscanf(). Your code lacks that very important piece. Again, read the docs.

If you want to read something (an integer, say) from file, you have to tell fscanf() where to put the result.

1
2
3
int n;
if (fscanf( f, "%d", &n ) != 1)
  FOOEY;

If you wish to read a double, the same applies:

1
2
3
double x;
if (fscanf( f, "%lf", &x ) != 1)
  FOOEY;

The same applies for c-strings as well. The only difference is that the c-string is already addressed via pointer:

1
2
3
char s[100];  // 's' decays to a pointer, pointing to the first character to store
if (fscanf( f, "%99s", s ) != 1)
  FOOEY;

The more explicit way to write it would be:

1
2
3
char s[100];
if (fscanf( f, "%99s", &(s[0]) ) != 1)
  FOOEY;

Finally, notice how I use the very same structure every time. Attempt to read a single item, check that the read succeeded, and if not, bail. Again, “FOOEY” is just a place-holder for however you wish to handle the read error. Make sure to close the file.

Learning to do I/O in C is a pain, but once you get the basics it is pretty straight-forward.
Hope this helps.
Topic archived. No new replies allowed.