如何在C语言中将一个包含4列文本的文件读入两个字符数组?

3

C - 如何将4列文件读入两个字符串数组

我正在尝试读取一个长度未知的文件,它的格式如下:

2082018 1200 79 Meeting
3082018 1300 60 Lunch
4082018 1400 30 Dinner
5082018 0600 90 Work

我试图从名为KEY_arr的数组中获取第一列,将其余列放到名为VAL_arr的数组中,满足如下条件:

KEY_Arr[0] = "2082018",VAL_arr[0] = "1200 79 Meeting"

我尝试了两种方法,都没有成功。第一种方法是使用getc在一个二维数组中读取文件:

int main(int argc, char** argv) {
    FILE *inp_cal;
    int word_count = 0;
    char c;
    char arr[50][50];
    int char_count = 0;
    int space_cnt = 0;
    char line[100];
    int line_count = 0;
    inp_cal = fopen("calendar_out.txt", "r");

            if (inp_cal) {
            printf("Processing file...\n");
            while ((c = fgetc(inp_cal)) != EOF) {
                if ((c == ' ' || c == '\n') && space_cnt == 0) {
                    arr[word_count][char_count] = '\0'; //Terminate the string
                    char_count = 0; //Reset the counter.
                    word_count++;
                    space_cnt = 1;
                } else {
                    if ((c == ' ' || c == '\n') && space_cnt == 1) {
                        word_count++;
                        char_count = 0; 
                    }

                    arr[word_count][char_count] = c;
                    printf("%c", arr[word_count][char_count]);

                    if (char_count < 50) {
                        char_count++;
                    } else {
                        char_count = 0;
                    }
                }
            }
        } else {
            printf("no file found.\n");
        }
    printf("\nword count: %d, char count: %d\n\n", word_count, char_count);
    for (int i = 0; i < word_count; i++) {
        printf("%s\n", arr[i]);
    }



    return (EXIT_SUCCESS);
}

这将产生以下输出:
2082018
1200
 79
 Meeting

3082018
 1300
 60
 Lunch

4082018
 1400
 30
 Dinner

5082018
 0600
 90
 Work

我在将其分离成键和值对的字符串时遇到了困难。我尝试过的第二种方法是使用fgets,但我没有得到任何正确的输出。
if (inp_cal) {
    printf("Processing file...\n");
    while (fgets(line, sizeof line, inp_cal)) {
        char KEY_arr[10];
        char VAL_arr[50];
        char KEY;
        char VAL;

        if (sscanf(line, "%29s%29s", KEY, VAL) != 2) { /* error, bad line */
            printf("Bad line format\n");
        } else {
            KEY_arr[line_count] = KEY;
            VAL_arr[line_count] = VAL;
            printf("%c, %c\n", KEY_arr[line_count], VAL_arr[line_count]);
        }
        line_count++;
    }
} else {
    printf("no file found.\n");
}

你有什么建议可以改进上述方法,以读取4列文本文件并存储在两个字符数组中?


这个问题太宽泛了。在尝试编写程序之前,您需要了解C语言中的字符串如何工作。 - Jabberwocky
1个回答

1
使用 fscanf(),因为您知道数据的格式,并提取每行中的每个标记。然后,第一个标记是您的键,其他三个标记意味着要一起使用,因此请使用 snprintf() 进行连接。
示例:
#include <stdio.h>
#include <string.h>

#define N 10 // max number of lines to be read
#define VALLEN 100
int main(void)
{
  int key_arr[N], a, count = 0;
  char val_arr[N][VALLEN], b[10], c[10], d[10];
  FILE* fp;
  fp = fopen("input.txt", "r");
  char bb[33];
  while (fscanf(fp, "%d %s %s %s", &a, b, c, d) != EOF) {
    if(count < N) {
      key_arr[count] = a;
      snprintf(val_arr[count++], VALLEN, "%s %s %s", b, c, d);
    }
  }
  for(int i = 0; i <count; ++i)
    printf("key=%d, val = %s\n", key_arr[i], val_arr[i]);
  fclose(fp);
  return 0;
}

输出:

key=2082018, val = 1200 79 Meeting
key=3082018, val = 1300 60 Lunch
key=4082018, val = 1400 30 Dinner
key=5082018, val = 0600 90 Work

这很简单而且有效,谢谢!我唯一看到的问题是sprintf()可能会导致缓冲区溢出,因为行数和val_arr字符串大小未知。此外,val_arr中第一个参数的前导零被忽略了,因此0600变成了600 - rrz0
1
@DawnofTime 没问题!似乎不能使用宽度说明符。关于行数,循环体内有一个if条件语句需要小心处理。然而,这是简单代码和一些内存浪费之间的权衡,如果你问我,这是一个公平的权衡。如果你的内存真的很珍贵(我不认为你在这样的环境中编程),那么你可以先计算文件的行数和每行的长度(记住最大长度是多少),然后动态分配内存。然而,从性能上来看,这是代价高昂的。 - gsamaras
1
关于 -ance,因为它需要两次解析文件。至于 0600,@DawnofTime 你是对的。我修改了代码,将最后三个标记视为字符串,其中10是我根据你的数据选择的大小,但你可能需要相应地进行调整。此外,我现在使用了 snprintf(),可以防止缓冲区溢出。 - gsamaras
感谢提供有用的信息。虽然我最初提出的问题已经得到了回答,但我仍然不断收到fscanf()返回-1的消息。通常情况下,这种情况发生在从文件中读取时出现某种错误时。 int ret = fscanf(inp_cal,“%d%s%s%s”,&a,b,c,d);打印出-1。这很可能是我的问题,因此将其标记为已回答。 - rrz0
嗯,@DawnofTime,尝试使用不同的格式说明符进行实验,因为这种方法对数据的格式很敏感。调试它,如果你仍然有问题。那么,也许明天,发布一个新的问题,如果你想的话,可以与我分享。祝你好运! - gsamaras

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接