CS50_메모리_(3)[파일 쓰기, 읽기, 퀴즈-!]

김두미·2022년 6월 23일
0
post-thumbnail

1. 파일 쓰기

1) scanf

heap, stack영역이 각각 커지면서 두 메모리 영역이 어디선가 충돌한다.

자기자신을 계속해서 호출하는 버그가 있는 프로그램이라면 stack이 넘처 스택오버플로우가 발생한다.

malloc을 계속 (너무 많은 메모리 할당) 하면 메모리 속 다른 내용을 덮어쓰게 된다.
이를 힙 오버플로우라고 한다.

지금까지는 cs50.h의 get_int을 이용해 입력을 받았지만 이제부터는 scanf를 이용해서 입력을 받아보자.

#include<stdio.h>

int main(void)
{
    int x;
    printf("x : ");
    scanf("%i",&x);
    printf("x : %i\n",x);
}

scanf는 형식 지정자를 이용해 원하는 형식대로 입력을 받는다.

사용자의 입력을 저장하고 싶은 변수의 주소(&x)를 적는 것을 확인할 수 있다.
-> scanf("%i",&x);

NULL은 특별한 포인터로 가리키는 곳이 없다는 뜻이다.

#include<stdio.h>
int main(void)
{
	char *s = NULL;
    printf("s : ");
    scanf("%s", s);
    printf("s : %s\n", s);
}

처음에 s를 NULL로 했으므로 입력받은 문자열이 저장될 메모리가 할당되지않은것이다.
즉 이 코드는 NULL을 출력한다.

#include<stdio.h>
int main(void)
{
	char s[5];
    printf("s : ");
    scanf("%s", s);
    printf("s : %s\n", s);
}

이런식으로 char자료형의 5자리를 할당받으면 코드가 제대로 실행된다.

배열은 메모리가 연속적으로 할당된 공간이다.
clang 컴파일러는 문자 배열의 이름을 포인터처럼 다룬다.

2) 파일 쓰기

#include<stdio.h>
#include<cs50.h>
#include<string.h>

int main(void)
{
	//open file
    FILE *file = fopen("phone_book.csv","a");
	
    // Get String from user
    char *name = get_string("name: ");
    char *number = get_string("number: ");
	
    //print 
    fprintf(file, "%s, %s\n",name,number);
    //close file
    fclose(file);
}

FILE 이라는 자료형의 포인터 file을 만들고
fopen의 인수에는 열고싶은 파일의 이름과 동작을 알려줍니다.
fopen은 해당 파일을 가리키는 포인터를 반환합니다.

r, w, a가 있는데
r은 read, w은 write, a는 append입니다.

fprintf는 file용 printf입니다.

실행시켜보면

phone_book.csv가 잘 생기고 제대로 저장되었음을 확인할 수 있습니다.

2. 파일 읽기

포인터가 아무것도 가리키고 있지않다면 NULL입니다.

#include<stdio.h>
int main(int argc, char *argv[]) 
{
	// 파일이름이 들어왔는지 확인
	if(argc != 2) { 
    	return 1;
    }
    
    FILE *file = fopen(argv[1],"r"); // read용으로 파일을 open
    
    if(file == NULL){
    	return 1;
    }
    
    // read 3 bytes from  file
    unsigned char bytes[3];
    fread(byes,3,1,file);
    
    if (bytes[0] == 0xff && bytes[1] == 0xd8 && bytes[2] == 0xff )
    {
    	printf("maybe\n");
    }
    else {
    	printf("NO\n");
    } 
}

fread(byes,3,1,file);
는 배열, 읽을 바이트 수, 읽을 횟수, 읽을 파일을 인수로 받습니다.

jpeg파일의 첫 세바이트는 ff, d8, ff로 시작하는 것으로 약속되어있기 때문에
첫 세바이트가 다음과 같은지 확인하여 jpeg인가를 확인할 수 있습니다.

3. 퀴즈 -!

1) printf("%i\n",*&n); 은 어떤 값이 나올까요?

n에 저장된 값이 나옵니다. 즉 20이 나옵니다. (처음에 설정할 때 20으로 설정)

2) 변수 n의 메모리 주소를 출력하는 올바른 코드는 ?

int n = 5;
int *p = &n;

n의 주소는 p에 저장되어있으므로

printf("%p\n",p);

3) string s과 동일한 의미를 지니는 코드는 ?

char *s

4) char *s = "EDWITH";이 있을 때 W를 출력하는 코드는 ?

printf("%c\n",*(s+2));

s는 E의 주소를 갖고있으니 2를 더해 W의 주소값을 얻을 수 있다.

5) char *s = "EDWITH"; 상태에서 새로운 변수 t에 동일한 문자를 복사하려고 한다. 총 몇바이트의 메모리를 할당해야할까?

6byte + null종단문자 = 7byte

6) 할당된 메모리를 해제하기위해서 사용하는 함수는 ?

free()

나는 알콜프리 근데 취해

7) malloc을 이용해 할당받은 메모리는 어디에 위치?

heap에 위치합니다.

8) data.csv 파일에 값을 입력하는 프로그램을 작성하려고한다. 필요한 함수가 아닌것은 ?

fopen, fprintf, flclose는 필요하므로

fcreate()가 답이다.

9) 다음 코드에서 출력되는 값은 ?


int main(void){
	int x = 5;
    func(&x);
    printf("%i",x);
}

void func(int *y)
{
	*y = 10;
}

func함수에 주소를 주어 잘 변경했으므로 답은 10

10) swap 잘되는 코드에서 swap함수의 인수에 무엇을 주어 호출해야 적절한가요?

swap(&x,&y);

주소를 전달해야합니다.

정말 이 강의 사랑한다...

profile
개발자를 꿈꾸는 대학생

0개의 댓글