-
CS50 Week4: Problem Set, ReverseProgramming/CS50 2023. 7. 17. 17:15
하버드 CS50 강의 4주차 Poblem Set 과제 Reverse 의 풀이 과정을 다룹니다.
바이너리 파일의 구조를 이해하고 데이터를 의미 있는 단위로 역순으로 처리해야 합니다.
C언어로 파일 스트림의 위치를 제어하여 조작하는 문제입니다.Task
문제 링크에서 자세한 내용을 확인할 수 있습니다.
WAV 오디오 파일을 뒤집는 과제
./reverse input.wav output.wav
Template
템플릿이 주어지며, 필요한 부분을 채워주면 됩니다.
#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 // Open input file for reading // TODO #2 // Read header // TODO #3 // Use check_format to ensure WAV format // TODO #4 // Open output file for writing // TODO #5 // Write header to file // TODO #6 // Use get_block_size to calculate size of block // TODO #7 // Write reversed audio to file // TODO #8 } int check_format(WAVHEADER header) { // TODO #4 return 0; } int get_block_size(WAVHEADER header) { // TODO #7 return 0; }
Code
Todo #1: Ensure proper usage
인자 수가 맞는지 확인한다.
// Ensure proper usage if (argc != 3) { printf("Usage: ./reverse input.wav output.wav\n"); return 1; }
Todo #2: Open input file for reading
파일을 열어준다. 이전 과제에서 언급했듯, 윈도우일 경우 "rb"를 사용해야 한다.
// Open input file for reading FILE *inptr = fopen(argv[1], "rb"); if (inptr == NULL) { printf("Could not open %s.\n", argv[1]); return 1; }
Todo #3: Read header
헤더를 읽어온다. 첫 8~11 바이트가 헤더이다.
// Read header WAVHEADER header; fread(&header, sizeof(WAVHEADER), 1, inptr);
Todo #4: Use check_format to ensure WAV format
WAV 파일인지 확인한다.
// Use check_format to ensure WAV format if (!check_format(header)) { printf("Input is not a WAV file.\n"); fclose(inptr); return 1; }
check_format 함수
헤더는 "WAVE"로 시작한다.
글자를 비교하기 때문에 작은 따옴표
'
사용해야 함에 유의.bool check_format(WAVHEADER header) { if (header.format[0] == 'W' && header.format[1] == 'A' && header.format[2] == 'V' && header.format[3] == 'E') { return true; } return false; }
Todo #5: Open output file for writing
"wb"를 사용해야 한다.
// Open output file for writing FILE *outptr = fopen(argv[2], "wb"); if (outptr == NULL) { printf("Could not create %s.\n", argv[2]); fclose(inptr); return 1; }
Todo #6: Write header to file
읽는 것과 반대로 쓰면 된다.
// Write header to file fwrite(&header, sizeof(WAVHEADER), 1, outptr);
Todo #7: Use get_block_size to calculate size of block
호출만 하면 된다.
// Use get_block_size to calculate size of block int block_size = get_block_size(header);
get_block_size 함수
간단하다. blockAlign 값을 반환하면 된다.
int get_block_size(WAVHEADER header) { return (int) header.blockAlign; }
Todo #8: Write reversed audio to file
파일을 거꾸로 읽어야 한다. 여러 방법을 시도해 보다가 아래 방법을 적용하기로 했다.
SEEK_END
를 써서 마지막 위치를 찾고 거기서부터 블록 사이즈단위로 읽어서 쓰면 된다.// Write reversed audio to file BYTE buffer[block_size]; long start_position = ftell(inptr); fseek(inptr, 0L, SEEK_END); long end_position = ftell(inptr); for (long pos = end_position - block_size; pos >= start_position; pos -= block_size) { fseek(inptr, pos, SEEK_SET); fread(buffer, block_size, 1, inptr); fwrite(buffer, block_size, 1, outptr); } fclose(inptr); fclose(outptr);