목록C (14)
살아가는 이야기
C의 gets는 매우 사용하기 편리하지만, 초기 설계의 문제로 인해 버퍼 오버플로(buffer overflow: 지정한 영역을 넘어 기록하는 현상)가 발생한다는 치명적 오류가 있다. 그래서 지속적으로 지원 중단 예정(deprecated) 함수로 지정되었다가 C11 이후로는 아예 지원되지 않는다. 문제는 이전에 gets를 이용하여 사용하던 코드의 경우 다시 작성해야 하는데, 이때 fgets를 사용해야 한다. fgets의 프로토타입은 다음과 같다. char *fgets(char *버퍼, size_t 크기, FILE *입력스트림); 따라서 gets로 다음과 같이 작성된 코드가 있다고 하면 gets(line); 다음과 같이 다시 작성해야 한다. fgets(line, sizeof line, stdin); 다만 줄..
2021년 추석 기념으로 프로그래밍 언어 인기도를 게시한다. 한동안 저장하지 못했던 프로그래밍 언어 인기도를 올해는 생각이 나서 측정해 보았다. 최근 게시글과 마찬가지로 TIOBE 인덱스(https://www.tiobe.com/tiobe-index/) 기준이다. 작년에 비해 조금 낮아지긴 했지만 아직 C가 부동의 1위이다. Fortran과 Delphi, Visual Basic의 약진이 놀랍다. 이후 50개의 인기 언어는 다음과 같다. 상위 10위 표에 작년 순위가 함께 게시되어 있어서 다행이라고 생각했었는데, 장기간 순위가 별도로 나와 있었다. 그래서 그것도 함께 게시한다. 장기간 순위를 보면 C/C++와 Java의 영향력이 독보적이다. 아직 대세는 C 언어 그룹임을 알 수 있다. 배우기 쉬운 BASIC..
표준입력(stdin)에서 행 단위로 읽으려면 fgets를 사용한다. 과거 사용하던 gets는 버퍼 넘침(buffer overflow) 문제로 인해 더 이상 사용하지 않는다. fgets의 인수는 fgets(버퍼, 크기, 스트림) 형식으로 사용하는데, 우리말 순서로는 인수 순서가 잘 이해되지 않지만 영어 순서로는 "get a string into 버퍼 with 크기 from 스트림"으로 읽을 수 있으므로 뜻이 통한다. 헷갈리는 것은 버퍼와 스트림 순서인데, strcpy(버퍼, 소스)의 순서처럼 우측 끝 인수가 소스(source)라고 생각하면 기억하기 쉽다. #include int main() { char line[BUFSIZ]; int sz = sizeof line, lineno = 0; while (fge..
C의 라이브러리 함수 printf에는 출력 폭을 지정하는 기능이 있다. %d가 그냥 십진수로 출력하는 것이라면 %5d는 5칸 내에 우측 정렬하여 십진수로 출력한다. 그런데 동적으로 출력폭을 지정하는 기능도 있다. 그것은 바로 별표 *이다. 출력폭을 별표로 지정하고 인수로 해당 출력폭을 주면 그 출력폭에 맞게 출력해 준다. 예컨대 다음 프로그램은 포물선을 따라 1부터 7까지 출력해 준다.#include int main() { int width = 1, i = 1; for (i = 1; i < 8; width *= 2, i++) printf("%*d\n", width, i); return 0; }사실 이 글을 전에 적은 줄 알았는데, 아무리 검색해도 나오지 않는다. 이건 건망증도 아주 이상한 건망증이다.
컴퓨터 시뮬레이션(simulation)을 할 때나 무작위로 테스트 데이터를 만들 때, 난수를 발생시켜야 하는 경우가 있다. 이런 경우를 대비해서 C 라이브러리에는 난수 발생 함수 rand()가 구비되어 있다. 물론 '진짜' 난수가 아니라 '사이비(pseudo)' 난수이긴 하지만 간단한 프로그램을 작성할 때는 매우 유용하다. 그런데 rand()를 이용하면 실행할 때마다 같은 난수 열이 발생된다. 따라서 srand()를 이용하여 난수의 시작점(seed)을 바꾸어 주어야 하는데, srand()의 인수를 다시 바꾸어 주어야 하는 문제가 발생한다. 이 때 사용할 수 있는 함수가 바로 time()이다. 간단히 말해서 다음과 같이 srand()를 호출한 후 rand()를 호출하면 실행할 때마다 다른 난수열이 발생된다..
C 언어의 표준 라이브러리에 perror라는 것이 있다. 오류 상황을 표준오류스트림(stderr)에 출력하기 위한 라이브러리 함수다. 의외로 사용법이 간단하기 때문에 초보자도 쉽게 사용할 수 있다. 간단한 예제 프로그램을 여기 적는다.#include int main() { FILE *inf = fopen("noname.inp", "r"); if (!inf) perror("ERROR in main"); return 0; }위 프로그램은 "noname.inp" 파일을 열려고 시도하다가 열 수 없으면 오류 메시지를 출력하는 함수다. 위 프로그램을 컴파일하여 실행하면 다음과 같은 출력이 나온다(물론 "noname.inp" 파일은 실행 폴더에 없어야 함).ERROR in main: No such file or d..
C 언어에 논리형이 있을까? 정답을 미리 말하면 없다. 그럼 이렇게 반론하는 사람이 있을지도 모르겠다. "예전에 다음과 같은 코드를 작성했었는데, 잘 돌아가던에요?"#include #include int main() { bool flag = true; printf("raw output: %d\n", flag); printf("str output: %s\n", flag?"true":"false"); return 0; }위 코드는 논리형 bool 타입의 flag 변수를 선언하고 이를 true로 설정한 다음 값을 출력하는 프로그램이다. printf에 %b 같은 것은 없기 때문에 값을 %d로 출력했는데, 그렇게 하면 true는 1, false는 0으로 출력된다. 따라서 두 번째 printf 문에서는 조건 연산자..
C 프로그램을 작성하다 보면 자신이 작성한 파일이 아닌데도 라이브러리의 특정 헤더 파일에서 오류가 나는 경우가 있다. 특히 오류 메시지가 이 글 제목처럼 syntax error before numeric constant 이라면 #define 문을 잘못 사용했을 수 있다. 즉 특정 헤더 파일에서 사용하는 이름(identifier)과 같은 이름을 #define 상수로 정의한 경우에 위와 같은 오류가 발생한다. 이럴 경우에는 오류가 난 헤더 파일을 찾아서 오류 위치를 확인한다. 그러면 자신이 무엇을 잘못 정의했는지 쉽게 판단할 수 있다.