0

I am practicing programming in C and I decided to create a function that will count the amount of rows in a file for later use in creating a matrix. The problem comes in when I provided it with different file types. I noticed that when I provide the function with a txt file it counts one less then it needs, while a csv is counting the correct amount of rows.

int countRows(char fileName[100]){
    FILE *fp;
    int nl = 1;
    char c;

    fp = fopen(fileName, "r");
    for (c = getc(fp); c != EOF; c = getc(fp)){
        if(c == '\n'){
            nl = nl + 1;
        }
    }

    fclose(fp);
    return nl;
}

Say if I were to have a txt file as

age name    score
15  jared   90
16  jerome  85
18  timmy   9

I would expect an output of 4 rows.

Jonathan Leffler
  • 730,956
  • 141
  • 904
  • 1,278
Dylan Edmonds
  • 47
  • 1
  • 6
  • 4
    Note that [`getc`](https://en.cppreference.com/w/c/io/getc) returns an `int`. That is actually very important for that `EOF` check. – Some programmer dude Feb 18 '19 at 04:37
  • 3
    Also you need to check if the last line actually ends with a newline. That might not always be true. – Some programmer dude Feb 18 '19 at 04:38
  • Possible duplicate of [C function that counts lines in file](https://stackoverflow.com/questions/12733105/c-function-that-counts-lines-in-file) –  Feb 18 '19 at 04:40
  • You should not start counting with `nl = 1` but with `nl = 0`. – Roland Illig Feb 18 '19 at 07:33
  • @RolandIllig I intially did that because I am going to add a function that recognizes when a file that is empty has been put into the function, but I agree with you so I will make the change – Dylan Edmonds Feb 18 '19 at 17:01

1 Answers1

1

To get the algorithm right, you should write a similar function that counts the lines of a string. Here are some test cases:

  • "" has 0 lines
  • "hello" has 1 line although it doesn't have any \n character
  • "\n" has 1 line
  • "hello\n" also has 1 line
  • "hello\n\n\n" has 3 lines
  • "\ntext" has 2 lines

You should write automatic tests for these test cases. The assert macro is a simple and good choice for this.

As soon as your algorithm covers all these test cases, it will probably also work for files.

Roland Illig
  • 40,703
  • 10
  • 88
  • 121
  • 1
    I would add this test case (even if covered by your last two): `"\n" has 1 line` – HAL9000 Feb 18 '19 at 09:33
  • So do you believe that it is not counting it because the last line does not contain \n and instead it the string just ends? such as in the "hello" has 1 line test case. – Dylan Edmonds Feb 18 '19 at 16:59
  • @DylanEdmonds Yes, that's one likely reason. Another is that the file contains a 0xFF byte, but that will be fixed by changing `char c` to `int c`, as suggested in another comment. – Roland Illig Feb 18 '19 at 17:21
  • So I guess it technically does what I want it to, but it is bringing different results because of formatting issues with the file. Do you have any recommendations on balancing the functions fail safes to accommodate for user error and determining the a reasonable amount of responsibility that the user should be able to accept and follow? @RolandIllig This is kind of a broad question, but I feel it will help me be more reasonable with my expectations of myself in my future work. – Dylan Edmonds Feb 18 '19 at 19:29
  • @DylanEdmonds Maybe it's already too late for me, but I don't get your question. I have no idea what you mean by "reasonable amount of responsibility", sorry. – Roland Illig Feb 18 '19 at 20:12