2

我正在尝试从键盘读取类似命令的内容,例如 start game,info1,info2 ,我想拆分并保存这两个字符串,一个与用户输入的命令类型有关,另一个与命令有关。到目前为止,我已经完成了此操作,它读取并打印了由空格字符串分隔的字符串,但在那之后,我遇到了这个问题Segmentation fault (core dumped),并且控制台程序停止了。

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

}

编译

gcc cmd.c -o cmd.out

输出

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

我也尝试过其他东西,但我一直遇到分段错误,我真的被卡住了。任何帮助将不胜感激。谢谢

4

2 回答 2

1

strsep()NULL当没有找到其他分隔符时将标记设置为。NULL然后将其传递给,strdup()导致您的分段错误。

我删除了while()in split_command()(我认为它很简单command arg)并在第二个之前添加了一个检查strdup()并让它工作。我还修复了一些内存泄漏:

  • 您正在分配strmain()然后newsplit_command()失去对 . 的引用时覆盖它str
  • 您在每次循环迭代时都分配了一个新字符串,而没有释放前一个字符串
  • 您没有释放使用创建的字符串strdup()

此外,您正在释放cmd_info一个在堆栈上静态分配的缓冲区。

这是我的版本:

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

请记住,传递NULLputs()等会导致问题:始终检查NULL

于 2020-06-14T17:20:25.360 回答
1

我试了一下,但是如果你输入的字符串多于两个空格,你一定要修改这段代码。

#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;
}
于 2020-06-15T06:36:43.567 回答