Can someone tell me why I tried this simple C program?

I keep getting seg with an error after I finish my first cycle, and for life I don't know why. The file I'm viewing is just 18 lines in 18 lines. I think the problem is how I split the double pointer called picks, but I don’t know exactly why. I am only trying to scan lines that are less than 15 characters long, so I don't see a problem. Maybe someone can help.

#include <stdio.h> #include <stdlib.h> #include <string.h> #define MAX_LENGTH 100 int main( int argc,char *argv[] ) { char* string = malloc( 15*sizeof(char) ); char** picks = malloc(15*sizeof(char*)); FILE* pick_file = fopen( argv[l], "r" ); int num_picks; for( num_picks=0 ; fgets( string, MAX_LENGTH, pick_file ) != NULL ; num_picks++ ) { scanf( "%s", picks+num_picks ); } //this is where i seg fault int x; for(x=0; x<num_picks;x++) printf("s\n", picks+x); } 
+4
source share
7 answers

picks is a pointer to a pointer: this means that the things it points to are pointers themselves.

When you do this:

 char** picks = malloc(15*sizeof(char*)); 

You picks into a block of 15 pointers - that’s as good as possible (although since you want to read in 18 lines, you really need 18 here instead of 15). This means that picks points to a block of variables in memory:

 | picks (char **) | --------> | picks[0] (char *) | ----> ? | picks[1] (char *) | ----> ? | picks[2] (char *) | ----> ? | ... | | picks[14] (char *) | ----> ? 

As you can see, those 15 char * pointers are not initialized now - they do not indicate anything. You cannot start using them until you allocate some memory for them - you need to do something like this:

 int i; for (i = 0; i < 15; i++) { picks[i] = malloc(15); } 

Now after that the memory location is as follows:

 | picks (char **) | --------> | picks[0] (char *) | ----> | picks[0][0] (char) | | picks[0][1] (char) | | ... | | picks[0][14] (char) | | picks[1] (char *) | ----> | picks[1][0] (char) | | ... | | ... | 

... and now you have space to store all the characters you want to read.

+9
source
  • string gets enough memory to hold one character ( sizeof(char) ). If you want to keep more characters, you will need to multiply sizeof(char) by the size of the line you want to keep, plus one for zero at the end.

  • Instead:

     char** picks = malloc(15*sizeof(char)); 

    You want to do this:

     char** picks = malloc(15*sizeof(char*)); 

    Each element in the picks array must be large enough to hold the pointer.

+5
source

First of all, byte arrays (char) are stored in C-lines and should be allocated. In this situation, the line used to read the file should be allocated for MAX_LENGTH + 1 (+1 for the line character, \ 0):

 char* string = malloc( (MAX_LENGTH+1) * sizeof(char) ); 

This will allocate enough memory for the maximum length string: MAX_LENGTH.

Another problem is that the array of char **picks pointers is not allocated to store 18 lines that you expect to read:

It should be allocated for 15 char pointers (char *), which should also be allocated in the first loop.

 int main( int argc,char *argv[] ) { ... char* string = malloc( (MAX_LENGTH+1) * sizeof(char) ); char** picks = malloc(15*sizeof(char *)); FILE* pick_file = fopen( argv[l], "r" ); int num_picks; for( num_picks=0 ; fgets( string, MAX_LENGTH, pick_file ) != NULL ; num_picks++ ) { printf("pick a/an %s ", string ); //--- allocate the char array to store the current string picks[num_picks] = malloc (15 * sizeof(char)); sscanf(string, "%s", picks[num_picks] ); } for(int x=0; x<num_picks;x++) printf("%s\n", picks[x]); } 

You also need to check the return value of malloc (), and you may need to check if the contents of the file are really expected and do not contain more lines or lines longer than 15 characters.


Also scanf () reads standard input, I replaced it with sscanf () and added the missing "%" sign in the second printf ().

+3
source
  • The location pointed to by string only allocates space for one char, but you are trying to read it in MAX_LENGTH ;
  • The location pointed to by picks is allocated for only 15 char * pointers, but you apparently want to keep pointers to 18 lines;
  • The location pointed to by picks is highlighted but not initialized. You need these 15 (or 18) pointers to actually point to something themselves before passing them to scanf .

In this case, there is no need for dynamic allocation at all - you can do what you want with arrays:

 #include <stdio.h> #include <stdlib.h> #include <string.h> #define MAX_LENGTH 100 #define MAX_LINES 18 int main(int argc, char *argv[]) { char string[MAX_LENGTH]; char picks[MAX_LINES][MAX_LENGTH]; FILE *pick_file = NULL; int num_picks; if (argc > 1) pick_file = fopen(argv[1], "r"); if (pick_file == NULL) return 1; for (num_picks = 0; num_picks < MAX_LINES && fgets(string, MAX_LENGTH, pick_file) != NULL; num_picks++) { printf("pick a/an %s ", string); scanf("%s", picks[num_picks]); } int x; for (x = 0; x < num_picks; x++) printf("%s\n", picks[x]); return 0; } 
+1
source

This is because in the line:
for( num_picks=0 ; fgets( string, MAX_LENGTH, pick_file ) != NULL ; num_picks++ )
MAX_LENGTH is 100, but are you reading a string variable that can only contain a single character?

0
source

You allocate an array of fifteen char* for picks :

 char** picks = malloc(15*sizeof(char*)); 

picks now has enough space to store fifteen char* , but you really don't put any pointers inside that point to memory that should contain the characters read.

You need to allocate memory for these lines, which will be read using scanf . For the time being, scanf just writing data to where the pointers in picks (which were not initialized to indicate useful anywhere) point to.

0
source

and get an error here.

scanf( "%s", picks+num_picks );

do it instead

 for( num_picks=0 ; fgets( string, MAX_LENGTH, pick_file ) != NULL ; num_picks++ ) { pics[num_picks] = (char* )malloc(100); scanf( "%s", picks+num_picks ); } 

The problem is that u allocated **pics to store 15 lines, but u reads the lines without allocating space for these lines. make sure you always read the highlighted pointers.

0
source

Source: https://habr.com/ru/post/1304957/


All Articles