ошибка seg, вызванная malloc и sscanf в функции - PullRequest
1 голос
/ 26 мая 2010

Я хочу открыть текстовый файл (см. Ниже), прочитать первое int в каждой строке и сохранить его в массиве, но я получаю ошибку сегментации. Я избавился от всех предупреждений gcc, я прочитал несколько учебных пособий, которые нашел в сети, и искал решения для работы с stackoverflow, но я не мог разобрать, что я делаю неправильно.

Это работает, когда у меня все есть в основной функции (см. Пример 1), но не когда я передаю ее второй функции (см. Пример 2 ниже). В примере 2 я получаю, когда правильно интерпретирую gdb ошибку сегмента на sscanf (line,"%i",classes[i]);.

Боюсь, это может быть что-то тривиальное, но я уже потратил на это один день.

Спасибо заранее.

[Пример 1] Даже при том, что это работает со всем в основном:

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

const int LENGTH = 1024;

int main() {
  char *filename="somedatafile.txt";
  int *classes;
  int lines;      
  FILE *pfile = NULL; 
  char line[LENGTH];
  pfile=fopen(filename,"r");
  int numlines=0;
  char *p;

  while(fgets(line,LENGTH,pfile)){
    numlines++;
  }

  rewind(pfile);

  classes=(int *)malloc(numlines*sizeof(int));
  if(classes == NULL){
    printf("\nMemory error.");
    exit(1);
  }
  int i=0;
  while(fgets(line,LENGTH,pfile)){
    printf("\n");
    p = strtok (line," ");
    p = strtok (NULL, ", ");
    sscanf (line,"%i",&classes[i]);
    i++;
  }
  fclose(pfile);
  return 1;
}

[Пример 2] Это не относится к функциональности, переданной функции:

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

const int LENGTH = 1024;

void read_data(int **classes,int *lines, char *filename){
  FILE *pfile = NULL; 
  char line[LENGTH];
  pfile=fopen(filename,"r");
  int numlines=0;
  char *p;

  while(fgets(line,LENGTH,pfile)){
    numlines++;
  }

  rewind(pfile);

  * classes=(int *)malloc(numlines*sizeof(int));
  if(*classes == NULL){
    printf("\nMemory error.");
    exit(1);
  }
  int i=0;
  while(fgets(line,LENGTH,pfile)){
    printf("\n");
    p = strtok (line," ");
    p = strtok (NULL, ", ");
    sscanf (line,"%i",classes[i]);
    i++;
  }
  fclose(pfile);
  *lines=numlines;
}  

int main() {
  char *filename="somedatafile.txt";
  int *classes;
  int lines;

  read_data(&classes, &lines,filename) ;
  for(int i=0;i<lines;i++){
    printf("\nclasses[i]=%i",classes[i]);
  }
  return 1;
}

[Содержимое somedatafile.txt]

50 21 77 0 28 0 27 48 22 2
55 0 92 0 0 26 36 92 56 4
53 0 82 0 52 -5 29 30 2 1
37 0 76 0 28 18 40 48 8 1
37 0 79 0 34 -26 43 46 2 1
85 0 88 -4 6 1 3 83 80 5
56 0 81 0 -4 11 25 86 62 4
55 -1 95 -3 54 -4 40 41 2 1
53 8 77 0 28 0 23 48 24 4
37 0 101 -7 28 0 64 73 8 1
...

Ответы [ 2 ]

2 голосов
/ 26 мая 2010

Это:

 sscanf (line,"%i",classes[i]);

, вероятно, неправильно. Там тоже нужно разыменовать, попробуйте:

 sscanf (line,"%i", &(*classes)[i]);

Это потому, что classes является указателем на массив целых чисел. Вам нужен адрес одного из этих целых чисел, чтобы sscanf() мог написать проанализированный номер там. Следовательно, сначала вы должны разыменовать classes, чтобы получить массив, а затем сказать, что вам нужен адрес элемента i в этом массиве.

Вы также можете использовать

 sscanf (line,"%i", *classes + i);

Что может быть понятнее, в зависимости от того, насколько вам комфортно с этими вещами.

0 голосов
/ 26 мая 2010

Проблема в том, что вы применяете оператор [] к int * в первом случае и к int ** во втором. Int ** похож на 2d массив, когда вы используете оператор [] вместе с int **, вы индексируете в массив int *. В вашем случае это не то, что вы хотите, потому что вы только инициализируете первую первую запись в этом массиве. Поэтому, когда вы обращаетесь к классам [1], он падает, потому что он не инициализирован. Вы можете избежать этой путаницы, передав указатель в качестве ссылки вместо двойного указателя:

int*& classes instead of int** classes

Тогда вы можете использовать тот же код, что и в вашей основной функции.

...