如何使用 fopen 在 c 编程中跳过注释



我想在使用fgets时忽略/跳过文本文件中的注释。

问题是,如果一行中的第一个字符以#开头,我只能跳过评论。 注释以文本文件中的#开头。但是我file.txt中有一些#不是一行的第一个字符,就像这样;

#Paths
A B #Path between A and B.
D C #Path between C and D.

A 是我的第一个节点,B 是我的第二个节点,当 # 出现时,我想忽略其余文本,直到下一行。我的新节点应该是 D 和 C 等。我只能在 fopen 函数中使用"r"。 我已经尝试过fgets但它逐行读取,fgetc也无济于事。

bool ignore_comments(const char *s)
{
int i = 0;
while (s[i] && isspace(s[i])) i++;
return (i >= 0 && s[i] == '#');
}
FILE *file;
char ch[BUFSIZE];
file = fopen("e.txt", "r");
if (file == NULL) {
printf("Errorn");
fprintf(stderr, "ERROR: No file inputn");
exit(EXIT_FAILURE);
}
while(fgets(ch, BUFSIZE, file) != NULL)
{
if (line_is_comment(ch)) {
// Ignore comment lines.
continue;
printf("%c",*ch);
}
fscanf(file, "%40[0-9a-zA-Z]s", ch);
....
}

以下建议的代码:

  1. 执行所需的功能
  2. 干净地编译
  3. 正确检查错误
  4. 此答案使用状态机,基于:"InComment">

现在,建议的代码:

#include <stdio.h>
#include <stdlib.h>
int main( void )
{
int InComment = 0;
FILE *fp = fopen( "file.txt", "r" );
if( !fp )
{
perror( "fopen to read -file.txt- failed" );
exit( EXIT_FAILURE );
}
int ch;
while( (ch = fgetc(fp)) != EOF )
{
if( ch == '#' )
{
InComment = 1;
}
else if( ch == 'n' )
{
InComment = 0;
fputc( ch, stdout );
}
else if( !InComment )
{
fputc( ch, stdout );
}
}
fclose( fp );
}

方法名称也不同,但我对这个版本是正确的吗? 忽略我的肮脏方法 line_is_comment - 从第一个版本开始,除非你想玩;-)

扩展测试输入:

#Paths
A B #Path between A and B.
D C #Path between C and D.
E F
G H

输出:

rest of line read
AB rest of line read
DC rest of line read
EF rest of line read
GH rest of line read
#include <stdio.h>
bool line_is_comment(const char *s)
{
char *commentPos = const_cast<char*>(strchr(s, '#'));
if(commentPos != NULL) {
*commentPos = 0; // cut-off chars after comment
//return true; // or false then to accept the line
return commentPos == s;
}
return false;
}
#define BUFSIZE 50
int main()
{
FILE *file;
char ch[BUFSIZE];
file = fopen("e.txt", "r");
if (file == NULL) {
printf("Errorn");
fprintf(stderr, "ERROR: No file inputn");
exit(EXIT_FAILURE);
}
int x;
while(!feof(file)) {
x = fscanf(file, "%40[0-9a-zA-Z]s", ch);
if(x == 0) {
ch[0] = fgetc(file);
if(ch[0] == '#' || ch[0] == 'n') {
if(ch[0] != 'n') fgets(ch, BUFSIZE, file);
printf(" rest of line readn");
}
} else if(x<0) break;
else {
printf("%c",*ch); // continue with ... undisclosed part here
}
}
return 0;
}

您还可以利用strcspn在单个简单调用中修剪所有注释(如果不存在,则修剪缓冲区中的行尾)。您通常会从fgets()读取的缓冲区中修剪行尾的位置:

ch[strcspn (ch, "rn")] = 0;  /* trim line-ending */

您只需将"#"字符添加到拒绝列表中,如果存在注释,则在那里终止 nul。这将减少删除以'#'开头的注释并将新格式化的行输出到以下位置的完整任务:

while (fgets (ch, BUFSIZE, fp)) {   /* read every line */
ch[strcspn (ch, "#rn")] = 0;  /* trim comment or line-ending */
puts (ch);                      /* output line w/o comment */
}

一个简短的示例,将文件作为程序的第一个参数读取(如果没有给出参数,则默认从stdin读取),您可以执行以下操作:

#include <stdio.h>
#include <string.h>
#define BUFSIZE 1024    /* if you need a constant, #define one (or more) */
int main (int argc, char **argv) {
char ch[BUFSIZE];
/* use filename provided as 1st argument (stdin by default) */
FILE *fp = argc > 1 ? fopen (argv[1], "r") : stdin;
if (!fp) {  /* validate file open for reading */
perror ("file open failed");
return 1;
}
while (fgets (ch, BUFSIZE, fp)) {   /* read every line */
ch[strcspn (ch, "#rn")] = 0;  /* trim comment or line-ending */
puts (ch);                      /* output line w/o comment */
}
if (fp != stdin) fclose (fp);       /* close file if not stdin */
return 0;
}

示例输入文件

借用汤姆的示例文件:)

$ cat dat/comments_file.txt
#Paths
A B #Path between A and B.
D C #Path between C and D.
E F
G H

示例使用/输出

$ ./bin/comments_remove <dat/comments_file.txt
A B
D C
E F
G H

仔细查看,如果您有其他问题,请告诉我。

相关内容

  • 没有找到相关文章

最新更新