c 코드로 c 파일에서 주석과 문자열을 제거하려고합니다. 예제에 대한 코멘트 만 붙이겠습니다. 슬라이딩 윈도우가있어 주어진 순간에 n
및 n-1
문자 만 있습니다. 가능한 경우 중첩 된 whiles
을 사용하지 않는 알고리즘을 알아 내려고하지만 입력을 통해 getchar
을 사용해야합니다. 처음 생각했을 때 n=* and (n-1)=/
을 통해 n=/ and (n-1)=*
까지 읽었을 때 찾아 냈지만 이것이 비효율적이라고 느낀 점을 감안할 때 고려했습니다. 그렇게해야한다면이 방법을 사용할 수 있습니다.하지만 누구에게 더 나은 솔루션이 있는지 궁금합니다.중첩 된 루프가없는 슬라이딩 윈도우로 주석 제거
답변
과 같을 수 하나 개 while
루프 작성 알고리즘 :
while ((c = getchar()) != EOF)
{
... // looking at the byte that was just read
if (...) // the symbol is not inside a comment
{
putchar(c);
}
}
입력 char
이 코멘트에 속하는지 여부를 결정하려면, 당신은 상태 머신을 사용할 수 있습니다. 다음 예제에서는 4 개의 상태를가집니다. 다음 상태로 이동하기위한 규칙도 있습니다.
int state = 0;
int next_state;
while ((c = getchar()) != EOF)
{
switch (state)
{
case 0: next_state = (c == '/' ? 1 : 0); break;
case 1: next_state = (c == '*' ? 2 : c == '/' ? 1 : 0); break;
case 2: next_state = (c == '*' ? 3 : 2); break;
case 3: next_state = (c == '/' ? 0 : c == '*' ? 3 : 2); break;
default: next_state = state; // will never happen
}
if (state == 1 && next_state == 0)
{
putchar('/'); // for correct output when a slash is not followed by a star
}
if (state == 0 && next_state == 0)
{
putchar(c);
}
state = next_state;
}
위의 예는 매우 간단합니다 : 그것은 C 문자열처럼 주석이 아닌 상황에서 /*
제대로 작동하지 않습니다; //
개의 댓글 등을 지원하지 않습니다.
나는 이것을 문자열, 문자 // 주석도 포함합니다. –
이 작업을 올바르게 수행하는 것은 처음에는 생각보다 복잡 할 수 있습니다. 다른 의견에 의해 지적되었습니다. 전이를 올바르게하기 위해 상태 전이 다이어그램을 사용하여 테이블 중심 FSM을 작성하는 것이 좋습니다. 사례 진술과 함께 몇 가지 상태 이상을 시도하는 것은 오류가 발생하기 쉬운 IMO입니다.
다음은 상태 표를 직접 코드화 할 수있는 도트/그래프 형식의 다이어그램입니다. 저는 이것을 전혀 테스트하지 않았 음을 유의하십시오, YMMV.
다이어그램의 의미는 <ch>
이 표시 될 때 해당 상태의 다른 입력이 하나도없는 경우 가을입니다. 파일의 끝은 S0
을 제외한 모든 상태의 오류이며 명시 적으로 나열되지 않은 문자도 있으므로 <ch>
입니다. 주석 (S4
및 S5
)을 제외하고 시작 주석 (S1
)을 감지 할 때를 제외하고는 스캔 된 모든 문자가 인쇄됩니다. 시작 주석을 감지 할 때 문자를 버퍼링해야하고 잘못된 시작 인 경우 문자를 인쇄해야하며, 그렇지 않으면 실제로 주석인지 확인하십시오.
도트 다이어그램에서 sq
은 작은 따옴표 '
이고, dq
은 큰 따옴표 "
입니다.
digraph state_machine {
rankdir=LR;
size="8,5";
node [shape=doublecircle]; S0 /* init */;
node [shape=circle];
S0 /* init */ -> S1 /* begin_cmt */ [label = "'/'"];
S0 /* init */ -> S2 /* in_str */ [label = dq];
S0 /* init */ -> S3 /* in_ch */ [label = sq];
S0 /* init */ -> S0 /* init */ [label = "<ch>"];
S1 /* begin_cmt */ -> S4 /* in_slc */ [label = "'/'"];
S1 /* begin_cmt */ -> S5 /* in_mlc */ [label = "'*'"];
S1 /* begin_cmt */ -> S0 /* init */ [label = "<ch>"];
S1 /* begin_cmt */ -> S1 /* begin_cmt */ [label = "'\\n'"]; // handle "/\n/" and "/\n*"
S2 /* in_str */ -> S0 /* init */ [label = "'\\'"];
S2 /* in_str */ -> S6 /* str_esc */ [label = "'\\'"];
S2 /* in_str */ -> S2 /* in_str */ [label = "<ch>"];
S3 /* in_ch */ -> S0 /* init */ [label = sq];
S4 /* in_slc */ -> S4 /* in_slc */ [label = "<ch>"];
S4 /* in_slc */ -> S0 /* init */ [label = "'\\n'"];
S5 /* in_mlc */ -> S7 /* end_mlc */ [label = "'*'"];
S5 /* in_mlc */ -> S5 /* in_mlc */ [label = "<ch>"];
S7 /* end_mlc */ -> S7 /* end_mlc */ [label = "'*'|'\\n'"];
S7 /* end_mlc */ -> S0 /* init */ [label = "'/'"];
S7 /* end_mlc */ -> S5 /* in_mlc */ [label = "<ch>"];
S6 /* str_esc */ -> S8 /* oct */ [label = "[0-3]"];
S6 /* str_esc */ -> S9 /* hex */ [label = "'x'"];
S6 /* str_esc */ -> S2 /* in_str */ [label = "<ch>"];
S8 /* oct */ -> S10 /* o1 */ [label = "[0-7]"];
S10 /* o1 */ -> S2 /* in_str */ [label = "[0-7]"];
S9 /* hex */ -> S11 /* h1 */ [label = hex];
S11 /* h1 */ -> S2 /* in_str */ [label = hex];
S3 /* in_ch */ -> S12 /* ch_esc */ [label = "'\\'"];
S3 /* in_ch */ -> S13 /* out_ch */ [label = "<ch>"];
S13 /* out_ch */ -> S0 /* init */ [label = sq];
S12 /* ch_esc */ -> S3 /* in_ch */ [label = sq];
S12 /* ch_esc */ -> S12 /* ch_esc */ [label = "<ch>"];
}
만 버퍼에 대한 두 개의 문자를 사용하고자하는 단 하나의 루프 동안, 나는 당신의 상태를 추적 할 수있는 세 번째 문자 제안하기 때문에 (여부를 텍스트를 건너 뛰는 여부). 다운로드하고 컴파일 나는 또한 그것을 쉽게하기 위해 Github에서에이 코드를 게시 한
// Program to strip comments and strings from a C file
//
// Build:
// gcc -o strip-comments strip-comments.c
//
// Test:
// ./strip-comments strip-comments.c
#include <stdio.h>
#include <sys/types.h>
#include <sys/uio.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdlib.h>
/* The following is a block of strings, and comments for testing
* the code.
*/
/* test if three comments *//* chained together */// will be removed.
static int value = 128 /* test comment within valid code *// 2;
const char * test1 = "This is a test of \" processing"; /* testing inline comment */
const char * test2 = "this is a test of \n within strings."; // testing inline comment
// this is a the last test
int strip_c_code(FILE * in, FILE * out)
{
char buff[2];
char skipping;
skipping = '\0';
buff[0] = '\0';
buff[1] = '\0';
// loop through the file
while((buff[0] = fgetc(in)) != EOF)
{
// checking for start of comment or string block
if (!(skipping))
{
// start skipping in "//" comments
if ((buff[1] == '/') && (buff[0] == '/'))
skipping = '/';
// start skipping in "/*" comments
else if ((buff[1] == '/') && (buff[0] == '*'))
skipping = '*';
// start skipping at start of strings, but not character assignments
else if (((buff[1] != '\'') && (buff[0] == '"')) &&
((buff[1] != '\\') && (buff[0] == '"')))
{
fputc(buff[1], out);
skipping = '"';
};
// clear buffer so that processed characters are not interpreted as
// end of skip characters.
if ((skipping))
{
buff[0] = '\0';
buff[1] = '\0';
};
};
// check for characters which terminate skip block
switch(skipping)
{
// if skipping "//" comments, look for new line
case '/':
if (buff[1] == '\n')
skipping = '\0';
break;
// if skipping "/*" comments, look for "*/" terminating string
case '*':
if ((buff[1] == '*') && (buff[0] == '/'))
{
buff[0] = '\0';
buff[1] = '\0';
skipping = '\0';
};
break;
// if skipping strings, look for terminating '"' character
case '"':
if ((buff[1] != '\\') && (buff[0] == '"'))
{
skipping = '\0';
buff[0] = '\0';
buff[1] = '\0';
fprintf(out, "NULL"); // replace string with NULL
};
break;
default:
break;
};
// if not skipping, write character out
if ((!(skipping)) && ((buff[1])))
fputc(buff[1], out);
// shift new character to old character position
buff[1] = buff[0];
};
// verify that the comment or string was terminated properly
if ((skipping))
{
fprintf(stderr, "Unterminated comment or string\n");
return(-1);
};
// write last character
fputc(buff[1], out);
return(0);
}
int main(int argc, char * argv[])
{
FILE * fs;
if (argc != 2)
{
fprintf(stderr, "Usage: %s <filename>\n", argv[0]);
return(1);
};
if ((fs = fopen(argv[1], "r")) == NULL)
{
perror("fopen()");
return(1);
};
strip_c_code(fs, stdout);
fclose(fs);
return(0);
}
/* end of source file */
:
- 1. 중첩 된 주석 제거 bz lex
- 2. 중첩 된 슬라이딩 활동
- 3. 주석 처리 된 주석에 주석 처리 (중첩 된 주석)
- 4. 중첩 루프가없는 반복 행
- 5. 슬라이딩 윈도우로 pandas rolling_sum을 사용하는 방법
- 6. 중첩 된 주석 시스템 sql
- 7. 지도 제거 버튼 클릭시 주석 주석 (생성 된 주석)
- 8. 중첩 루프가없는 연속 3D 그리드의 이동 색인
- 9. 주석 좌표를 사용하여 주석 제거
- 10. Mongodb c-n 중첩 된 주석 체인의 주석 업데이트
- 11. MongoDB의 단일 상위 주석 내에서 중첩 된 (하위) 주석
- 12. 중첩 된 observableArray에서 항목 제거
- 13. 중첩 된 사전에서 항목 제거
- 14. 제거 중복 된 중첩 배열
- 15. QStringList에서 주석 문자 제거
- 16. XML의 중첩 주석?
- 17. 빌드의 web.config에서 주석 제거
- 18. Visual C++에서 중첩 된 주석?
- 19. 중첩 된 주석 시스템을 구현하는 방법은 무엇입니까?
- 20. 중첩 된 주석 뒤에있는 알고리즘은 무엇입니까?
- 21. 을 주석 중첩 된 삼중 따옴표 파이썬에서
- 22. 중첩 된 Jsr 303 유효성 검사 주석
- 23. Django/Python에서 중첩 된 주석 달기
- 24. NSmutableString에서 주석 문자열 제거
- 25. Laravel Blade보기의 주석 제거
- 26. Apple지도 기본 주석 제거
- 27. 자동 생성 주석 제거
- 28. Perl을 사용하여 주석 제거
- 29. mkmapview 변경 (주석 제거)
- 30. 버튼으로 주석 제거
나는 인라인 코멘트 논리를 설명과 함께 당신을 위해 함께 테스트 프로그램을 넣었습니다 상태 기계를 공식화하십시오. 나는. 문자 '*'또는 '/'또는 '\'또는 '' '또는 작은 따옴표를 만나면 이전 상태에 따라'상태 '를 업데이트합니다 (불쾌한 예는 btw입니다.주석 행 분리기'* /'를 여러 줄로 나누십시오 :'* \/n /') –
상태 머신은 이것을 개념화하는 가장 좋은 방법입니다. '/ * foo * /'스타일 C 주석을 처리 할 때는'normal','normal-seen-slash','comment','comment-seen-star'의 네 가지 상태가있을 것입니다. – Will
trigraphs를 다뤄야합니까? 시작 주석의'/'와'* '사이에 (또는 C++ 스타일 주석의'/'와'/'사이에 또는'*'와'/'사이에 백 슬래시 - 개행 문자를 처리해야합니까? C 스타일 주석의 끝)? C++ 스타일 주석 끝에 백 슬래시 - 개행 문자를 처리해야합니까? 주석을 시작하지 않는 '/ *'와 같은 다중 문자 상수를 처리합니까? 분명히, "/ * 이것은 주석이 아닙니다. * /"'는 주석이 아닙니다; 그것은 주석이 아니라는 것을 말하는 문자열입니다. (오히려 Magritte와 그의 "Ceci n'est pas un pipe"그림 - Google it.) –