1

I am trying to write a code in C so that if I have a file reg2.dat as such:

5.1 3.5 1.4
4.9 3 1.4
4.7 3.2 1.3
4.6 3.1 1.5
5 3.6 1.4

Then, I can 1) determine the number of rows (in this case 5), 2) determine the number of columns (in this case 3), 3) write all 15 values in an array X.

I have my code working for the first two goals. However, I cannot get the array X to contain the values (5.1, 3.5, 1.4, 4.9, 3, 1.4, 4.7, 3.2, 1.3, 4.6, 3.1, 1.5, 5, 3.6, 1.4). I am getting a few errors as well.

Below is my complete and ordered code:

#include <stdio.h>
#include <string.h>
#include <stdlib.h>

int getCol(char *myStr);
int getRow(char *fileName);
int assignX(int nCol, int nRow, double *X, char *fileName);

int main(){
   FILE *f;
   char myStr[1000];
   int strL;
   int nCol;
   int nRow;
   char *fileName = "reg2.dat";
   double *X;

   f = fopen(fileName, "r");
   if (f == NULL) perror ("Error opening file");
   else {
     if (fgets(myStr, 1000, f) != NULL )
       puts(myStr);
     fclose(f);
   }

   strL = strlen(myStr);
   nCol = getCol(myStr);
   nRow = getRow(fileName);
   printf("Sample size and number of predictors are %d and %d respectively.\n", nRow, nCol-1);

   X = (double *) malloc(sizeof(double) * (nRow* nCol));

   return 0;
}

The helper function that does not work follows...

int assignX(int nCol, int nRow, double *X, char *fileName){
  int i=0;
  int j;
  char *string;
  FILE *f;
  f = fopen(fileName, "r");

  while(!feof(f)){  
    string = fgets(f);
    for (j=0; j<nCol; j++){
       strcpy(X[i], strtok(string, " "));
       i++;
    }  
  }

  for (i=0;i<(nRow*nCol);i++){
    printf("%d\n", X[i]);
  }
}

The helper functions that do work follows...

int getCol(char *myStr){
    int length,i,count=0;
    char prev;
    length=strlen(myStr);
    if(length > 0){
      prev = myStr[0];
    }
    for(i=0; i<=length; i++){
      if(myStr[i]==' ' && prev != ' '){
        count++;
      }
      prev = myStr[i];
    }
    if(count > 0 && myStr[i] != ' '){
        count++;
    }
    return count;
}

int getRow(char *fileName){
  char ch;
  int count=0;
  FILE *f;
  f = fopen(fileName, "r");

  while(!feof(f)){
    ch = fgetc(f);
    if(ch == '\n')
    {
      count++;
    }
  }
return count;
}

I have tested that the last two helper functions getRow and getCol work, and return values of nRow = 5 and nCol = 3. I am only keeping them in here in case it could possibly cause the error (which I doubt). The errors appear to come from the first helper function assignX. Here are the errors when I run:

gcc -ansi -pedantic readReg.c -o readReg -llapack -lblas -lgfortran

Errors:

readReg.c: In function ‘assignX’:
readReg.c:52: warning: passing argument 1 of ‘fgets’ from incompatible pointer type
/usr/include/stdio.h:626: note: expected ‘char * __restrict__’ but argument is of type ‘struct FILE *’
readReg.c:52: error: too few arguments to function ‘fgets’
readReg.c:54: error: incompatible type for argument 1 of ‘strcpy’
/usr/include/string.h:128: note: expected ‘char * __restrict__’ but argument is of type ‘double’

Thank you for your help.

  • The [`fgets()`](http://pubs.opengroup.org/onlinepubs/9699919799/functions/fgets.html) function takes three arguments, and the third is the file pointer, not the first. Also, [`while (!feof(file))` is always wrong](http://stackoverflow.com/questions/5431941/while-feof-file-is-always-wrong). Also copying strings into an array of `double` is dubious; are you looking for `atof()` or something similar. You look like you have memory management issues too. – Jonathan Leffler Mar 22 '15 at 23:38

2 Answers2

1

Number of issues

  1. Instead of char *string; ... while(!feof(f)){ string = fgets(f);, use char string[1000]; while(fgets(string, sizeof string, f) != NULL) {. Learner code rarely uses feof(). Check fgets() return value instead.

  2. int getRow(char *fileName) opens, but does not close f. Add fclose(f).

  3. main() appears to only read 1 line of the file.

There is more, but GTG

chux - Reinstate Monica
  • 143,097
  • 13
  • 135
  • 256
0

There are other few issues, but the compiler fails because of this line:

string = fgets(f); 

fgets cannot be called this way, since there are missing arguments:

char * fgets (char *s, int count, FILE *stream)

The other mistake your compiler is complaining about is this line in your assignX function:

   strcpy(X[i], strtok(string, " "));

You have this declaration in your main:

double *X;

While to call strcpy you need to follow this template:

char * strcpy (char *restrict to, const char *restrict from)

Moreover, You declared your X to be a pointer not an array, so trying to access X[i] would in any case lead to any kind of errors: undefined behaviour (if you are in a context that allows you to access the memory locations in the same block as X), segmentation faults and failures at compile time.

The array declaration char a[6] requests that space for six characters be set aside, to be known by the name a''. That is, there is a location nameda'' at which six characters can sit. The pointer declaration char *p, on the other hand, requests a place which holds a pointer, to be known by the name ``p''. This pointer can point almost anywhere: to any char, or to any contiguous array of chars, or nowhere

Mariano Macchi
  • 242
  • 1
  • 7