Question

My program decodes an image that is covered by random pixels, to decode the image, I have to multiply each pixel's red color component by 10. The green and blue color components are the same values as the new red component. I've created multiple helper functions, to make the code easier to read in main, but when I try to run my a.out, I keep getting "Segmentation Fault". I can't seem to find my mistakes! Help is appreciated.

void check_argument(int arg_list)
{
   if (arg_list < 2)
   {
      perror("usage: a.out <input file>\n");
   }
}

void print_pixel(int a, FILE *out)
{
   int r, g, b;

   r = a * 10;

   if (r > 255)
   {
      r = 255;
   }

   g = r;
   b = r;

   fprintf(out, "%d\n", r);
   fprintf(out, "%d\n", g);
   fprintf(out, "%d\n", b);
}

void read_header(FILE *in)
{
   char str[20];

   for (int i = 0; i < 3; i++)
   {
      fgets(str, 20, in);
   }
}

FILE*  open_files(FILE *infile, char *input[])
{
   infile = fopen(input[1], "r");

   if (infile == NULL)
   {
      perror("Error: Cannot read file.\n");
   }

   return infile;
}

void decode(int arg_list, char *in[])
{
   FILE *input, *output;

   int check, red, green, blue;

   open_files(input, in);
   output = fopen("hidden.ppm", "w");

   fprintf(output, "P3\n");
   fprintf(output, "%d %d\n", 500, 375);
   fprintf(output, "255\n");

   read_header(input);
   check = fscanf(input, "%d %d %d", &red, &green, &blue);

   while (check != EOF)
   {
      print_pixel(red, output);
      check = fscanf(input, "%d %d %d", &red, &green, &blue);
   }

   fclose(input);
   fclose(output);
}

int main(int argc, char *argv[])
{
   check_argument(argc);
   decode(argc, argv);
}
Was it helpful?

Solution

After calling open_files(input, in); you will not have the file handle in input.

OTHER TIPS

As this is supposed to be homework, I'll try to show you the some common source of bugs and how to find them.

  1. Variables which are used must (should) be assigned to before that. This counts especially for pointers, e. g. FILE *.

  2. If a function (e. g. fopen()) fails, it normally indicates this by returning a special value which must be checked before continuing.

  3. To check which value a variable has, you can use printf() to show it.

This is for finding principal errors such as segfaults.

But logical errors are hard to find as well: if you read 3 values and store them into variables, it might be more useful to use them all instead of only one of them. (But maybe this one is not yet the goal of this exercise.)


I wrote the lines before this before I learned that it is not the task to search for bugs in a given program, but to write a program by yourself, so I'll get a little more concrete by now.

A FILE * is something returned by fopen(). You can return it or you can write it to a variable or another memory location indirectly pointed to by a pointer "one level deeper".

So you should rewrite your open_files() (BTW: why file*s*? It's currently only one...):

either for returning the value (preferrable):

FILE* open_files(char *input[])
{
   FILE *infile = fopen(input[1], "r");

   if (infile == NULL)
   {
      perror("Error: Cannot read file.\n");
   }

   return infile;
}

and call it with

input = open_files(input);

or with "pass by reference":

void open_files(FILE **infile, char *input[])
{
   *infile = fopen(input[1], "r");

   if (*infile == NULL)
   {
      perror("Error: Cannot read file.\n");
   }

   return *infile;
}

and call it with

open_files(&input, in);

Only doing that you'll have your variable input at the caller's site really written to.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top