'Why do we need to subtract 1 from the size of the buffer to get the size of the column? [closed]

I'm making a program that takes a file of an unknown size as an input and dynamic allocate it as much as the size of the array. Why do we need to subtract 1 from the size of the buffer to get the size of the column?

This is part of the code.

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MAX_SIZE 500

void CountRowCol(FILE* fp);
void allocateMemory();

int main()
{
      FILE* fp = NULL;
      fp = fopen("test.txt", "r");
      if (fp != NULL)
     {
        CountRowCol(fp);
        allocateMemory();
     }
      else
        printf("There is No file\n");

      fclose(fp);

      return 0;
 }

void CountRowCol(FILE* fp)
{
      int row = 0; int col = 0;
      char buffer[MAX_SIZE];
      if (fgets(buffer, 1000, fp))
     {
        col = strlen(buffer) - 1;
        row = 1;
     }
      while (fgets(buffer, 1000, fp))
     {
        row++;
     }
      fclose(fp);
      fp = NULL;
}
c


Solution 1:[1]

Why do we need to subtract 1 from the size of the buffer to get the size of the column?

As code does not use col, col = strlen(buffer) - 1; has no direct usefulness. @shjeff


Let us assume code is trying to find the length of the first line and not count a final '\n' @David Ranieri .

strlen(buffer) - 1, code risks 2 mistakes:

  1. A '\n' may not exist in buffer[], so finding its offset is moot. E.g. the line of input may exceed buffer space, so no '\n' saved.

  2. Although rare to first read a null character, it is possible, then strlen(buffer) is an unsigned 0 and strlen(buffer) - 1 is a very large value: SIZE_MAX. Assigning that to an int leads to implementation defined behavior, possible returning INT_MAX.

A better way to lop off a potential '\n':

buffer[strcspn(buffer, "\n")] = 0;
col = strlen(buffer);

Wrong size

User code is lying to fgets() as buffer is less than 1000 bytes. @the busybee

#define MAX_SIZE 500
...
// if (fgets(buffer, 1000, fp))
if (fgets(buffer, sizeof buffer, fp))

Solution 2:[2]

fgets(buffer, 1000, fp

This reads a line (assuming it fits in 999 bytes, one byte is used for string terminator, '\0').

This line includes the newline character, '\n'.

Subtracting 1 excludes that.


You might additionally want to remove the line feed from the string:

size_t len = strlen(buffer);
if (len > 0 && buffer[len-1] == '\n') {
    // reduce line length by 1 and overwrite newline with 0
    buffer[--len] = '\0';
} else {
    // handle line which does not end in newline
}

Missing newline might be because file ended and did not have newline at the end, or because line was longer than the buffer. Here you can probably just... print error message and exit, if you aren't required to handle such input.

Solution 3:[3]

In the C standard library, the character reading functions such as getchar return a value equal to the symbolic value (macro) EOF to indicate that an end-of-file condition has occurred. The actual value of EOF is implementation-dependent and must be negative (but is commonly ?1, such as in glibc). Block-reading functions return the number of bytes read, and if this is fewer than asked for, then the end of file was reached or an error occurred (checking of errno or dedicated function, such as ferror is often required to determine which).

Source

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1
Solution 2
Solution 3 Dedey