简体   繁体   中英

C program doesn't recognize '\n' in file exported from MATLAB

I have a matrix G in MATLAB that I have printed into a text file using:

file = fopen('G.dat','w');
fprintf(file, [repmat('%f\t', 1, size(G, 2)) '\n'], G'); 
fclose(file);

The dimension of this matrix is 100 x 500. If I count rows and columns using awk, for instance, using

cat G.dat | awk '{print NF}END{print NR}' 

I see that the dimensions correspond to the original one.

Now, I want to read this file, G.dat, from a C program that counts the columns of the first row just to understand the columns' dimension as in:

    while (!feof(file) && (fscanf(file, "%lf%c", &k, &c) == 2) ) {
        Ng++; 
        if (c == '\n') 
            break;
}

Unfortunately it gives me Ng = 50000 and it doesn't recognize any of the '\\n'. Instead, if I create the text file just by copying and pasting the data, it works. Can you explain me why? Thanks!

Are you working in Windows? Try opening your output file in text mode:

file = fopen('G.dat','wt');

This will automatically insert a carriage return before each newline when writing to the file.

if I understand the matlab syntax correctly, this expands to a format string like %f\\t%f\\t%f\\t\\n\\%f\\t%f\\t%f\\t\\n for a 3x2 matrix. Note the extra \\t at the end of each line. If this assumption is correct, the last fscanf() call in a line will assign the last \\t to &c . The next fscanf() call just skips the \\n because it doesn't match your format.

I'd propose you use fgets() instead for reading each line and then loop over the fields using strtok() , reading the values with atof() eg

char buf[8192];
if (fgets(buf, 8192, file))
{
    if (strtok(buf, '\t'))
    {
        ++Ng;
        while (strtok(0, '\t')) ++Ng;
    }
}
else
{
    /* error reading ... */
}

Code's approach is too fragile to "counts the columns of the first row just to understand the columns' dimension". fscanf(file, "%lf%c"... is too susceptible to variant white-space delimiters and EOL to detect the '\\n' .

Recommend explicitly examine white-space to determine width:

// return 0 on success, 1 on error
int GetWidth(FILE *file, size_t *width) {
  *width = 0;
  for (;;) {
    int ch;
    while (isspace(ch = fgetc(file))) {
      if (ch == '\n') return 0;
    }
    if (ch == EOF) return 0;
    ungetc(ch, file);
    double d;
    if (fscanf(file, "%lf", &d) != 1)) {
      return 1;  // unexpected non convertible text
    }
    (*width)++;
  }
}

//Sample, usage
size_t width;
if (GetWidth(file, &width)) return 1;

// read entire file
rewind(file);
for (size_t line = 0; foo(); line++)
  for (size_t column = 0; column<width; column++) {
    double d;
    if (fscanf(file, "%lf", &d) != 1)) {
      break;  // EOF, unexpected non convertible text or input error
    }
  }
  ...
}

Matlab writes rows as

 %f\t%\f .. %f\t\n 

which is a problem. I have used

dlmwrite('G.dat', G, '\t');

and it is fine!

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM