将单词从文本文件获取到数组

Getting words from text file to an array

提问人:Hzyf 提问时间:3/13/2012 更新时间:6/3/2023 访问量:21277

问:

我的文本文件的格式如下:

my.txt
Red
Green
Blue
Yellow

我很想得到这样的话:

typedef char * string;
main(){
   int i;
   string array[4];

   FILE *my;
   my = fopen("my.txt","r");
   for(i = 0; i < 4; i++)
         fscanf(data, "%s", &array[i]);
   fclose(my);
}

当我尝试打印数组时出现错误。我的代码有什么问题,我该如何修复它?

c

评论

0赞 David C. Rankin 6/3/2023
typedef 指针是个好主意吗?(答案:“否”)这是对 CS50 项目如何使用 of 的一个主要抱怨,就像您在问题中所说的那样。typdefstring

答:

3赞 Filip Roséen - refp 3/13/2012 #1

您需要为以 null 结尾的字符串分配内存。

目前,您只为 4 分配内存,但这些指针未初始化,因此当您尝试将数据写入它们指向的内存时,将导致 UB(未定义的行为)。char *


工作示例片段

在下面的代码片段中使用“%127s”是为了防止我们在分配的内存范围之外写入。对于有问题的格式字符串,我们最多可以读/写 127 个字节 + null 终止符。

请记住,如果要在“现实生活”中使用,则应实施进一步的错误检查。

  • 尝试打开文件后检查是否确实有效file_handle
  • 检查是否确实分配了请求的内存malloc
  • 检查以查看读取所需的输入fscanf

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

int
main (int argc, char *argv[])
{
  int i;
  char * lines[4];
  FILE *file_handle = fopen ("my.txt", "r");

  for (i =0; i < 4; ++i) {
    lines[i] = malloc (128); /* allocate a memory slot of 128 chars */
    fscanf (file_handle, "%127s", lines[i]);
  }

  for (i =0; i < 4; ++i)
    printf ("%d: %s\n", i, lines[i]);

  for (i =0; i < 4; ++i)
    free (lines[i]); /* remember to deallocated the memory allocated */

  return 0;
}

输出

0: Red
1: Green
2: Blue
3: Yellow

评论

0赞 Paul Bénéteau 4/5/2017
分段故障fscanf (file_handle, "%127s", lines[i]);
1赞 Shahbaz 3/13/2012 #2

你试图读取一些数据,但你没有地方可以放它。你所拥有的只是 4 个指针,指向天知道在哪里,你正试图写进去!

有很多方法可以做到这一点:

  1. 您知道数据大小的绑定:

    #include <stdio.h>
    
    #define MAX_CHARS 20
    
    typedef char string[MAX_CHARS+1];  // leave one space for '\0'
    
    main(){
       int i;
       string array[4];
    
       FILE *my;
       my = fopen("my.txt","r");
       for(i = 0; i < 4; i++)
             fscanf(data, "%s", array[i]);  // no need for & with %s
       fclose(my);
    }
    
  2. 假设绑定到数据的大小,并忽略其余的字符串(如果它太大):

    #include <stdio.h>
    
    #define MAX_CHARS 20
    #define MAX_CHARS_STR "20"  // there are better ways to get this
    
    typedef char string[MAX_CHARS+1];
    
    main(){
       int i;
       string array[4];
    
       FILE *my;
       my = fopen("my.txt","r");
       for(i = 0; i < 4; i++){
             fscanf(data, "%"MAX_CHARS_STR"s", &array[i]);  // read at most 20 chars for the string
             ungetc('x', data);     // append one character to make sure we don't hit space
             fscanf(data, "%*s");   // ignore whatever is left of string
       }
       fclose(my);
    }
    
  3. 读取文件两次,第一次找出每个字符串的大小(或最大大小,为简单起见),然后为字符串分配内存(使用 )。然后再次读取文件,这次实际存储字符串:malloc

    #include <stdio.h>
    
    typedef char *string;
    
    main(){
       int i;
       string array[4];
       int cur_size = 0;
    
       FILE *my;
       my = fopen("my.txt","r");
       for(i = 0; i < 4; i++){
             fscanf(data, "%*s%n", &cur_size);
             array[i] = malloc((cur_size+1)*sizeof(*array[i]));
       }
       fclose(my);
    
       my = fopen("my.txt","r");
       for(i = 0; i < 4; i++){
             fscanf(data, "%s", array[i]);
       }
       fclose(my);
    
       // and when done:
       for(i = 0; i < 4; i++){
             free(array[i]);
       }
    }
    
  4. 逐个区块读取输入区块。对于每个字符串,如果输入字符串尚未完成,请调整为该字符串分配的内存大小(增加其大小),读取另一个块并再次检查。方法 3 虽然更快,我推荐它,但正如您所知,这基本上就是 C++ 中发生的事情。string

1赞 twain249 3/13/2012 #3

因为所有其他答案都告诉你你做错了什么,而不是如何解决它。这里

typedef char * string;
#define LEN 100 //long enough for your line
main(){
   int i;
   string array[4];

   for(i = 0; i < 4; i++) {
      if((array[i] = (char *)(malloc(sizeof(char) * LEN))) == NULL) {
          printf("malloc failed");
          return 1;
      }
   } 

   FILE *my;
   my = fopen("my.txt","r");
   for(i = 0; i < 4; i++)
         fscanf(data, "%s", &array[i]);
   fclose(my);
}

就像他们说的,你为指针腾出了空间,但没有为指针指向的内容腾出空间。