1

I am reading data from a file, retrieving how many columns and rows I have ( data file ), everything of so far. Now I am trying to read the values one by one and store the values in to a 2D array (double). I get the values as char using getc but when I try to use atoi or atof to convert the values from char to double i get strange values.

double ther[j][number];
char c;
int tim=0,nther=0;


FILE *fp3 = fopen("data.txt", "r");
c = getc(fp3) ;

while (c!= EOF)
{ 

    ther[tim][nther]=atoi(&c);
    printf("%lf", ther[tim][nther]);


    nther++;
    c = getc(fp3);

    if(nther==number)
    {
        tim++;
        nther=0;
    }
    tim=0;
}

fclose(fp3);

any suggestion?… (i keep searching). Sorry well i have a file data.txt and this file has rows an columns of numbers:

1 2 3 4 5

6 7 8 9 10

So i need to store the data into a 2D array: Thanks to the answers i have some ideas like: use an string, then divide all values and stored every one of them. 1st line is string-> array[0][0], array[0][1], etc. Then move to the other row and do the same.

Until now i get some numeric values but none of them are stored at the data.txt.

Chris Martin
  • 30,334
  • 10
  • 78
  • 137
mrmurmanks
  • 33
  • 12

3 Answers3

1

You can read a double from a file using fscanf. An example would be:

double d;
fscanf("%f", &d);

fscanf can do much more than that so I'd recommend checking the documentation.

The method you're using gets a single character (as Matt McNabb pointed out - incorrectly). A character is 1 byte and can store the values 0-255. You're reading in text mode since you don't specify a mode with fopen (it is generally considered a good practice to explicitly ask for either binary "rb/wb" or text "rt/wt" mode). This means you read the ASCII value of a single digit.

So let's say the file contains:

7.2, 3.0, 1.0

The first call to getc(fp3) would get the character '7' which would have a value of 55 for ASCII. Obviously this is not going to give you what you're looking for.

Instead you could use:

double d[3];
fscanf("%f, %f, %f" &d[0], &d[1], &d[2]);

Which would get the three float values in the file.

Peter Clark
  • 2,863
  • 3
  • 23
  • 37
  • In fact i am trying to avoid fscanf because o do not want to store the values in a single line. But you gave me some ideas :). – mrmurmanks Mar 28 '14 at 05:12
  • That was just an example, you can always read in one value at a time, or use a format specifier that includes newlines (assuming you know whether your file uses '\n' or "\r\n" for new lines). For example: `fscanf("%d\n%d\n%d", ...)` would read the same values if they were each on their own line. You can adjust the format specifier to fit your needs. Bear in mind that you should also error check the return value of fscanf to verify that it actually read as many values as you expect. I'd recommend keeping [a reference to cstdio.h](http://www.cplusplus.com/reference/cstdio/) open while you learn. – Peter Clark Mar 28 '14 at 05:23
  • oh yes, so i can use fscanf to read a complete line? and divide the line later i suppose. something like: fscanf (pFile, "%s", str); and then work with the string :) – mrmurmanks Mar 28 '14 at 05:29
  • 2
    From the documentation for the [`scanf` `%s` format specifier](http://www.cplusplus.com/reference/cstdio/fscanf/): "Any number of non-whitespace characters, stopping at the first whitespace character found." So no, `%s` would only get a **single token delimited by whitespace**. If you want a whole line you would want [fgets](http://www.cplusplus.com/reference/cstdio/fgets/). Note that you can use `fgets` and `sscanf` (the string member of the scanf family) together to get a whole line then break it up into tokens. – Peter Clark Mar 28 '14 at 05:45
1

Firstly, it should be int c;. The getc() function has to be able to return a different value for all possible chars, and also a different value EOF (which signifies end-of-file, or stream error).

If you use char c;, then you must end up with EOF being converted to the value of a legal character, so you can't tell the difference between the two cases. In other words, your code might act like it hit EOF when in fact it just hit that particular character.

Moving on, atoi(&c) is not correct. If you read the documentation for the atoi function -- this is always a good idea when using functions -- you will find that it expects a string as input. However, &c is not a string. It is the address of a single char.

So your options are:

  • construct a string and pass it to atoi
  • don't use atoi

You didn't say what you were expecting to happen; but if you want to convert the character you read in of '3' to be the integer 3 then you can write: ther[tim][nther] = c - '0';.

However you should also have some code to handle cases when you read something that was not a number.

If you wanted to read in more than one character at a time (e.g. "31" -> 31) then the approach of using getc is not appropriate - you'll need to switch to using a function that reads multiple characters at once, such as fscanf or fgets.

Finally, you set tim to 0 every single loop iteration, so the tim++ never has any lasting effect, maybe this was an oversight.

M.M
  • 138,810
  • 21
  • 208
  • 365
  • Sorry, i am trying to read a number 3 and store the same number in the array. – mrmurmanks Mar 28 '14 at 05:11
  • 1
    Do you also want to read things like `31` or `3.1`, or is the whole file just numbers from `0` through `9` ? – M.M Mar 28 '14 at 05:21
  • Yes it must read several numbers, but all of them are integers ( maybe later will read float ). – mrmurmanks Mar 28 '14 at 05:23
  • Maybe this will help me… while( fgets ( line, sizeof(line), fp3 ) != NULL ) and then inside the while can i divide the string. line is a pointer to some string ( a line on the file ). – mrmurmanks Mar 28 '14 at 05:27
  • 1
    That'd be one way to do it, yes. You could divide up the string with careful use of `sscanf` or `strtod`. – M.M Mar 28 '14 at 05:34
0
#include <stdio.h>

int main(){
    int j = 2;
    int number = 5;

    double ther[j][number];
    double d;
    int tim=0,nther=0;
    FILE *fp3 = fopen("data.txt", "r");

    while (fscanf(fp3, "%lf", &d)==1){
        ther[tim][nther]=d;
        printf("%g ", ther[tim][nther++]);

        if(nther==number){
            ++tim;
            nther=0;
            printf("\n");
        }
    }
{
    int r, c;
    for(r=0;r<tim;++r){
        for(c=0;c<number;++c){
            printf("%f ", ther[r][c]);
        }
        printf("\n");
    }
}
    return 0;
}
BLUEPIXY
  • 39,699
  • 7
  • 33
  • 70
  • i was searching for a clue at my code and i remembered your post :) (pretty helpful), thanks pixy (pixy from ace combat?), who knows :). Muchas gracias desde el otro lado del pacifico pixy :D – mrmurmanks Apr 20 '14 at 03:38