0

I'm trying to write a piece of code that will read the "header" of a PPM file. For example:

P3
400 200
255

In this case the width is 400 and the height is 200 and the max colour value is 255. I'm trying to assign these strings values as integers but I think there is a better way to do this with less lines and more "safer." How can I avoid having to use the atoi() function? (Note I've already included the "check if file is open-able part in my ACTUAL code this is merely a reduced snippet)

  char buffer[200];
  char height[200];
  char width[200];
  char maxColour[200];

  FILE *file = fopen("mcmaster.ppm", "r");

  fgets(buffer, sizeof(buffer), file); // File format line

  fgets(buffer, sizeof(buffer), file); // Width x height line
  sscanf(buffer, "%s %s", width, height);

  fgets(buffer, sizeof(buffer), file); // Max colour line
  sscanf(buffer, "%s", maxColour);

  int actHeight = atoi(height);
  int actWidth = atoi(width);
  int actMaxColour = atoi(maxColour);
  • 1
    For your width x height why are you not just directly using a `sscanf` format string to scan integers: `sscanf(buffer, "%d %d", &actWidth, &actHeight);` (assuming of course they're previously declared as `int`)? Same for reading `actMaxColour`. – lurker Nov 22 '18 at 03:44
  • @lurker: Good question, especially as the conversion function is [`atoi()`](http://port70.net/~nsz/c/c11/n1570.html#7.22.1.2) which has [undefined error handling](http://port70.net/~nsz/c/c11/n1570.html#7.22.1p1) properties. If the code used [`strtol()` correctly](https://stackoverflow.com/questions/14176123/) for the conversion, then scan to strings and then strings to integers would avoid undefined behaviour in `sscanf()` (or `scanf()`) when the value is too large for the integer type. I doubt if the thinking here was that subtle, though — it was more likely a simple oversight. – Jonathan Leffler Nov 22 '18 at 03:53
  • "better way to do this with less lines and more "safer.". It depends: 1) What do you want to happen when the input is not a valid `int`? What do you want to happen when the input is out of range? – chux - Reinstate Monica Nov 22 '18 at 05:25

1 Answers1

-2

I suggest you to use fscanf instead of sscanf. First, define a "Error Function" to verify problems of reading the file, as

void fscanf_Error(char *file)
{
    fprintf(stderr,"Error reading file: %s\n. Exiting(1).\n ",file);
    exit(1);
}

Then

  char dummy[12];
  if(!fscanf(file, "%s\n", dummy))
      fscanf_Error(file);
  if(!fscanf(file," %d %d\n", width, height))
      fscanf_Error(file);
  if(!fscanf(file, "%d\n", maxColour))
      fscanf_Error(file);
  • You rarely want spaces and never want newlines in the fscanf format string. Also, fscanf only returns 0 if no conversions happen and EOF is not reached. So while 0 should be an error, some non-zero return values should also be errors. – Chris Dodd Nov 22 '18 at 07:17
  • I only put this new line because, depending on the version of the C compiler you're using, warnings appear complaining that the returning of fscanf is not used. – Anderson Oliveira Nov 23 '18 at 08:15