【问题标题】:allocation with char pointer用 char 指针分配
【发布时间】:2018-08-15 21:39:53
【问题描述】:

我是初学者。我有一个文件,其中包含 MONSTER,ERRTU,14,2 之类的行。当我试图读取这些行并将它们存储到一个动态内存分配的数组中时。似乎它起初可以工作,但是当我稍后尝试打印它的元素时,它不能正常工作。是关于使用 char * 吗?我该如何解决这个问题?

这是我的代码;

char *lines_ptr;
line_ptr=(char *)malloc(line*(sizeof(char)*100));   
int i=0;

if (fptr==NULL){

    printf("file could not be opened.");
}
else{ 

//line=number of lines
while(!feof(fptr)){
    for(i=0;i<line;i++){

        fscanf(fptr,"%s",lines_ptr+i);

        printf("%s\n",(lines_ptr+i));
    }
}

printf("%s",(lines_ptr));//this part shows me i did something wrong.

}  

这是我的输出;

   HERO,DRIZZT,8,3
   HERO,CATTIE,6,3
   HERO,BRUENOR,10,1
   HERO,WULFGAR,12,4
   MONSTER,TROLL,4,3
   MONSTER,GOBLIN,1,3
   MONSTER,UNDEAD,1,1
   MONSTER,VERMIN,3,2
   MONSTER,MINDFLAYER,10,2
   MONSTER,ERRTU,14,2
   HHHHMMMMMMONSTER,ERRTU,14,2 

为什么会这样?

【问题讨论】:

  • 在 C 中,不赞成将 malloc 的返回值强制转换为 while(!feof(file))
  • @JGroven 应该改成什么?
  • 看看here.
  • @JGroven 所以你认为唯一的问题是在你上面看到的代码中?
  • 关于:line_ptr=(char *)malloc(line*(sizeof(char)*100)); 1) 在 C 中,任何堆分配函数(malloccallocrealloc)的返回类型为 void*。 IE。它可以分配给任何其他指针。强制转换只会使代码混乱,使其更难以理解、调试等。 2) 始终检查 (!=NULL) 返回值以确保操作成功。 3)表达式:sizeof(char)在标准中定义为1。任何东西乘以1绝对没有效果。

标签: c arrays file dynamic-memory-allocation


【解决方案1】:
HHHHMMMMMMONSTER,ERRTU,14,2 //why does it happen?

你做的事情如下。

您读取到行缓冲区,但每次将文本的开头移动1 字符。 因此,当您返回并打印缓冲区的开头时,您将获得所有先前读取的行的所有第一个字符以及最后读取的行。

【讨论】:

    【解决方案2】:

    你错误地使用了“line_ptr”(还有很多其他的东西......)。

    据我了解,您似乎想将整个文件加载到“line_ptr”中,每个文件的行都在“line_ptr[i]”中。

    如果是这样,那么我建议您花点时间编写非常简单的代码,然后再让它变得更复杂。

    例如,不要使用 malloc :对于您当前的代码,无论如何它都没用。

    假设您有一个文件最多包含 NB_LINE 行,每行最多包含 NB_MAX_CHAR 个字符。

    #define NB_LINE_MAX 50
    #define NB_CHAR_MAX 100
    
    char   lines[NB_LINE_MAX][NB_CHAR_MAX];
    size_t nbLines = 0;
    
    for (nbLines = 0; fgets(lines[nbLines], NB_CHAR_MAX, fptr); ++nbLines) {
      // Nothing to do, fgets do it for us
    }
    
    if (!feof(fptr)) {
      // problem while reading :/
    }
    
    
    printf("Test :\");
    for (size_t i = 0; i < nbLines; ++i) {
      printf("%d : %s", i, lines[i]);
    }
    

    此代码有效吗?如果是,请尝试通过首先删除 NB_LINE_MAX 来改进它(然后您可以在文件中包含您想要的多行,而不仅仅是 50 行),然后尝试删除 NB_CHAR_MAX(然后您可以拥有没有字符限制的行)。

    其他备注:

    • sizeof(char) 始终为 1。所以你可以从你的 malloc 中删除它。
    • fscanf(fptr,"%s",lines_ptr+i) 很危险。 %s 会读取它想要的许多字符,因此如果他读取 500 个字符但lines_ptr 只能容纳其中的 100 个,它会在某个不好的地方写入,并且您可能会遇到 SIGSEV 运行时崩溃。
    • while(!feof(fptr)) 已经被其他人说了,但请注意您如何使用 feof。

    【讨论】:

    • 我明白感谢您的帮助。我需要使用 malloc,我正在努力学习它。如何将 fgets() 与 malloc 一起使用?
    • fgets 与 malloc 无关。如果你想读取未知数量的东西(实际上是文件中的一行),有两种常见的方法:第一个 si 检索“某物”的总数,分配,然后填充它。第二种方法是填充它,如果你没有足够的空间,重新分配它。每个都有优点和缺点,这取决于首先检索您需要分配的东西的总数以及其他实现上下文的东西是多么“容易/可能/不惩罚”。试试第一种方法(在你的情况下,这是最简单的)。
    【解决方案3】:

    你做错了。首先仔细看看你在图片中弄乱了什么。假设输入helloworld有两行,而取第一个输入line_ptr从0开始,所以它将把你好从0存储到4,但是在第二行line_ptr递增到1,所以它将把world1存储到5,如果有更多行,这将继续. 注意:始终检查scanf()fscanf() 的返回值

    要在 c 中将行作为输入,您应该使用指针数组,例如 char *lineptr[MAXLINE];

     int readline(char* lineptr[])
     {
          char line[1000];
          for(i=0;i<MAXLINE;i++){
               if(fscanf(stdin,"%s",line)){
                  char *temp=malloc((strlen(line)+1)*sizeof(char));
                  strcpy(temp,line);
                  lineptr[i]=temp;  
               }
          }
          return i; 
     }
    

    此函数将读取变量line 中的一行,然后它将为temp 中的该行分配内存,lineptr[i] 将指向该新行。它返回读取的行数。

    【讨论】:

      【解决方案4】:

      以下建议的代码:

      1. 总是从文件中读取整行
      2. 正确检查错误
      3. 将读取的数据正确放置在“malloc”数组中
      4. 消除代码中的混乱
      5. 消除了代码中“幻数”的使用

      现在是建议的代码

          if ( !fptr )
          {
              perror( "file could not be opened." );
              exit( EXIT_FAILURE );
          }
      
          // implied else, fopen successful
      
          #define MAX_LINE_LEN 100
      
          //size_t line=number of lines
          char *line_ptr = malloc( line * MAX_LINE_LEN ));
          if( !line_ptr )
          {
              perror( "malloc failed" );
              exit( EXIT_FAILURE );
          }
      
          // implied else, malloc successful
      
          size_t i = 0;
          // Note: '%[^\n]' reads to end of line, but not the newline char
          //      AND appends a NUL byte to the end of the input
          //      '%*c' reads and discards the newline char
          // Note: using the '%*c' requires the last line in the file ends with a newline char
          //      otherwise the last call to `fscanf()` will 'hang' looking for the final newline
          while( i < lines && 1 == fscanf(fptr,"%[^\n]%*c", line_ptr+(MAX_LINE_LEN*i) ) )
          {
              printf( "%s\n", line_ptr+(MAX_LINE_LEN*i) );
              i++;
          }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2011-05-23
        • 2019-01-10
        • 1970-01-01
        • 2015-10-26
        • 2011-04-02
        • 2018-10-06
        • 2015-05-21
        • 1970-01-01
        相关资源
        最近更新 更多