0

I am trying to read from a file and store it in a matrix using c. The code I have is

ReadSparseInput (int nvtxs,int nsize, double  vector[], int rowptr[] ,int colind [] , double values[])
{
    int index,row=0,column=0;
    int sparsity_value, nvtxs_local;
    int VECTOR_SIZE =50;
    double value;
    double  randvect[VECTOR_SIZE];
    int  length=0;
    char buf[BUFSIZ];
    FILE *fp;
    fp=fopen("/home/lopez380/Parallel/m10-A.ij", "r");
    index =0;
    nvtxs_local = 0;
    rowptr[0] = 0;
    char *p1;
    while ( !feof(fp))
    {
         // null buffer, read a line
        buf[0] = 0;
        fgets(buf, BUFSIZ, fp);
        // if it's a blank line, ignore
        if(strlen(buf) > 1) 
        {
            p1 = strtok(buf, " ");
            row=atoi(p1);
            #ifdef DEBUG
                fprintf(stdout, "Row : %d ", row);
            #endif
            p1 = strtok(NULL, " ");
            column=atoi(p1);
            #ifdef DEBUG
                fprintf(stdout, "column : %d ", column);
            #endif
            p1 = strtok(NULL, " ");
            value=atof(p1);
            #ifdef DEBUG
                fprintf(stdout, "value : %g\n ", value);
            #endif
        }

    }
    fclose(fp);

    #ifdef DEBUG
    printf("lFileLen = %d\n", length);
    #endif

}

The code works well when I take p1 and convert it to integer using atoi. But when I use atof to convert the value to float, I am getting a zero. my input looks like

0 0 1.76420546156578
0 3 -4.80876443295632
0 6 1.20260376970926
0 9 3.30693451100554
1 1 1.13901264701619
1 4 0.370358438592131
1 7 -0.551593262343761

After I read this input, when I print it I am getting

 Row : 0 column : 0 value : 0
 Row : 0 column : 3 value : 0
 Row : 0 column : 6 value : 0
 Row : 0 column : 9 value : 0
 Row : 1 column : 1 value : 0
 Row : 1 column : 4 value : 0
 Row : 1 column : 7 value : 0

when I use atoi , I get the following

Row : 0 column : 0 value : 1
 Row : 0 column : 3 value : -4
 Row : 0 column : 6 value : 1
 Row : 0 column : 9 value : 3
 Row : 1 column : 1 value : 1
 Row : 1 column : 4 value : 0
 Row : 1 column : 7 value : 0

Can someone please help me?

LGG
  • 528
  • 9
  • 21
  • 1
    Hi, Lopez - SUGGESTIONS: 1) input the line with `fgets()`, just like you're doing now. 2) Explicitly check for errors/null data in your `fopen()` and your `fgets()`. 3) Substitute `sscanf()` in place of atoi() and atof(). Do this so you can check for formatting errors. 4) You can forget about the `strtok()` stuff: sscanf() lets you parse all the variables in the string at once. 5) Let us know how it works for you :)! – paulsm4 Apr 18 '13 at 04:05

3 Answers3

1

I would strongly discourage you from using atoi() and atof(), unless your implementation provides error checking (e.g. atoi() and atof()" update errno.

I prefer fscanf(): illegal input can be detected by the return value.

EXAMPLE:

if (fscanf(fp, "%f", &f) == 1)
    ...all OK...
else
    ...EOF or conversion failure...
paulsm4
  • 114,292
  • 17
  • 138
  • 190
  • 3
    Some people discourage the use of `fscanf` as well. Since he's already `fgets`ing the line he could also use `sscanf`. – Kninnug Apr 18 '13 at 00:10
  • 1
    Agreed. I was really suggesting "use any appropriate member of the XXscanf() family". "sscanf()" would definitely be the more appropriate choice here, since he already input the string. PS: The OP should be checking for errors *everywhere* - especially "fopen()", too. – paulsm4 Apr 18 '13 at 00:12
  • 1
    An implementation that provides error checking for `atoi` and `atof` doesn't argue for using them; depending on it could make your code silently fail under other implementations. And how would you know when to check the value of `errno`? Functions that set `errno` also indicate errors in some other way; you need to set `errno` to `0`, *then* call the function, *then* check `errno`, but *only* if the call tells you it failed. `atoi` and `atof` don't return enough information to let you do that. – Keith Thompson Apr 18 '13 at 00:29
  • Thank you for your replies. I am reading from a file where the number of rows varies. Also, as I have to read the row and store each column in a different array I have used strtok. The first two column values are stored in integer array while the last one should be stored in a float array. I am not sure how scanf can be used int his case - Ms Lopez :) – LGG Apr 18 '13 at 00:55
  • 2
    The `scanf` family also lacks robust error checking. The best interface to use is `strtod`. – R.. GitHub STOP HELPING ICE Apr 18 '13 at 01:30
  • I think "%lf" should be used here rather than "%f" for the floating point values in question are of type `double`. – chux - Reinstate Monica Jun 28 '13 at 19:25
1

For reasons mentioned above, replace

value = atof(p1);

...with...

if( sscanf(p1,"%s",&value) != 1) { 
    fprintf(stderr,"Error: non-number found!\n");
    exit(1); 
}
JWDN
  • 382
  • 3
  • 13
0

The solution as paulsm4 described in the comment is

 fp=fopen("/home/lopez380/Parallel/m10.vec", "r");
    int i=0;
    double val;
    while ( !feof(fp))
    {
        buf[0] = 0;
        fgets(buf, BUFSIZ, fp);
        if(strlen(buf) > 1) 
        {
            p1 = sscanf(buf, "%lf",&val );
            vector[0]=val;
            ++i;
            #ifdef DEBUG
                fprintf(stdout, "vector : %lf \n", vector[0]);
            #endif
        }
    }
    fclose(fp);

Output comes to

vector : 0.837565
vector : 3.074878
vector : -3.968584
vector : 3.975388
vector : 0.703345

TO read values (separated by space )into multiple arrays I used

 sscanf(buf, "%d%d%lf",&row,&column,&value );

and buf has a datatype

char buf[BUFSIZ];
LGG
  • 528
  • 9
  • 21
  • 1
    It still is wrong (it will read one "phantom" record at the end of file, which is then rejected by the strlen() thing). Better remove the `feof()` and put the fgets in the loop condition: `while(fgets(buf, BUFSIZ, fp)) {...}` – wildplasser Apr 20 '13 at 16:14