0

Questions:

  1. I don't know why I'm getting the first error, I used unsigned char for file1.
  2. I didn't understand how sprintf(file1, "%03i.jpg",2); FILE *img = fopen(file1, "w"); will create a jpg file.

Please help me out with these questions. Thank you! :)

//I'm trying to print out one jpg image first and then worry about the looping and all.

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

#include "bmp.h"

int main(int argc, char *argv[])
{
    //these are the initial checks to check if the arguments are correct and if the file exists.
    if (argc != 2)
    {
        fprintf(stderr, "Usage: ./recover file_name\n");
        return 1;
    }

    JPEGFILE buffer; //buffer inptr
    FILE *corruptptr = fopen(argv[1], "r");

    if (corruptptr == NULL)
    {
        fprintf(stderr, "Error: File '%s' not found.\n", argv[1]);
        return 2;
    }
    int check_return = -15; // 1 if it reads, 0 if it doesn't, so we need some other number.
    int ctr = 0, y = 0;
    do
    {
        //Doing this in two loops. First time, I'll just check malloc size.
        check_return = fread(&buffer, sizeof(JPEGFILE), 1, corruptptr);

        if (buffer.b1 == 0xff && buffer.b2 == 0xd8 && buffer.b3 == 0xff && (buffer.b4 & 0xf0) == 0xe0)
            y ++;

        if (y == 1)
            ctr++; //ctr checks the number of 512 byte blocks we have to copy.

    }while(y != 2); //I'm just trying to get one picture, will try to loop over later.

    fseek(corruptptr, -(ctr * sizeof(JPEGFILE)), SEEK_CUR); //we're taking the pointer back to rerun the second time.
    unsigned char* file1 = malloc(ctr * sizeof(JPEGFILE)); //

    sprintf(file1, "%03i.jpg",2);
    FILE *img = fopen(file1, "w");

    //second do-while is to write (first was to get the size for malloc)
    for (int i = 0; i < ctr; i--)
    {
        fread (&buffer, sizeof(JPEGFILE), 1, corruptptr);
        fwrite (&img, sizeof(JPEGFILE), 1, buffer);
    }


    //do the print of JPEG.

    printf("%d\n",check_return);
    fclose(corruptptr);

    printf("All's good.\n");
    free(file1);
}

Errors:

~/workspace/pset4/recover/ $ make recover
clang -fsanitize=signed-integer-overflow -fsanitize=undefined -ggdb3 -O0 -std=c11 -Wall -Werror -Wextra
-Wno-sign-compare -Wshadow    recover.c  -lcrypt -lcs50 -lm -o recover recover.c:44:13: error: passing 'unsigned char *' to
parameter of type 'char *' converts between pointers to integer types with different sign
  [-Werror,-Wpointer-sign]
sprintf(file1, "%03i.jpg",2);
        ^~~~~
/usr/include/stdio.h:364:38: note: passing argument to parameter '__s' here
extern int sprintf (char *__restrict __s,
                                 ^
recover.c:45:23: error: passing 'unsigned char *' to parameter of type 'const char *' converts between pointers to integer
types with different
  sign [-Werror,-Wpointer-sign]
FILE *img = fopen(file1, "w");
                  ^~~~~
/usr/include/stdio.h:272:44: note: passing argument to parameter '__filename' here
extern FILE *fopen (const char *__restrict __filename,
                                       ^
recover.c:51:44: error: passing 'JPEGFILE' to parameter of incompatible type 'FILE *' (aka 'struct _IO_FILE *')
    fwrite (&img, sizeof(JPEGFILE), 1, buffer);
                                       ^~~~~~
/usr/include/stdio.h:716:38: note: passing argument to parameter '__s' here
                  size_t __n, FILE *__restrict __s);
                                               ^
3 errors generated.
make: *** [recover] Error 1
0
sprintf(file1, "%03i.jpg",2);
FILE *img = fopen(file1, "w");

These two lines will open a jpeg file for output. Each has a separate purpose.

The first line does nothing more than build a char string that will be the file name. It really doesn't have anything to do with a file yet. file1 is a var that will contain the string name. "%03i.jpg" is the pattern used to fabricate the actual string. %03i is both a placeholder and a pattern descriptor. It says to build a number with leading zeros that is 3 digits long, using an int. The int comes from the 2, or from an int var that you could replace the 2 with.

Once the filename is built and stored in file1, the next line opens a file with the name stored in file1. It is opened in w, or write, mode.

When file1 is declared, it only needs to be declared as a char array with enough length to hold the 7 chars needed for the file name pattern plus 1 for the end of string marker. The current declaration in the code above is far too much space.

There are more issues, but this answers your question.

If this answers your question, please click on the check mark to accept. Let's keep up on forum maintenance. ;-)

| improve this answer | |
  • Thank you for your answer! I don't completely understand what you're trying to say. "The first line does nothing more than build a char string that will be the file name. It really doesn't have anything to do with a file yet." But, you wrote "Once the filename is built and stored in file1, the next line opens a file with the name stored in file1. It is opened in w, or write, mode. " I'm unable to understand how the file is created. – Krishna Jun 24 '18 at 16:21
  • The fopen() function is designed to handle opening files for us. If you want to really know how it does it, google fopen source code and study it. You'll probably have to research functions that it uses too, etc. Or, google "How does fopen work". I applaud the desire to know how it works, but for now, think of it this way. While it might be fun or enlightening, a person doesn't need to know the inner workings of a car to drive it to the store. ;-) – Cliff B Jun 24 '18 at 20:52
  • No no, I meant to ask fopen opens a file, doesn't "open" a pointer or anything. And you said first line builds a char string only. How do we "open a file" when we just have a pointer? – Krishna Jun 25 '18 at 0:23
  • Hey, I figured it out. fopen either opens files or creates files when the file doesn't exist. Thank you for helping me out. – Krishna Jun 25 '18 at 11:21

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .