Exam02 관련해서 예상 내용을 추려보았습니다.

Exam01에서의 내용을 추가하여 이번 시험을 준비하시면 좋을 것 같습니다. C00 ~ C07에 내용은 Exam01과 Exam02의 중복되는 내용입니다.

기본적인 접속과 시험 정답 제출 방법에 대해서는 시험 팁 링크를 참고해주세요.


C00


C언어에서 출력하는 방법에 대해서 다룬 챕터입니다.

#include "unistd.h"

write(int fd, char *buf, unsigned int size);

unistd.h 헤더에서 write 함수를 이용하여 문자 혹은 문자열을 찍는 문제들이 주로 나왔으며, 정수형의 숫자를 몫과 나머지 연산과 ascii code 이용하여 문자로 변환하고 이것을 출력하는 경험을 할 수 있는 챕터였습니다.

추가적으로 int형의 범위에 대한 것을 다루는 내용이 있습니다.


C01


C언어에서 값을 할당할 때 함수에 변수의 주소 값을 인자로 넘기고 포인터로 참조하여 값을 변경하는 방식을 배우는 챕터입니다.

기본적인 포인터에 대한 이해를 주제로 하였고 추가적으로 문자열을 다루는 방법에 대해서도 알 수 있는 챕터입니다.

추가적으로 정렬의 개념에 대해서 다루는 내용이 있습니다.

char    *pointer
char    a[] = "abcd"

// 포인터와 배열은 사실상 같은 내용이다.
// *(pointer + index) : pointer[index]
// 포인터 자체는 주소를 의미하며 배열의 인덱스를 참조한 값의 주소를 의미한다고도 할 수 있다.
// ++pointer : &pointer[1]

C02


아스키 코드값에 어떤 값이 있는 지, 어떤식으로 이용하면 좋을지에 대해서 생각해 볼 수 있는 챕터입니다. 또한 print 할 수 있는 문자와 그렇지 않은 문자에 대해서 생각해 볼 수 있습니다.

void                *addr = "abc";
unsigned long long  address;

address = (unsigned long long)addr;
ft_putnbr(address);
ft_putnbr_hex(address);

추가적으로 문자열을 복사하는 string.h의 함수를 다뤄 볼 수 있었고 마지막 문제를 통해 포인터(주소)의 값을 직접 보는 방법과 10진수를 16진수로 변환하는 방법을 경험할 수 있습니다.


C03


string.h에 나와있는 유용한 함수들을 직접 구현하여 사용방법을 익힐 수 있는 문제들로 구성되어 있습니다.

/*
strcmp : string compare
strncmp
strstr : string in string
strcat : string concatenate
strncat
strlcat
*/

C04


문자열을 정수형으로 정수형을 문자열로 양방향으로 변환하는 문제에 대해서 경험할 수 있습니다.

(문자열 <-> 정수형)

// "10001"(decimal) <-> 17 (10진수로 표현)
// "bc"(hex) <-> 188 (10진수로 표현)
// "ab0"(customed base 3 : "0ab") <-> 120 (3진수로 표현)

C05


재귀함수와 반복문에 대해서 여러가지 문제를 경험할 수 있습니다. 또한, 반복문을 재귀함수로 재귀함수를 반복문으로 생각할 수 있는 기회의 문제들이 출제됩니다.

마지막 문제로 재귀함수로 생각할 수 있는 MAP을 그려서 DFS를 구성하는 문제를 경험할 수 있습니다.

/*
factorial
pow
fibonacci
sqrt
prime
ten_queens : dfs
*/

C06


메인함수의 인자 입력에 대해서 다루는 내용을 주제로 문제들이 출제됩니다.

int argc 는 인자의 개수 char **argv는 문자열의 배열로 X 번째 인자의 string을 의미합니다.

추가적으로 argc는 항상 1이상이며 1일 때에는 인자를 입력하지 않았을 때를 의미합니다.

argv[0]에는 항상 실행파일의 이름이 들어갑니다. 예를 들어 a.out 파일을 실행하였을때 argv[0]을 출력해보면 ./a.out이 출력됩니다.

#include <stdio.h>

int main(int argc, char **argv)
{
    if (argc > 1)
        printf("인자가 입력되었습니다");
    else
        printf("./실행파일명 만이 argv에 들어갑니다");
    return (0);
}

C07


전체적인 내용은 문자열을 다루는 내용들의 문제들이 분포되어있습니다.

처음으로 동적할당에 개념에 대해서 다루기 시작합니다.

문자열의 문자열을 특정 character set을 기준으로 합치거나 문자열을 특정 character set을 기준으로 분리하는 내용의 문제가 출제되고 Shell01 마지막 문제에서 obase와 ibase를 이용했던 것 처럼 하나의 진법을 다른 진법으로 바꾸는 방법에 대해서 생각해보는 문제가 출제됩니다.

