读取文本文件并显示除所有空白行和注释之外的每一行的C程序

时间:2018-10-17 23:20:33

标签: c tokenize

基本上,我需要读取一个文本文件,并且只打印完整的行,但不包括以注释或空格开头的任何内容。我很难忽略注释,或者基本上忽略;之后直到\n字符之后的内容。这将指示该行的结尾。

我认为该代码可以正常工作,但在注释后仍会打印出来,

 char* t=strtok(line,"\n ,.; ");
          while(t != NULL ) {
            if(t == ";"){
                t = strtok(NULL," ");
                while(t != NULL && t!="\n") {
                t = strtok(NULL, "");
              }
            }
            else
            {
                printf("%s\n",t);
                t = strtok( NULL, "\n ,.; \n");
            }
          }
        }

这是完整的代码:

int main()
{

char line [5000];
FILE *fp;

fp=fopen("gt.txt", "r");
if (fp == NULL)
 perror ("error opening file");
else{
  while(fgets (line, sizeof (line), fp)){
    char* t=strtok(line,"\n ,.; ");
      while(t != NULL ) {
        if(t == ";"){
            t = strtok(NULL," ");
            while(t != NULL && t!="\n") {
            t = strtok(NULL, "");
          }
        }
        else
        {
            printf("%s\n",t);
            t = strtok( NULL, "\n ,.; \n");
        }
      }
    }
  }
fclose(fp);
return(0);
}

这是我打印的内容,也用作下面的文本文件:

hello                                                                                        
goodbye 
error                                                                                        
interesting                                                                                  
comment                                                                                      
wonderful

分号是文本文件中的真实分号:

hello
goodbye


(semicolon) error
(semicolon) error

interesting (semicolon) comment

wonderful

预先感谢

2 个答案:

答案 0 :(得分:2)

  

仅打印完整行,不包括以注释或空格开头的任何内容

OP的if(t == ";"){不是必需的功能。 @Craig Estey。确保启用所有警告以节省时间。

这会将指针char *t";"进行比较,OP可能希望比较指向的字符串的内容,或者如果*t';'则可能要进行比较。


有时state machine是一种很好的简单方法。跟踪行尾。在开始新行previous == '\n'时,请检查它是否为空白行。

#include <ctype.h>
#include <stdio.h>
#define COMMENT_CHAR (';')

int main(void) {
  FILE *fp = fopen("gt.txt", "r");
  if (fp == NULL) {
    perror("error opening file");
    return EXIT_FAILURE;
  }

  bool blank_the_line = false;
  int previous = '\n';
  int ch;

  while ((ch = fgetc(fp)) != EOF) {
    if (previous == '\n') {
      blank_the_line = isspace(ch) || ch == COMMENT_CHAR;
    }
    if (!blank_the_line) {
      fputc(ch, stdout);
    }
    previous = ch;
  }

  fclose(fp);
  return EXIT_SUCCESS;
}

注意:没有行长限制。

答案 1 :(得分:0)

请注意,t == ";"可能[无效],甚至无法使用-Wall干净地编译:

orig.c: In function ‘main’:
orig.c:19:11: warning: comparison with string literal results in unspecified behavior [-Waddress]
     if (t == ";") {
           ^~
orig.c:21:28: warning: comparison with string literal results in unspecified behavior [-Waddress]
      while (t != NULL && t != "\n") {
                            ^~

if (t == ";")t中包含的地址与字符串文字";"的地址进行比较。这样做不会测试t指向的内容与字符串";"的相等性,并且几乎不会产生期望的结果。

比较字符串的通常方法是使用strcmp等。 al(例如)if (strcmp(t,";") == 0)。它将t指向的 content 与字符串进行比较。


假设;是您的注释字符,则将其添加到strtok调用的定界符arg中是不正确的,因为它将在具有 some 有效文本和以结尾的注释结尾。

注释 char 将被删除,但是从strtok返回的令牌将不再包含该注释。 ;之后返回的令牌将是其后的第一个令牌(即 comment 的第一个令牌)。但是,我们将无法检测到这一点,因此我们将打印整行-而不是我们想要的。

因此,需要对注释字符进行单独扫描,以去除注释字符和后续文本 ,然后用strtok

循环

这是应该工作的清理版本:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int
main(void)
{
    char line[5000];
    FILE *fp;
    char *cp;
    char *bp;
    char *sep;(i.e. we will strip the 

    fp = fopen("gt.txt", "r");
    if (fp == NULL) {
        perror("error opening file");
        exit(1);
    }

    while (fgets(line, sizeof(line), fp)) {
        // strip comment from right side of line (do this _before_ token scan)
        cp = strchr(line,';');
        if (cp != NULL)
            *cp = 0;

        // set up for token scan
        bp = line;
        sep = "";

        // output all valid tokens on the line
        while (1) {
            // locate next token
            cp = strtok(bp," ,.\t\n");
            bp = NULL;

            // stop if didn't find one
            if (cp == NULL)
                break;

            // print the token
            printf("%s%s",sep,cp);

            // separate tokens by a space
            sep = " ";
        }

        // end line that had _valid_ data
        if (sep[0] != 0)
            printf("\n");
    }

    fclose(fp);

    return 0;
}