Reverse .wav file in C, any error in there? - c

I've been making the program from CS50'x about reversing the .WAV files. Seems to work fine, however the cs50's check finds an error. Don't know where it is, the code seems to be alright and there I can't find any problem.
I tried to change 'i' - iterator in for-loop but when set as = infile_size - block_size the file won't be converted / reversed.
My code below:
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include "wav.h"
int check_format(WAVHEADER header);
int get_block_size(WAVHEADER header);
int main(int argc, char *argv[])
{
// Ensure proper usage
// TODO #1
// check if command-line arguments = argv[0], argv[1], argv[2] = 3 in sum
if (argc != 3)
{
if (argc < 3)
{
printf("not enough command-line args\n");
}
else
{
printf("too much command-line args\n");
}
return 1;
}
// remember filenames
char *infile = argv[1];
char *outfile = argv[2];
// open input file for reading
FILE *inptr = fopen(infile, "r");
if (inptr == NULL)
{
printf("could not open the infile\n");
return 1;
}
// read header into an array
WAVHEADER header;
fread(&header, sizeof(header), 1, inptr);
// use check_format to ensure WAV format
check_format(header);
// open output file for writing
FILE *outptr = fopen(outfile, "w");
if (outptr == NULL)
{
printf("couldn't open the outfile\n");
fclose(inptr);
return 1;
}
// write header to file
fwrite(&header, sizeof(header), 1, outptr);
// use get_block_size to calculate size of block
int block_size = get_block_size(header);
printf("block_size: %i\n", block_size);
if (block_size < 0)
{
printf("block_size with no size\n");
return 1;
}
// write reversed audio to file
// 1. declare an array to store each block of audio
char *buffer = malloc(block_size * sizeof(char));
if (buffer == NULL)
{
printf("no memory location");
return 1;
}
// get the size of the input file
fseek(inptr, 0, SEEK_END);
long int infile_size = ftell(inptr);
printf("file_size: %li\n", infile_size);
// iterate through the input file audio data
for (long int i = infile_size; i >= 0; i -= block_size)
{
// move the file indicator to the start
fseek(inptr, i, SEEK_SET);
// read from inptr each size
fread(buffer, sizeof(char), block_size, inptr);
// write in outfile
fwrite(buffer, sizeof(char), block_size, outptr);
}
// free
free(buffer);
// close files:
fclose(inptr);
fclose(outptr);
}
int check_format(WAVHEADER header)
{
// TODO #4
if (header.format[0] == 'W' && header.format[1] == 'A' && header.format[2] == 'V' && header.format[3] == 'E')
{
printf("This is the type .wav\n");
return 0;
}
else
{
printf("File is not the type .wav\n");
return 1;
}
}
int get_block_size(WAVHEADER header)
{
// TODO #7
// check if channels are mono or audio
if (header.numChannels == 1 || header.numChannels == 2)
{
int block_size;
block_size = header.numChannels * (header.bitsPerSample / 8);
return block_size;
}
else
{
printf("Not supported\n");
return 1;
}
}
Thanks in advance!

Related

RECOVER code returns 51 jpegs and are incorrect i need some cues

So I'm trying CS50 Recover exercise (where you need to search for jpg files in a memory card and whenever you find one- you open a new file and write the jpg found to the new file). My code compiles and returns 51 jpegs instead of only 50 and all of them are incorrect. Please, I need some cues on what to focus at and fix/replace.
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
typedef uint8_t BYTE;
int main(int argc, char *argv[])
{
// Check for valid usage
if ( argc != 2)
{
printf("Usage: ./recover IMAGE\n");
return 1;
}
// Check for valid image
FILE *image = fopen(argv[1], "r");
if (image == NULL)
{
return 1;
}
BYTE buffer[512];
int i = 0;
char new_image[8];
FILE *output;
FILE *output1;
while (fread (buffer, 1, 512, image) == 512)
{
// IF Start of a JPEG
if (buffer[0] == 0xff && buffer[1] == 0xd8 && buffer[2] == 0xff && ((buffer[3] & 0xf0) == 0xe0))
{
sprintf(new_image, "%03i.jpg", i);
//if first JPEG
if ( i == 0)
{
output = fopen(new_image, "w");
fwrite(buffer, 512, 1, output);
i++;
}
// if not first JPEG
else
{
fclose(output);
sprintf(new_image, "%03i.jpg", i);
output1 = fopen(new_image, "w");
fwrite(buffer, 1, 512, output1);
fclose(output1);
i++;
}
}
// if not start of a JPEG
else
{
output = output1 = fopen(new_image, "w");
fwrite(buffer, 1, 512, output);
}
}
fclose(image);
}

Is there anyway to use a file pointer outside of a if condition in C

