2

I'm trying to read from the keyboard something like a command e.g. start game,info1,info2 and I want to split and save those two strings, one having to do with what kind of command the user,types in and the other having information about the command. I have done this so far, which reads and prints the separated by space strings but after that it hits me with this Segmentation fault (core dumped) and the console program stops.

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

typedef struct
{
    char *command;
    char *value;
} string;

string *allocate_memory();
void split_command(char* cmd_info, string **s);

int main(void) {
    char cmd[255];
    memset(cmd, 0, 255);
    do
    {
        // read command
        fgets(cmd, 255, stdin);
        cmd[strcspn ( cmd, "\n")] = '\0';

        string *str;
        str = allocate_memory();
        split_command(cmd, &str);

        puts(str->command);
        puts(str->value);

        if(!strcmp(str->command, "start"))
            printf("Starting...\n");

    } while(strcmp(cmd, "exit"));
    printf("Exiting the command line.");
    return 0;
}

string *allocate_memory() {
  string *p;
  if( (p = (string *) malloc(sizeof(string))) == NULL ) {
    printf("Memory allocation failed\n");
    exit(1);
  }
  return p;
}

void split_command(char* cmd_info, string **s) {

    string *new;
    new = allocate_memory();
    char *token;
    while ((token = strsep(&cmd_info, " ")) != NULL)
    {
      printf("%s\n", token);
      new->command = strdup(token);
    }
    new->value = strdup(token);
    puts(new->value);
    *s = new;
    free(cmd_info);

}

Compile

gcc cmd.c -o cmd.out

Output

./cmd.out 
one two
one
two
Segmentation fault (core dumped)

I've tried other stuff as well but I'm keep getting the Segmentation fault, I'm really stuck. Any help would be greatly appreciated. Thanks

Gofoboso
  • 21
  • 2

2 Answers2

1

strsep() sets token to NULL when no other delimiter is found. That NULL is then passed to strdup(), causing your the segmentation fault.

I removed the while() in split_command() (I assumed that it is a simple command arg) and added a check before the second strdup() and got it working. I also fixed some memory leaks:

  • you were allocating str in main() and then overriding it with new in split_command() losing the reference to str.
  • you were allocating a new string every loop iteration without freeing the previous one
  • you weren't freeing the strings created using strdup()

Moreover, you were freeing cmd_info which is a buffer allocated statically on the stack.

This is my version:

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

typedef struct
{
    char *command;
    char *value;
} string;

string *allocate_memory();
void split_command(char* cmd_info, string *s);

int main(void) {
    char cmd[255];
    string *str = allocate_memory();
    memset(cmd, 0, 255);
    do {
        fgets(cmd, 255, stdin);
        cmd[strcspn(cmd, "\n")] = '\0';

        split_command(cmd, str);

        if(!strcmp(str->command, "start"))
            printf("Starting...\n");

        free(str->command);
        free(str->value);
    } while(strcmp(cmd, "exit"));
    free(str);
    printf("Exiting the command line.");
    return 0;
}

string *allocate_memory() {
    string *p;
    if( (p = (string *) malloc(sizeof(string))) == NULL ) {
    printf("Memory allocation failed\n");
    exit(1);
    }
    return p;
}

void split_command(char* cmd_info, string *s) {
    char *token = strsep(&cmd_info, " ");

    s->command = strdup(token);
    token = strsep(&cmd_info, " ");
    if (token)
        s->value = strdup(token);
    else
        s->value = NULL;
}

Remember that passing NULL to puts() and such leads to problems: always check for NULL!

BreadyX
  • 47
  • 5
1

I gave a try, But If your input string more than two spaces, You should definitely modify this code.

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

typedef struct
{
    char *command;
    char *value;
} string;
string *split_command(char *cmd);

int main()
{
    char cmd[255];
    while (1)
    {
        fgets(cmd, 255, stdin);
        if (!strcmp(cmd, "exit\n"))
        {
            break;
        }
        cmd[strcspn(cmd, "\n")] = '\0';

        string *str = split_command(cmd);
        puts(str->command);
        puts(str->value);
    }
    return 0;
}

string *split_command(char *cmd)
{
    string *new_string = (string *)malloc(sizeof(string));
    if(new_string == NULL) {
        printf("MEMORY_ALLOCATION_FAILED\n");
        exit(-1);
    }
    char *token = strtok(cmd, " ");
    new_string->command = token;
    token = strtok(NULL, " ");
    new_string->value = token;
    return new_string;
}
Appaji Chintimi
  • 613
  • 2
  • 7
  • 19