【问题标题】:How do I store a txt file as a two array of strings?如何将 txt 文件存储为两个字符串数组?
【发布时间】:2016-01-17 05:37:21
【问题描述】:

现在我被困在如何从文本文件中获取字符串并根据这些单词创建两个单独的数组。文件中的字符串示例如下:

BQN 阿瓜迪亚,波多黎各

格式:

<3 letter code><2 white spaces><a string up to 100 characters>

有一个 100 strings 列表,我正在尝试创建一个数组来仅存储 3 个字母代码,另一个 array 来存储机场。

代码:

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

    #define MAX_LINE_LENGTH 1000

    int main()
    {
      FILE *airports;
      airports = fopen("airports.txt", "r");
      FILE *routes;
      routes = fopen("routes.txt", "r");
      FILE *flights;
      flights = fopen("flights.txt", "r");

      char line[MAX_LINE_LENGTH];
      char air[100][3];
      char airp[100][100];


      if (airports == NULL)
        {
           printf("Could not open database files\n");

        }
      else
        {
          int i = 0;
          while(fgets(line, MAX_LINE_LENGTH, airports) != NULL)
            {
              sscanf(line, "%s" , air[i]);
              strcpy(airp[i], line+5);
               i++;


            }
          printf("%s" "%s", air, airp);

这个项目还有很多,所以代码不完整。

我已经包含了 printf 只是为了查看数组是否有效。到目前为止,它只在一行中打印了所有 3 个字母代码,后跟第一个机场。

我的描述有点混乱,但我们将不胜感激!

【问题讨论】:

  • printf("%s" "%s", air, airp); 只打印每个数组中的第一个元素。我猜你想把它放在while 循环中并更改为printf("%s %s\n", air[i], airp[i]);
  • 并且您应该警惕sscanfstrcpy 调用中的缓冲区溢出。
  • 不要缩进文件打开测试下的所有内容,只需测试if (airports == NULL) { printf (...); return 1; } 并在那里完成if 块。你所做的很好,你可以很容易地结束比必要更多的缩进。换句话说,你可以不用else
  • @kaylum sscanf 和 strcpy 不应该将所有字符串放入字符串数组中,因此 printf 不应该打印出整个数组吗?如果是这样,我不需要将 printf 放入 while 循环中吗?另外,缓冲区溢出是什么意思?
  • @Peter 建议你复习一下 C 指针和数组。是的,你确实有一个字符串数组。但是您不能使用单个格式说明符打印任何内容的数组。 air 本身只给出数组中的第一个元素。 RE 缓冲区溢出 - 每个air[i] 只有 3 个字节长。存储 3 个字符的字符串需要 4 个字节,因为每个字符串的末尾都有一个 NUL 终止符。此外,如果在字母代码长度超出预期的情况下输入错误,会发生什么?良好的编程要求您防止任何不良输入。

标签: c arrays string io


【解决方案1】:
#include  <stdlib.h>
#include <stdio.h>
#include <string.h>


#define MAX_LINE_LENGTH 100
int  getline(char ** lineptr, size_t * linelen, FILE * stream);


int main()
{
  FILE *airports;
  airports = fopen("airports.txt", "r");
  FILE *routes;
  routes = fopen("routes.txt", "r");
  FILE *flights;
  flights = fopen("flights.txt", "r");

  char line[MAX_LINE_LENGTH];

  char air[5][100];
  char airp[100][100];
    int i = 0,lines=0;

  if (airports == NULL)
    {
       printf("Could not open database files\n");
        exit(1);
    }
  else
    {


        while (fgets( line,  MAX_LINE_LENGTH, airports)  )
        {
            for(int j=0 ; j<MAX_LINE_LENGTH;j++){
                if(line[j]=='\n'){
                    line[j]=0;
                    break;
                }
            }

            sscanf(line, "%3s" , air[lines]); //first 3 chars
            strcpy(airp[lines],&line[4]);   // the remaining chars starting from 4

            lines++;

            if(lines==100) // up to 100 line allowed
                break;

        }
      fclose(airports);
    }

    // printing the arrays
    for(i=0;i<lines;i++){
        printf("%d - '%s' - '%s'\n",i+1,air[i],airp[i]);
    }


}

【讨论】:

  • 友情提示:您错误地使用了getline()pline 指向无法使用free() 函数释放的内存,违反了documentation for getline() 规定的要求(你也可以view alternative documentation for the GNU implementation。)如果你想测试它,#define MAX_LINE_LENGTH 2。换句话说,char *line = malloc(N); 是正确的方法(或者只是char *line = NULL;)。否则,你可以getline(&amp;line, ...
  • @Chrono Kitsune?正确,但是有足够的空间来容纳一行,所以它不会尝试重新分配它,如果我不确定行大小应该如何,我将传递一个空指针,函数将为我分配内存,我只需释放它。 (但现在所有这些只会用不必要的代码破坏代码)
  • @Chrono Kitsune,他将 MAX_LINE_LENGTH 定义为 1000,这对于机场名称来说太多了,100 可以接受并且足够了。
  • 我明白你的意思。但是,您大多违背了使用getline() 的目的,并且应该只使用fgets() 来避免可能的段错误,无论情况多么不可能。您甚至没有存储返回的行长,因此fgets() 是更好(更安全)的选择。
  • 我认为你是对的,我现在就纠正这个问题
猜你喜欢
  • 2021-02-09
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-10-16
  • 1970-01-01
  • 2020-08-22
  • 1970-01-01
  • 2011-09-07
相关资源
最近更新 更多