views:

110

answers:

2

Hi,

I want to open a text file (see below), read the first int in every line and store it in an array, but I get an segmentation fault. I got rid of all gcc warnings, I read through several tutorials I found on the net and searched stackoverflow for solutions, but I could't make out, what I am doing wrong.

It works when I have everything in the main function (see example 1), but not when I transfer it to second function (see example 2 further down). In example 2 I get, when I interpret gdb correctly a seg fault at sscanf (line,"%i",classes[i]);.

I'm afraid, it could be something trivial, but I already wasted one day on it.

Thanks in advance.

[Example 1] Even though that works with everything in main:

#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;
}

[Example 2] This does not with the functionality transfered to a function:

#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;
}

[Content of 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  A: 

This:

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

is probably wrong. You need to dereference there too, try:

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

This is because classes is a pointer to an array of integers. You want the address of one of those integers, so that sscanf() can write the parsed number there. Therefore, you must first dereference classes to get the array, then say that you want the address of element number i in that array.

You could also use

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

Which might be clearer, depending on how comfortable you are with these things.

unwind
Framester
danben
@danben Thanks!
Framester
A: 

The problem is you're applying the [] operator to an int* in the first case and an int** in the second. The int** is like a 2d array, when you use the [] operator in conjunction with the int** you are indexing into an array of int*. In your case this is not what you want, because you only initialize the first the first entry in this array. So when you access classes[1] it will crash because it's uninitialized. You could avoid yourself this confusion by passing in the pointer as a reference instead of a double pointer:

int*& classes instead of int** classes

Then you could use the same code as from your main function.

bshields