【问题标题】:Read text file line by line, divide into words in C逐行读取文本文件,在C中分成单词
【发布时间】:2015-08-29 16:49:16
【问题描述】:

我正在尝试处理一些文件。文件路径存储在 txt 文件中。每行有 4 个文件名,每个文件名用空格分隔。我想将一行读入缓冲区,将缓冲区划分为这 4 个文件路径,然后处理它们。完成后,我想对下一行的文件路径执行相同的操作。

我有以下代码来处理文件名:

int i, j, check, fileidx, filenum;
char buf[100000], *testfile;
char filename_out[500], filename_mess[500], filename_ref[500], filename_dark[500];

filenum = getFileNumber("filelist.txt"); //get number of lines in the txt file

filelist = fopen("filelist.txt","r");

for (fileidx=0; fileidx<filenum; fileidx++){
    memset(&filename_mess[0], 0, sizeof(filename_mess)); //clear filenames
    memset(&filename_dark[0], 0, sizeof(filename_dark));
    memset(&filename_ref[0], 0, sizeof(filename_ref));
    memset(&filename_out[0], 0, sizeof(filename_out));
    memset(&buf[0],0,sizeof(buf));

    for (check = 0;check<fileidx+1;check++){  //up to the current file index
        testfile = fgets(buf,100000,filelist); //get each line into the buffer
            if ((testfile == NULL)&(check == fileidx)){ //if at the correct file index and line is empty
                printf("Error in filelist (line %i is empty!)",check+1);
                goto fileerror;
            };
    };

    if (fileidx==filenum-1)
            sprintf(buf,"%s\0",buf); //desperate try - not helping

    if ((buf[0] == '\n') | (buf[0] == ' ') | (buf[0] == EOF)){
        printf("Error in filelist (line %i)!",fileidx+1);
        goto fileerror;
    };

    i=0;
    while (buf[i]!=' '){ //while not hitting the first space
        if (buf[i] == '\n'){ //if a filename is missing, the end of the line is found too early
            printf("Error in filelist (line %i)! Element missing!",fileidx+1);
            goto fileerror; //goto the next file
        };
        filename_mess[i] = buf[i]; //copy the buffer to the first filename array
        i++;
    };
    i++; //skip the space between the filepaths
    j = i; //save start of second filepath
    while (buf[i]!=' '){ //repeat the process for second filename
        if (buf[i] == '\n'){
            printf("Error in filelist (line %i)! Element missing!",fileidx+1);
            goto fileerror;
        };
        filename_ref[i-j] = buf[i];
        i++;
    };
    i++;
    j = i;
    while (buf[i]!=' '){ //repeat process for third filename
        if (buf[i] == '\n'){
            printf("Error in filelist (line %i)! Element missing!",fileidx+1);
            goto fileerror;
        };
        filename_dark[i-j] = buf[i];
        i++;
    };
    i++;
    j = i;
    while ((buf[i]!='\n') & (buf[i]!= EOF) & (buf[i]!=' ')){ //we're at the last element, check for end of line or EOF here, too
        if (buf[i] == ' '){
            printf("Error in filelist (line %i)! Too many elements!",fileidx+1);
            goto fileerror;
        };
        filename_out[i-j] = buf[i];
        i++;
    };


//read the files, process them

};

此代码对除最后一行之外的所有行都运行良好。在最后一行中,只有最后一个元素存储在“filename_out”中,其他元素(mess、ref 和 dark)保持为空。缓冲区“buf”看起来不错,但是(使用printf("%s",buf) 检查它会显示预期的行)。当我在文本文件的最后一行下方添加一个空行时,读取工作正常。我还尝试使用sprintf(buf,"%s\n",buf) 每次都将这个(看似必要的)字符添加到缓冲区 - 没有用。

澄清一下:读取一个包含

的txt文件
R1E1 R1E2 R1E3 R1E4
R2E1 R2E2 R2E3 R2E4

会给我:

File1:
filename_mess = R1E1
filename_ref = R1E2
filename_dark = R1E3
filename_out = R1E4

File2:
filename_mess = 
filename_ref = 
filename_dark = 
filename_out = R2E4

虽然应该是:

File1:
filename_mess = R1E1
filename_ref = R1E2
filename_dark = R1E3
filename_out = R1E4

File2:
filename_mess = R2E1
filename_ref = R2E2
filename_dark = R2E3
filename_out = R2E4

在文本文件末尾添加一个空行将返回:

File1:
filename_mess = R1E1
filename_ref = R1E2
filename_dark = R1E3
filename_out = R1E4

File2:
filename_mess = R2E1
filename_ref = R2E2
filename_dark = R2E3
filename_out = R2E4

File3:
*Error Message*

编辑:删除了一些错误。

【问题讨论】:

  • 在这段代码中的许多不正确/有问题的事情中,while (buf[i]!=' ') - buf[i]char*,您将它与 char 文字进行比较。最大化您的编译器警告级别,因为其中标记了 许多。它至少看起来像 buf 应该是 char 数组,而不是 char* 数组。
  • 这里的代码有错误,抱歉。它实际上是char
  • 发布代码时,请将真实代码还原为minimum, complete, and verifiable example后复制/粘贴,以重现您的问题。复制/粘贴 = 没有错别字。
  • 而且由于您不需要逐行保留 fname(此代码当然不需要),因此可以将其设为 considerably simpler

标签: c text fopen fgets


【解决方案1】:
for (fileidx=0; fileidx<filenum-1; fileidx++)

这适用于单行文件吗?不应该有

【讨论】:

  • 简单fileidx &lt; filenum怎么样
  • 哇,这里还有一个错误。对不起。 -1 在实际代码中不存在。但是,是的,它确实对一行文件“起作用”。发生同样的错误。要只读取一个文件,我需要在下面添加一个空行。否则它只读取最后一个文件路径并由于某种原因忽略前三个。
【解决方案2】:

删除buf[i]== EOF 确实有效。将'\n' 添加到每个buf 的末尾并检查buf[i]=='\n' 而不是EOF

【讨论】:

    【解决方案3】:

    您可以在 cplusplus 参考中查看link 的链接,该链接描述了按顺序从文件中读取行的直接方式。

    这个link 也在 cplusplus 参考中描述了基于分隔符对字符串进行标记的直接方法(将行拆分为 4 个单独的字符串)

    使用这些链接,我设法将以下代码组合在一起,这些代码似乎可以满足您的需求

    //#include "file_processor_main_stackoverflow_question.h" //this is my own stuff
    #include <stdio.h>
    #include <string.h>
    #include <memory.h>
    #include <stdlib.h>
    #include <assert.h>
    
    
    static void parse_line(char *line, char *res[], const int n_words, const int word_length);
    
    int file_processor_so_main(int argc, char **argv) {
        int n_words = 4;
        int word_length = 1000;
    
        FILE *f = NULL;
        char buf[9999];
    
        printf("file processor main\n");
        if (argc < 2) {
            printf("usage: file_processor [file_name]\n");
            return 0;
        }
    
        printf("%s\n", argv[1]);
        f = fopen(argv[1], "r");
        if (!f) {
          printf("failed to open file: %s\n", argv[1]);
          return 0;
        }
    
        //file was opened successfully
    
        while (!feof(f)) {
          int i; char *res[4];
          if (fgets(buf, 9999, f) == NULL)
            break;
          printf("buf: %s\n", buf);
          //initialize res
          for (i = 0; i < n_words; ++i) {
            res[i] = (char*)calloc(word_length, sizeof(char));
          }
          parse_line(buf, res, n_words, word_length);
          for (i = 0; i < n_words; ++i) {
            printf("res[%d]: %s\n", i, res[i]);
            //process file at res[i]
            free(res[i]);
          }
        }
    
        fclose(f);
        return 0;
      }
    
      void parse_line(char *line, char *res[], const int n_words, const int         word_length) {
        int count = 0;
        char *buf = strtok(line, " ");
        while (buf != NULL && count < n_words) {
          printf("%s ", buf);
          assert(strlen(buf) < word_length);
          strcpy(res[count++], buf);
          buf = strtok(NULL, " ");
        }
        printf("\n");
      }
    

    【讨论】:

      猜你喜欢
      • 2011-04-12
      • 2012-10-11
      • 1970-01-01
      • 2020-09-11
      • 1970-01-01
      • 2023-02-10
      • 2022-01-25
      • 1970-01-01
      • 2010-12-24
      相关资源
      最近更新 更多