删除注释的C程序
这是我第一次发帖,所以我为糟糕的格式和/或任何不合理的问题道歉 因此,我已经在“删除评论”项目上工作了一段时间,取得了一些进展,但进展甚微。我是C语言的新手,所以我用一些基本的函数和技巧来编写它。代码的输入文件不需要读取任何函数,而是使用终端中的<传递给程序 我正在使用的文本文件包含以下内容:删除注释的C程序,c,C,这是我第一次发帖,所以我为糟糕的格式和/或任何不合理的问题道歉 因此,我已经在“删除评论”项目上工作了一段时间,取得了一些进展,但进展甚微。我是C语言的新手,所以我用一些基本的函数和技巧来编写它。代码的输入文件不需要读取任何函数,而是使用终端中的
some/* crazy */stuff
some/* crazy */ stuff
some/*crazy /*crazy*/*/stuff
"some /* crazy */ stuff "
some/* "crazy" */ stuff
some/* crazy stuff
测试不同的注释格式。
到目前为止,我掌握的代码是:
#include <stdio.h>
#define IN_COMMENT 1
int main(int argc, char **argv)
{
int c;
while ((c=getchar())!=EOF)
{
if(c=='/'&&getchar()=='*')
{
while(c!='*' && getchar()!='/')
{
c = " ";
c= getchar();
}
}
if(c=='"')
{
c=getchar();
while(c!='"')
{
putchar(c);
c=getchar();
}
putchar(c);
}
}
putchar(c);
printf("done.\n");
return 0;
}
我最终得到以下结果:
一些东西
some* stuff
some**/tuff
"some /* crazy */ stuff "
some* stuff
我想不出解决这两个问题的办法。教授提出了一种通过定义不同的状态来编写程序的不同方法,但当我尝试时,它更令人困惑。您的描述重点是在流上操作和在缓冲区上操作之间的区别。在C和Java中,这两种技术都是可能的 在这里,您的任务是在流的情况下完成工作,即您不能“向前看”也不能“向后写”-您所能做的就是检索下一个字符,在适当的情况下更新一些变量,并决定是否输出该字符 这称为状态机;主循环将读取一个字符,然后根据变量所处的状态采取不同的操作 要开始,您至少需要存储以下内容:
some/* crazy */stuff
some/* crazy */ stuff
some/*crazy /*crazy*/*/stuff
"some /* crazy */ stuff "
some/* "crazy" */ stuff
some/* crazy stuff
- 无论你是否在评论中
- 如果您不在评论中,那么您是否只是阅读了
/
例如,如果设置了后一种状态,并且您得到了一个
“*”
,那么您将设置前一种状态(并重置后一种状态)。好的,解决这类问题的通常方法是。所以,只需确定状态数,并根据当前状态确定下一个字母将如何影响状态。类Smth
//#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <stdlib.h>
//#include <conio.h>
#include <string.h>
typedef enum states {
CODE,
HASH_START,
STAR_END,
COMMENT
} states;
void main() {
FILE *input = NULL;
char c;
states state;
state = CODE;
input = fopen("C:/c/code.txt", "r");
if (input == NULL) {
exit(EXIT_FAILURE);
}
while (fscanf(input, "%c", &c) == 1) {
switch (c) {
case '/' :
switch (state) {
case CODE:
state = HASH_START;
break;
case STAR_END:
//a bit ugly here, but require less states. You can omit read next
//if use more states
fscanf(input, "%c", &c);
state = CODE;
break;
}
break;
case '*' :
switch (state) {
case HASH_START:
state = COMMENT;
break;
case COMMENT:
state = STAR_END;
break;
}
break;
default:
if (state == HASH_START) {
state = CODE;
}
}
if (state == CODE) {
printf("%c", c);
}
}
//_getch();
}
/#定义(CRT)安全(NO)警告
#包括
#包括
//#包括
#包括
typedef枚举状态{
密码
开始,
星光大道,
议论
}国家;
void main(){
文件*input=NULL;
字符c;
国家;
状态=代码;
输入=fopen(“C:/C/code.txt”、“r”);
如果(输入==NULL){
退出(退出失败);
}
而(fscanf(输入,“%c”,&c)==1){
开关(c){
案例“/”:
开关(状态){
案例代码:
状态=散列\开始;
打破
案例之星(完)
//这里有点难看,但需要较少的状态。您可以省略阅读下一步
//如果使用更多的状态
fscanf(输入,“%c”、&c);
状态=代码;
打破
}
打破
案例“*”:
开关(状态){
案例哈希表开始:
状态=评论;
打破
案例评论:
状态=星端;
打破
}
打破
违约:
if(state==HASH\u START){
状态=代码;
}
}
如果(状态==代码){
printf(“%c”,c);
}
}
//_getch();
}
此代码仅删除/**/。写出更大的图表和完整的代码。#包括
#include <stdio.h>
#if 0
Description :
To delete a comment by entering the C source from standard input.
// To delete a line break up (newline remain)
/**/ To allow the nest (standard does not allow)
also replaced with a single space(The request by the standard)
#endif
int main(void){
FILE *fp = stdin;
int ch, chn;
int nest_level=0;
#if 0
in_range_comment : /* this */
in_line_comment : //this
in_string : "this"
in_char_constnt : ' '
#endif
enum { none, in_line_comment, in_range_comment, in_string, in_char_constant } status;
status = none;
while(EOF!=(ch=fgetc(fp))){
switch(status){
case in_line_comment :
if(ch == '\n'){
status = none;
putchar(ch);
}
continue;
case in_range_comment :
if(ch == '*'){
chn = fgetc(fp);
if(chn == '/'){
if(--nest_level == 0){
status = none;
putchar(' ');
}
continue;
}
ungetc(chn, fp);
} else if(ch == '/'){
chn = fgetc(fp);
if(chn == '*'){
++nest_level;
continue;
}
ungetc(chn, fp);
}
continue;
case in_string :
if(ch == '\\'){
putchar(ch);
chn = fgetc(fp);
if(chn == '"'){
putchar(chn);
continue;
}
ungetc(chn, fp);
} else {
if(ch == '"')
status = none;
putchar(ch);
}
continue;
case in_char_constant :
if(ch == '\\'){
putchar(ch);
chn = fgetc(fp);
if(chn == '\''){
putchar(chn);
continue;
}
ungetc(chn, fp);
} else {
if(ch == '\'')
status = none;
putchar(ch);
}
continue;
case none :
switch(ch){
case '/':
if('/' == (chn = fgetc(fp))){
status = in_line_comment;
continue;
} else if('*' == chn){
status = in_range_comment;
++nest_level;
continue;
} else
ungetc(chn, fp);
putchar(ch);
break;
case '"':
status = in_string;
putchar(ch);
break;
case '\'':
status = in_char_constant;
putchar(ch);
break;
default:
putchar(ch);
}
}
}
return 0;
}
#如果0
说明:
通过从标准输入中输入C源来删除注释。
//删除换行符(换行符保留)的步骤
/**/允许嵌套(标准不允许)
也替换为单个空间(标准要求)
#恩迪夫
内部主(空){
文件*fp=stdin;
int ch,chn;
int nest_level=0;
#如果0
在\u范围内\u注释:/*此*/
在注释中://this
在字符串中:“this”
在字符常量中:“”
#恩迪夫
枚举{none,in_line_comment,in_range_comment,in_string,in_char_constant}状态;
状态=无;
而(EOF!=(ch=fgetc(fp))){
开关(状态){
第行注释中的案例:
如果(ch='\n'){
状态=无;
putchar(ch);
}
持续
案例范围注释:
如果(ch=='*'){
chn=fgetc(fp);
如果(chn=='/'){
如果(--nest_level==0){
状态=无;
putchar(“”);
}
持续
}
ungetc(chn,fp);
}else if(ch=='/')){
chn=fgetc(fp);
如果(chn=='*'){
++巢穴水平;
持续
}
ungetc(chn,fp);
}
持续
字符串中的大小写:
如果(ch='\\'){
putchar(ch);
chn=fgetc(fp);
如果(chn==“”){
putchar(chn);
持续
}
ungetc(chn,fp);
}否则{
如果(ch==“”)
状态=无;
putchar(ch);
}
持续
_char_常量中的大小写:
如果(ch='\\'){
putchar(ch);
chn=fgetc(fp);
如果(chn=='\''){
putchar(chn);
持续
}
ungetc(chn,fp);
}否则{
如果(ch='\'')
状态=无;
putchar(ch);
}
持续
案例无:
开关(ch){
案例“/”:
如果('/'==(chn=fgetc(fp))){
状态=行内注释;
持续
}else如果('*'==chn){
状态=范围内注释;
++巢穴水平;
持续
}否则
ungetc(chn,fp);
putchar(ch);
打破
案例'':