逐行阅读文本文件,分成C

时间:2015-08-29 16:49:16

标签: c text fopen fgets

我正在尝试处理一些文件。文件路径存储在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*

编辑:删除了一些错误。

3 个答案:

答案 0 :(得分:0)

for (fileidx=0; fileidx<filenum-1; fileidx++)

这适用于一个行文件吗?不应该有&lt; =?

答案 1 :(得分:0)

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

答案 2 :(得分:0)

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

cplusplus参考中的这个link描述了基于分隔符对字符串进行标记的直接方式(将该行拆分为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");
  }