저는 “The C Programming Language”(K & R) 책에서이 코드를 컴파일하려고합니다. UNIX 프로그램의 베어 본 버전입니다 wc
.
#include <stdio.h>
#define IN 1; /* inside a word */
#define OUT 0; /* outside a word */
/* count lines, words and characters in input */
main()
{
int c, nl, nw, nc, state;
state = OUT;
nl = nw = nc = 0;
while ((c = getchar()) != EOF) {
++nc;
if (c == '\n')
++nl;
if (c == ' ' || c == '\n' || c == '\t')
state = OUT;
else if (state == OUT) {
state = IN;
++nw;
}
}
printf("%d %d %d\n", nl, nw, nc);
}
그리고 다음과 같은 오류가 발생합니다.
$ gcc wc.c
wc.c: In function ‘main’:
wc.c:18: error: ‘else’ without a previous ‘if’
wc.c:18: error: expected ‘)’ before ‘;’ token
이 책의 두 번째 판은 1988 년에 나왔고 저는 C를 처음 접했습니다. 아마도 컴파일러 버전과 관련이있을 수도 있고 말도 안되는 이야기 일 수도 있습니다.
현대 C 코드에서 main
함수 의 다른 용도를 보았습니다 .
int main()
{
/* code */
return 0;
}
이것은 새로운 표준입니까 아니면 유형없는 메인을 사용할 수 있습니까?
답변
문제는 당신의 처리기 정의 함께 IN
하고 OUT
:
#define IN 1; /* inside a word */
#define OUT 0; /* outside a word */
이들 각각에 후행 세미콜론이 어떻게 있는지 주목하십시오. 전처리 기가 확장하면 코드는 대략 다음과 같습니다.
if (c == ' ' || c == '\n' || c == '\t')
state = 0;; /* <--PROBLEM #1 */
else if (state == 0;) { /* <--PROBLEM #2 */
state = 1;;
두 번째 세미콜론은 중괄호를 사용하지 않기 때문에 else
이전 if
에 일치하는 항목이 없도록합니다. 따라서 IN
및 의 전 처리기 정의에서 세미콜론을 제거하십시오 OUT
.
여기서 배운 교훈은 전 처리기 문이 세미콜론으로 끝날 필요가 없다는 것입니다.
또한 항상 중괄호를 사용해야합니다!
if (c == ' ' || c == '\n' || c == '\t') {
state = OUT;
} else if (state == OUT) {
state = IN;
++nw;
}
else
위 코드에는 모호함 이 없습니다 .
답변
이 코드의 주요 문제점 은 K & R의 코드 가 아니라는 것입니다 . 이 책에는없는 매크로 정의 뒤에 세미콜론이 포함되어 있으며 다른 사람들이 지적했듯이 의미를 변경합니다.
코드를 이해하기 위해 변경하는 경우를 제외하고는 코드를 이해할 때까지 그대로 두어야합니다. 이해하는 코드 만 안전하게 수정할 수 있습니다.
이것은 아마도 여러분의 오타 일 뿐이지 만 프로그래밍 할 때 세부 사항에 대한 이해와주의의 필요성을 보여줍니다.
답변
매크로 뒤에는 세미콜론이 없어야합니다.
#define IN 1 /* inside a word */
#define OUT 0 /* outside a word */
그리고 아마
if (c == ' ' || c == '\n' || c == '\t')
답변
IN과 OUT의 정의는 다음과 같아야합니다.
#define IN 1 /* inside a word */
#define OUT 0 /* outside a word */
세미콜론이 문제를 일으켰습니다! 설명은 간단합니다. IN과 OUT은 모두 전 처리기 지시문입니다. 본질적으로 컴파일러는 소스 코드에서 IN의 모든 발생을 1로, OUT의 모든 발생을 0으로 대체합니다.
원래 코드에는 1과 0 뒤에 세미콜론이 있었기 때문에 코드에서 IN과 OUT이 바뀌었을 때 숫자 뒤의 추가 세미콜론이 잘못된 코드를 생성했습니다. 예를 들면 다음과 같습니다.
else if (state == OUT)
다음과 같이 보입니다.
else if (state == 0;)
그러나 당신이 원했던 것은 다음과 같습니다.
else if (state == 0)
해결 방법 : 원래 정의에서 숫자 뒤의 세미콜론을 제거하십시오.
답변
보시다시피 매크로에 문제가 있습니다.
GCC에는 전처리 후 중지하는 옵션이 있습니다 .(-E)이 옵션은 전처리 결과를 보는 데 유용합니다. 사실이 기술은 c / c ++에서 대규모 코드 기반으로 작업하는 경우 중요한 기술입니다. 일반적으로 메이크 파일에는 전처리 후 중지 할 대상이 있습니다.
빠른 참조 : SO 질문은 옵션을 다룹니다. Visual Studio에서 전처리 한 후 C / C ++ 소스 파일을 어떻게 볼 수 있나요? . vc ++로 시작하지만 아래에 언급 된 gcc 옵션 도 있습니다 .
답변
정확히 문제는 아니지만의 선언 main()
도 날짜가 적혀 있습니다.
int main(int argc, char** argv) {
...
return 0;
}
컴파일러는 함수가없는 함수에 대해 int 반환 값을 가정하고 컴파일러 / 링커가 argc / argv에 대한 선언 부족과 반환 값 부족을 해결할 것이라고 확신하지만 거기에 있어야합니다.
답변
코드 블록 주위에 명시적인 중괄호를 추가해보십시오. K & R 스타일은 모호 할 수 있습니다.
18 행을보십시오. 컴파일러는 문제가있는 곳을 알려줍니다.
if (c == '\n') {
++nl;
}
if (c == ' ' || c == '\n' || c == '\t') { // You're missing an "=" here; should be "=="
state = OUT;
}
else if (state == OUT) {
state = IN;
++nw;
}