동적할당은 배열과 달리 개발자가 원하는 양의 메모리를 할당해주는 방식을 얘기합니다. 예를들어 char a[n]은 선언할 때 char형 변수 n개를 메모리에 연속적으로 할당해주는 것을 얘기합니다. 하지만 동적할당은 개발자가 원하는 시점에서 char형 변수 n개를 메모리에 할당해줄 수 있습니다. 두개의 큰 차이중 하나는 동적할당은 메모리를 점유했다 해제할 수 있다는 것이고 배열은 메모리를 함수 혹은 프로그램이 종료될 때 반환하게 됩니다.


char *p;
char **p_p;

// 변수명 = (캐스팅)malloc(sizeof(변수형) * 개수);
// 문자열의 문자열 생성
p_p = (char **)malloc(sizeof(char *) * n) // char *형을 n개만큼 메모리에 할당

// 문자열 생성
p = (char *)malloc(sizeof(char) * n) // char형을 n개만큼 메모리에 할당

// 문자열의 첫번째 문자열을 할당
*p_p = p;


exam01 예상


c00 ~ c07 까지는 문자열을 다루는 방법이 대다수이다. 또한 c06에서 메인함수를 통한 인자를 받는 방법을 배우기 때문에 인자를 받고 받은 문자열을 원하는 규칙에 맞게 처리하는 문제가 나올것으로 예상된다.

예를 들어 대소문자 변환 또는 짝수번째 문자 출력과 같은 문제가 있을 것이다.

어려운 문제로는 동적할당을 이용하여 문자열을 문자열의 문자열을 분리하는 함수를 이용하는 것이나 문자열의 문자열을 하나의 문자열로 합치는 내용들이 나올 것으로 예상된다.

예를 들어 문자열 두개를 인자로 받고 하나는 구분자로 사용하고 하나는 전체 문자열로 사용하여 구분자 단위로 문자열을 나누어 문자열의 문자열을 반환하는 함수 또는 프로그램을 작성하는 문제를 생각해 볼 수 있다.






C08


헤더와 구조체, 메크로를 다루고 있습니다. 또한 마지막 문제로 구조체의 포인터를 이용해서 출력하는 방법을 배울 수 있습니다.

예를 들어 구조체에 str과 str의 복사본 copy 그리고 이것의 길이 size가 들어있는 구조체들의 배열을 처음 부터 끝까지 각 내용을 출력하는 문제를 볼 수 있습니다.

시험에는 norm 검사가 필요하지 않음으로 불필요할 수 있지만 관련된 내용임으로 주석설명된 헤더의 예시를 보시면 좋을 것 같습니다.

#ifndef FT_HEADER_H // if not define FT_HEADER_H , #endif로 헤더가 끝납니다.
# define FT_HEADER_H // define FT_HEADER_H

# include <필요한 헤더>

# define TRUE 1
# define FALSE 0 // FALSE 는 0으로 치환됨
# define EVEN(n) (n % 2 == 0) // 전처리 매크로 EVEN(값)을 값이 짝수 인지 아닌지 판단해주는 문법으로 치환해줌

typedef struct	s_point // 구조체 s_point 라는 타입을 t_point 라는 타입으로 선언
{	// 구조체는 여러개의 내용물을 갖고 하나의 구조를 이루는 변수의 타입
	int x; // 구조체의 내용들
	int y;
}				t_point;

void	ft_name(char *a, char *b); // 구현한 프로토타입 선언

#endif // 헤더의 끝을 알림

C09


정적 라이브러리와 Make 파일에 대해서 다루는 내용을 배웁니다.

정적 라이브러리는 c 파일을 오브젝트 파일(기계 언어로 변환된 파일)로 변환한 내용을 링크할 수 있도록 모아놓은 라이브러리이다.

gcc로 컴파일 할 때 -L옵션으로 라이브러리의 디렉토리와 -l옵션으로 해당 디렉토리에서의 라이브러리를(libft.a 이면 ft만 해당된다. 즉, -lft 가 된다.)

Make file은 컴파일 과정을 쉽고 간편하게 할 수 있도록 해주는 도구이다. 프로그램을 만들 때에는 많은 함수와 내용이 필요로 하므로 c파일과 헤더파일이 많게되는데, 이 파일들을 쉽게 컴파일 할 수 있도록 해준다.

make라는 프로그램을 통해 사용할 수 있으며 Makefile에는 의존성, make의 옵션등을 정의한다.

gcc -Wall -Wextra -Werror *.c -o *.o
ar rc libft.a *.o // 모든 목적파일을 정적 라이브러리에 넣음
	//r은 새로운 파일이면 추가한다는 옵션
	//c는 libft.a 파일이 없어도 오류를 출력하지 않는다는 옵션
gcc -Wall -Wextra -Weeror main.c -L. -lft
	// 라이브러리를 이용하여 컴파일

// Makefile 예시
CC		= gcc
CFLAGS	= -Wall -Wextra -Werror
SRCS	= ./srcs/ft_strcmp.c ./srcs/ft_strcpy.c
OBJS	= ./srcs/ft_strcmp.o ./srcs/ft_strcpy.o
INC		= ./includes
RM		= rm -f
TARGET	= a.out

all : $(TARGET) // all은 최종적으로 이루어지는 내용을 의미
			// all 전에 $(TARGET)이 필요하다는 의존성을 나타냄

$(TARGET) : $(OBJS)
	$(CC) $(CFLAGS) $(OBJS) -o $(TARGET) -I$(INC)
	//$(TARGET)을 하기 전에 $(OBJS)가 필요하고
	//$(OBJS)가 만족되었으면 해당 내용을 진행함

%.o : %.c
	$(CC) $(CFLAGS) -c $< -o $@ -I$(INC)
	// 모든 c파일을 o파일로 컴파일 하라는 내용

// 모든 오브젝트 파일을 지우는 명령어
// make clean을 입력하면 진행된다.
clean :
	$(RM) $(OBJS)

// 모든 오브젝트 파일을 지우고 타겟 파일까지 지우는 명령어
// make fclean
fclean : clean
	$(RM) $(TARGET)

// fclean하고 all을 다시하는 명령어
// make re
// .PHONY는
// re라는 파일이 있으면 파일을 무시하고 실행이 가능하게함
.PHONY : re
re : fclean all


C10


난이도가 높은편에 속하는 챕터입니다. write를 지금 까지 배웠다면 이 챕터는 파일을 읽고 쓰는 방법에 대해서 다룹니다.

// 1. open : 파일을 여는 함수, 파일의 디스크립터를 받아온다.
// man 2 open 을 통해 볼 수 있습니다.
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>

int open(const char *pathname, int flags);
// 파일의 경로와 이름이 담긴 문자열과 읽기 방식 또는 쓰기 방식 등을 정하는 flag가 나온다.
// 반환값으로 int 타입 파일 디스크립터를 반환한다.

// 2. read : 파일의 내용을 읽는 함수
// man 2 read 를 통해 볼 수 있습니다.
#include <unistd.h>

ssize_t read(int fd, void *buf, size_t count);
// 파일의 내용을 읽고 읽은 수 만큼의 길이를 반환 받는다.
// buf에 읽은 파일의 내용이 복사된다.
// 해석을 하자면 fd에 해당하는 파일을 buf에 count 만큼 읽는다.

// 3. close : 파일을 열고나서 닫을 때 사용하는 함수
// man 2 close
#include <unistd.h>

int close(int fd);
// 열었던 파일을 닫는다.
// 성공인지 실패인지에 대한 값을 반환한다.

// 4. errno
#include <errno.h>

// 위에 헤더를 선언하게 되면 전역변수 int 타입의 errno를 사용할 수 있게 된다.
// errno는 파일을 열때 혹은 파일의 내용을 읽을 때에 오류 내용을 int형 값으로 하여 값이 변하게 된다.
// string.h 에서 strerror(errno)를 사용하여 에러의 내용을 확인 할 수 있다.


C11


함수 포인터에 대한 간단한 문제들이 나옵니다.

함수 포인터란 함수도 하나의 주소를 갖고 있다는 내용에서 시작합니다. 함수의 주소를 매개변수(인자)로 넘겨주고 그것을 다른 함수에서 사용할 수 있습니다.


// 예시 함수
int *function(int a, int b)
{
	return (0);
}
// 반환형이 int *이고 인자 정수형 인자를 두개 갖는 f함수의 포인터 선언
int *(*f)(int, int);
f = &function;


C12


연결리스트라는 자료형에 대해서 배웁니다.

연결리스트란, 하나의 구조체의 포인터가 다른 구조체를 가리키게 하여 연결고리와 같은 형태의 자료형입니다.

예를 들어 ㅁ->ㅁ->ㅁ->ㅁ-> 이런 형태라고 생각할 수 있습니다.

이 자료형을 어떤식으로 생성, 삽입, 삭제, 추가, 더 나아가서 정렬 등을 하는 것에 대한 내용을 배웁니다.

// 기본적인 리스트 구조체
typedef struct	s_list
{
	struct s_list *next;
	void *data;
}				t_list;

t_list *one;
t_list *two;

// one과 two에 동적할당하여 리스트를 할당
one = (t_list *)malloc(sizeof(t_list));
two = (t_list *)malloc(sizeof(t_list));

// one이 two를 가리키게함.
one->next = two;

⤧  Next post Oh-My-C-Lang - Section 2, 3 - 01 ⤧  Previous post exam01