如何在c中的数组指针上加载文本

问题描述 投票:-1回答:1

嘿,我想要一些帮助,我想在我的c程序上加载字典,但我采取段故障。我会喜欢一些帮助。在使用gdb进行调试时,它说它在第63行失败了,命令说:lines[i]=string_coppied

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

const int step=200;
char **loadfile();


int main()
{   
  char **words=loadfile();
  if (words==NULL) printf ("cant build structure");
  for (int i=0 ; i<100 ; i++) printf("%s \n" , words[i] );
}

char **loadfile()
{
  //We load our text file at the stack
  FILE * fpointer;
  fpointer = fopen ("word.txt" , "r");
  if (fpointer==NULL) printf ("file not loaded \n");
  else printf ("File loaded \n");

  int array_size=step;
  char ** lines=(char **)malloc(array_size*sizeof(char*));
  if (lines=NULL) printf ("cant allocate memory \n");

  char temp[100];
  int i=0;

  while (fgets(temp,100,fpointer))
  {
    //we check if the already allocated memory is full , if so we realloc
    if (i==array_size)
    { 
      array_size +=step;

      char **newlines= (char**)realloc(lines , array_size * sizeof(char*));
      if (newlines==NULL) //check if the memory was allocated
      {
         printf ("Cant reallocate memory , please try again \n ");
         return 0 ;
      }

      lines=newlines;
    }
    //now that we made sure that the memory was allocated we continue by copying the temp //
    temp[strlen(temp)-1]="\0" ;
    int length =strlen(temp);
    char * string_coppied=malloc((length+1) * sizeof(char));
    strcpy(string_coppied ,temp);
    lines[i]=string_coppied;
    i++;
  }
  return lines;

  free(lines);
  fclose(fpointer);
}
c segmentation-fault segment
1个回答
0
投票

gdb说它在第63行失败,命令说:lines[i]=string_coppied

这是因为之后

char **newlines= (char**)realloc(lines , array_size * sizeof(char*));

你不能在realloc之后使用行,因为如果可能被realloc释放,并且可见这是因为gdb发出了问题的信号


但是你的代码中存在更多问题

1)编译器在temp[strlen(temp)-1]="\0" ;行上发出错误信号,因为temp是char数组,而不是char *数组,你当然想要temp[strlen(temp)-1] = 0 ;

2)主要:

 if (words==NULL) printf ("cant build structure");
 for (int i=0 ; i<100 ; i++) printf("%s \n" , words[i] );

缺少一个else,如果worlds为NULL,你可以执行for和(尝试)访问带有未定义行为的words[i]

3)在主要

for (int i=0 ; i<100 ; i++) printf("%s \n" , words[i] );

您可以访问100个第一个单词条目来打印它们而不知道它的大小/它有多少条目,如果它有少于100个条目你有另一个未定义的行为,如果有更多你没有打印所有这些条目

loadfile必须返回条目数,例如通过输出变量char **loadfile(size_t * n)允许你做for (int i=0 ; i<n ; i++) ...

4)在loadfile中

 fpointer = fopen ("word.txt" , "r");
 if (fpointer==NULL) printf ("file not loaded \n");
 else printf ("File loaded \n");

如果你无法打开文件文件,你打印一条消息,你继续执行,你需要return NULL;

请注意,您也很乐观,因为您在打开文件时已经打印了File loaded

5)在loadfile中

 char ** lines=(char **)malloc(array_size*sizeof(char*));
 if (lines=NULL) printf ("cant allocate memory \n");

如果malloc返回NULL,则打印消息并继续执行,因此当行为NULL且未定义的行为时,您可以稍后执行lines[i]=string_coppied;

6)在loadfile中

就像我说的

 char **newlines= (char**)realloc(lines , array_size * sizeof(char*));
 if (newlines==NULL) //check if the memory was allocated
 {
     printf ("Cant reallocate memory , please try again \n ");
     return 0 ;
 }

 lines=newlines;

可以替换为

  lines= (char**)realloc(lines , array_size * sizeof(char*));
  if (lines==NULL) //check if the memory was allocated
  {
      printf ("Cant reallocate memory , please try again \n ");
      return NULL;
  }

7)在loadfile中

在做什么时(我将“\ 0”更改为0):

temp[strlen(temp)-1]=0;
int length =strlen(temp);

当你知道第二个strlen值第一个减去1时,你计算字符串长度的2倍

int length = strlen(temp) - 1;

temp[length] = 0;

但还有一个问题,你这样做是为了删除换行符,但是

  • 文件的最后一行可能不包含新行,并且在这种情况下您丢失了最后一个字符。
  • 当一行大于100个字符时,它会被剪切掉几个,并且第一个子行不包含换行符并删除它们的最后一个字符

要不切割线条,也不必复制它们,可以使用getline

8)在loadfile中

return lines;

free(lines);
fclose(fpointer);

最后两行无法执行,所以你没有自由行(但这更好,因为你返回它)并且文件没有关闭


一份提案 :

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

const int step=200;
char **loadfile(ssize_t * n);

int main()
{   
  ssize_t n;
  char **words=loadfile(&n);

  if (words == NULL)
    puts("error when reading file");
  else {
    for (ssize_t i = 0 ; i < n ; i++) {
      puts(words[i]);
      free(words[i]);
    }
  }
}

char **loadfile(ssize_t * n)
{
  *n = 0;

  //We load our text file at the stack
  FILE * fpointer = fopen ("word.txt" , "r");

  if (fpointer==NULL) {
    printf ("file not loaded \n");
    return NULL;
  }
  puts ("load file");

  int array_size = 0;
  char ** lines = NULL;

  for (;;) {
    char * lineptr = NULL;
    size_t zero = 0;
    ssize_t sz = getline(&lineptr, &zero, fpointer);

    if (sz <= 0) {
      fclose(fpointer);
      return lines;
    }

    if (lineptr[sz - 1] == '\n')
      lineptr[sz - 1] = 0;

    if (*n == array_size)
    { 
      array_size += step;
      lines = realloc(lines , array_size * sizeof(char*));

      if (lines == NULL) //check if the memory was allocated
      {
         printf ("Cant reallocate memory , please try again \n ");
         return NULL;
      }
    }

    lines[*n] = lineptr;
    *n += 1;
  }
}
© www.soinside.com 2019 - 2024. All rights reserved.