My problem starts from the while loop. I have an if condition and inside of the if condition I create a file and write to it. But naturally, I can't use the pointer outside of the condition. I'm new to C and I'm looking for a way to make that pointer global variable like in python. Here is my code:
#include <stdio.h>
#include <stdlib.h>
#include "cs50.h"
//define chunk size
const int chunksize = 512;
int main(int argc, char *argv[])
{
if (argc != 2)
{
fprintf(stderr,"Usage: ./recover image\n");
return 1;
}
// open memory card file
FILE *inptr = fopen(argv[1], "r");
if (inptr == NULL)
{
fprintf(stderr, "Could not open %s.\n", argv[1]);
return 2;
}
//create a variable to store memory size
fseek(inptr, 0L, SEEK_END);
long int memorysize = ftell(inptr);
rewind(inptr);
//find how many chunk does memory card contain
int nofchunks = memorysize / chunksize;
//create a file counter
int nofjpeg = 0;
while(nofchunks > 0)
{
//create a temporary storage
unsigned char chunk[chunksize];
// read a 512 byte chunk from memory card
fread(&chunk, chunksize, 1, inptr);
FILE *outptr = NULL;
//check the chunk if it is a JPEG by looking first 4byte of the chunk
if (chunk[0] == 0xff && chunk[1] == 0xd8 && chunk[2] == 0xff && (chunk[3] & 0xf0) == 0xe0)
{
nofjpeg++;
//create a temporary file name
char filename[8];
if (nofjpeg == 1)
{
//create a new file name
sprintf(filename, "%03i.jpg", nofjpeg);
//open the file in write mode
outptr = fopen(filename, "w");
if (outptr == NULL)
{
fprintf(stderr, "Could not open %s.\n", argv[1]);
return 2;
}
fwrite(&chunk, chunksize, 1, outptr);
}
else
{
//close the previous file
fclose(outptr);
//create a new file name
sprintf(filename, "%03i.jpg", nofjpeg);
//open the file in write mode
outptr = fopen(filename, "w");
if (outptr == NULL)
{
fprintf(stderr, "Could not open %s.\n", argv[1]);
return 2;
}
fwrite(&chunk, chunksize, 1, outptr);
}
}
else if(nofjpeg > 1)
{
fwrite(&chunk, chunksize, 1, outptr);
}
nofchunks--;
}
}
You can see that inside of the first inner if condition I open the file and write to it. And I need to close that file inside the following else condition. You can also see I also use that pointer following the outer if condition.
Declare the file pointer before the if statement but assign it a null value. It is then available after the if statement. Inside the if statement you can assign it a value which will persist after the if statement. Following the if statement you should check to make sure it's not null before de-referencing it.
//check the chunk if it is a JPEG by looking first 4byte of the chunk
FILE *outptr = (FILE*) NULL; // Declare before the if and assign to NULL cast to type FILE*
if (chunk[0] == 0xff && chunk[1] == 0xd8 && chunk[2] == 0xff && (chunk[3] & 0xf0) == 0xe0)
{
nofjpeg++;
//create a temporary file name
char filename[8];
if (nofjpeg == 1)
{
//create a new file name
sprintf(filename, "%03i.jpg", nofjpeg);
//open the file in write mode
outptr = fopen(filename, "w"); // Assign inside the if statement, but don't declare.
if (outptr == NULL)
{
fprintf(stderr, "Could not open %s.\n", argv[1]);
return 2;
}
fwrite(&chunk, chunksize, 1, outptr);
}
else
{
//close the previous file ... this is likely a logical error; it should be NULL at this point, so there's nothing to close.
if (outptr) fclose(outptr); // Check to see if pointer is null before use.
//create a new file name
sprintf(filename, "%03i.jpg", nofjpeg);
//open the file in write mode
outptr = fopen(filename, "w");
if (outptr == NULL)
{
fprintf(stderr, "Could not open %s.\n", argv[1]);
return 2;
}
fwrite(&chunk, chunksize, 1, outptr);
}
}
else if(nofjpeg > 1)
{
// This is likely a logical error; outptr will be NULL here
if (outptr) fwrite(&chunk, chunksize, 1, outptr);
}
nofchunks--;
Finally found the solution!!! (I am using cloud visual studio)
Outside the loop declare it like this: FILE * outptr = (FILE *) outptr ;
And then just use outptr anywhere else (inside the differnt IF statements):
..inside the 1st IF >>>
open the file with: outptr = fopen(filename, "w");
write: fwrite(&chunk, chunksize, 1, outptr);
..inside the last ELSE IF >>>
write: fwrite(&chunk, chunksize, 1, outptr);

EDX CS50x PSET3 recover.c (recovered image does not match: applies to the 049.jpg file only)

