0

My program is used for displaying numbers from a .DAT file. There are 2 fields in each line. For example: content of .dat file:

1 2.2
3 10.9

10 100

There are 4 lines in the .DAT file. In the first line, field1 is "1" while field2 is "2.2" And so on. Line 3 is a blank line.

My program is used for displaying the numbers in the same format as we see in the .DAT file which is:

1 2.2
3 10.9

10 100

I do all my programming in Ubuntu. Compiling and running the program in gcc.

My code is shown below:

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

int main()
{
    FILE *fp = fopen("number.dat", "r");
    if (fp == NULL)
    {
        fprintf(stderr, "ERROR: cannot open the file\n");
        return 1;
    }

    char *field1 = NULL;
    char *field2 = NULL;

    char line[100];
    while(fgets(line, 100, fp)!=NULL)
    {
        if(line[0] != '\n')
        {
            field1 = strtok(line, " ");
            field2 = strtok(NULL, " ");

            printf("%s ", field1);
            printf("%s", field2);
        }
        else
        {
            printf("Blank Line!");
        }
     }
     fclose(fp);

     return 0;
}

However, after i run the program, the result is shown below:

1 2.2
3 10.9

 (null)10 100

I do not understand why "(null)" is shown instead of "Blank Line!". Can someone help me find out what the problem is?

Gareth Lam
  • 145
  • 1
  • 4
  • 13
  • 2
    A blank line may contain whitespace characters (tabs, etc). `fgets()` will pick them up. But your calls of `strtok()` will not pick up whitespace characters other than the space character. – Peter Oct 01 '16 at 06:13
  • @alk I tried "rt". But it still doesnt work... – Gareth Lam Oct 01 '16 at 06:20
  • @Gareth lam - Your program works fine with GCC after did a correction. – msc Oct 01 '16 at 06:20
  • @Peter Thats why i set a conditional statement to print out "Blank Line!" instead of processing strtok() when meeting a blank line. The blank line in the . DAT file is created by pressing an "Enter" button. – Gareth Lam Oct 01 '16 at 06:21
  • @alk `"rt"`? Eh? Is that some weird compiler extension? Text mode is supposed to be the default if `"b"` is omitted. – jamesdlin Oct 01 '16 at 07:09
  • @jamesdlin: You are completely right. Another temp brain lapse ... huhu .. deleting. – alk Oct 01 '16 at 07:15
  • "rt" is unnecessary and the same as "r". "rb" means open in in binary mode, and is sometimes necessary, but not here. The problem is that the blank lines are actually padded with whitespace character. – Malcolm McLean Oct 01 '16 at 07:16

2 Answers2

0

Use if(line[0] != '\r' && line[0] != '\n') instead of if(line[0] != '\n').

msc
  • 33,420
  • 29
  • 119
  • 214
  • Eh? The OP is using that, not `strcmp()`. – Peter Oct 01 '16 at 06:14
  • I do not see a call to `strcmp()`. – alk Oct 01 '16 at 06:14
  • 2
    I am sorry, i changed from strcmp() to line[0] != '\n'. But i find that both of them have the same result which is "(null)10 100". – Gareth Lam Oct 01 '16 at 06:19
  • @GarethLam Which compiler use? – msc Oct 01 '16 at 06:22
  • @M.SChaudhari I am using gcc in Ubuntu. – Gareth Lam Oct 01 '16 at 06:26
  • @GarethLam I have modified my answer, plz try this. – msc Oct 01 '16 at 06:28
  • @M.SChaudhari Thank you very much!!! It works. I would like to ask why '\r' is needed? – Gareth Lam Oct 01 '16 at 06:31
  • @GarethLam I don't know exactly, but some compiler return `\r` & `\n`. See the link : http://stackoverflow.com/questions/1761051/difference-between-n-and-r – msc Oct 01 '16 at 06:33
  • 1
    @M.SChaudhari Thanks for your help! – Gareth Lam Oct 01 '16 at 06:40
  • No, the presence of `\r` and `\n` has nothing to do with the compiler. The file that you're reading was created on Windows, and Windows uses `\r\n` as its line-ending sequence. Meanwhile, you are probably running your program on Unix (or something similar) which expects newlines to be `\n`. Consequently, the C stdio library does not perform its usual newline conversions for text-mode streams, so `fgets` ends up reading `\r` from the file. – jamesdlin Oct 01 '16 at 07:06
0

A blank line might contain spaces. You could write a function to skip leading whitespace. Or you could use sscanf() which automatically ignores whitespace. This also lets you read numbers directly into integers and floats.

int field1;
double field2;

char line[100];
while(fgets(line, 100, fp)!=NULL)
{
    int num_matches = sscanf(line, "%d %lf", &field1, &field2);

    if( num_matches == 2 ){
        printf("%d %.2lf\n", field1, field2);
    }
    else
    {
        printf("Malformatted line\n");
    }
}
fclose(fp);
Schwern
  • 153,029
  • 25
  • 195
  • 336