I'm stuck in this problem:
Result:
:) recover.c exists.
:) recover.c compiles.
:) handles lack of forensic image
:) recovers 000.jpg correctly
:) recovers middle images correctly
:( recovers 049.jpg correctly
recovered image does not match
The file compiles correctly and all the 50 .jpg files are clear, however there is this small issue with the last file (049.jpg: recovered image does not match) and I just cannot figure out the reason.
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
int main(int argc, char *argv[])
{
// ensure 1 command-line argument:
if(argc != 2)
{
fprintf(stderr, "Usage: name of forensic image from which to recover JPEGs");
return 1;
}
// open the memory card file:
FILE *file = fopen(argv[1], "r");
if (!file)
{
fprintf(stderr, "Could not open %s.\n", argv[1]);
fclose(file);
return 2;
}
//fseek(file, 0, SEEK_SET);
unsigned char buffer[512];
char* filename = malloc(50 * sizeof(int));
if (!filename)
{
return 3;
}
bool jpeg_found = false;
int f = 0;
int n = 0;
while (!(feof(file)))
{
sprintf(filename, "%03i.jpg", f);
FILE *img = fopen(filename, "w");
if (!filename) return 6;
if (f > 0) fwrite(buffer, 1, 512, img);
n = 0;
while (n == 0)
{
if (feof(file))
{
fclose(img);
break;
}
fread(buffer, 1, 512, file); //read 512 bytes into a buffer
if (buffer[0] == 0xff && // start of a new JPEG?
buffer[1] == 0xd8 &&
buffer[2] == 0xff && (
buffer[3] & 0xf0) == 0xe0)
{
if (jpeg_found) // have you already found a JPEG or not?
{
// YES: close the previous file and open a new one,
fclose(img);
f += 1;
n = 1;
}
else // NO: start very 1st JPEG
{
fwrite(buffer, 1, 512, img);
jpeg_found = true;
}
}
else
{
if (jpeg_found) // Have your already found a JPEG or not?
{
// YES: Those 512 bytes belong to the current opened JPEG file
fwrite(buffer, 1, 512, img);
}
else // NO: Discard the 512 bytes and go to the start of the loop
{
continue;
}
}
}
}
free(filename);
fclose(file);

Pset4 recover fails check50 test

I'm struggling with the CS50 course pset4 "recover". The code works, but when I test it (check50), it shows two errors:
:( recovers middle files correctly
:( recovers last file correctly
Here's the sandbox.
Could anyone help me with it, please? :)
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#define BLOCK 512
typedef uint8_t BYTE;
int main(int argc, char* argv[])
{
if(argc !=2)
{
fprintf(stderr, "Usage: ./copy infile\n");
return 1;
}
char* infile = argv[1];
FILE* card = fopen(infile, "r");
if(card == NULL)
{
fprintf(stderr, "Couldn't open %s!\n", infile);
return 2;
}
FILE* img = NULL;
int counter = 0;
char image[8];
BYTE data[BLOCK];
//checking if the end of the card is reached
while(fread(&data, sizeof(BLOCK), 1, card) !=0)
{
//checking if it's a new jpeg
if(data[0] == 0xff && data[1] == 0xd8 && data[2] == 0xff && (data[3] & 0xf0)==0xe0)
{
//if it's not the first new jpeg, close the previous
if(img !=NULL)
{
fclose(img);
}
sprintf(image, "%03i.jpg", counter);
img = fopen(image, "w");
if(img == NULL)
{
fprintf(stderr, "Couldn't open %s!\n", image);
fclose(card);
return 3;
}
counter++;
}
if(img !=NULL)
{
fwrite(&data, sizeof(BLOCK), 1, img);
}
}
fclose(img);
fclose(card);
return 0;
}

Binary file size change(reduced) when edit a block of that file [duplicate]

I wrote a very simple file corruptor for fun, but to my surprise, the "corrupted" file ends up being smaller in size than the original.
Here is the corruption function that is supposed to replace bytes but not to delete them:
void
corruptor(char *inputname, int percent)
{
FILE *input;
FILE *output;
int filesize;
char *outputname = append_name(inputname);
// Duplicate file
cp(outputname, inputname);
// Open input and output
input = fopen(inputname, "r");
if (input == NULL)
{
printf("Can't open input, errno = %d\n", errno);
exit(0);
}
output = fopen(outputname, "w+");
if (output == NULL)
{
printf("Can't open output, errno = %d\n", errno);
exit(0);
}
// Get the input file size
fseek(input, 0, SEEK_END);
filesize = ftell(input);
// Percentage
int percentage = (filesize * percent) / 100;
srand(time(NULL));
for (int i = 0; i < percentage; ++i)
{
unsigned int r = rand() % filesize;
fseek(output, r, SEEK_SET);
unsigned char corrbyte = rand() % 255;
fwrite(&corrbyte, 1, sizeof(char), output);
printf("Corrupted byte %d\n", r);
}
fclose(input);
fclose(output);
}
output = fopen(outputname, "w+");
This deletes the contents of the file, To open the file for reading and writing without deleting the contents, use mode "r+".

Resources