c - 将行解析为 ***char 时出现段错误

标签 c parsing pointers char segmentation-fault

我的代码应该将字符数组解析为 ***char,以便它首先用“|”将其分割char 然后由空格、换行符等转换成单词。输入/输出示例:

I = ls -l | sort | unique

O=

  *cmds[1] = {"ls", "-l", NULL};
  *cmds[2] = {"sort", NULL};
  *cmds[3] = {"unique", NULL};

上面是指向 char 数组的指针,因此按单词分割,下面是 ***char 以及指向上面指针的指针

  char **cmds[] = {1, 2, 3, NULL};

现在,我没有看到我的错误(可能是因为我对 C 不太熟练),但是当我从 parsePipe() 内部调用 parse(..) 函数时,程序给出了段错误。有人可以帮忙吗?

void parse(char *line, char **argv)
{
        while (*line != '\0') {     
        while (*line == ' ' || *line == '\t' || *line == '\n')
            *line++ = '\0'; 
        *argv++ = line;     
        while (*line != '\0' && *line != ' ' && *line != '\t' && *line != '\n'){
            line++;
        }
    }
    *argv = '\0';  
}

void parsePipe(char *line, char ***cmds)
{
    char *cmd = strtok(line, "|");
    int word_counter = 0;

    while (cmd != NULL) 
    {
       printf("Printing word -> %s\n", cmd);
       word_counter++; 
       parse(cmd, *cmds++);

       cmd = strtok(NULL, "|");
    }

    printf("This string contains %d words separated with |\n",word_counter);
}


void  main(void)
{
    char  line[1024];          
    char  **cmds[64]; 
    while (1) {    
        printf("lsh -> ");   
        gets(line);     
        printf("\n");
        parsePipe(line, cmds);
    }
}

最佳答案

[评论太长]

这一行

*argv++ = line; /* with char ** argv */

指的是无效内存,因为代码中的*argv[n](带有字符**argv[64])没有任何内容。

您使用的命名并不会让生活变得更轻松。

尝试以下命名:

void parse(char *line, char **cmd)
{
    while (*line != '\0') {     
        while (*line == ' ' || *line == '\t' || *line == '\n')
            *line++ = '\0'; 
        *cmd++ = line;     
        while (*line != '\0' && *line != ' ' && *line != '\t' && *line != '\n'){
            line++;
        }
    }
    *argv = '\0';  
}

void parsePipe(char *line, char ***cmdline)
{
    char *cmd = strtok(line, "|");
    int word_counter = 0;

    while (cmd != NULL) 
    {
       printf("Printing word -> %s\n", cmd);
       word_counter++; 
       parse(cmd, *cmdline++);

       cmd = strtok(NULL, "|");
    }

    printf("This string contains %d words separated with |\n",word_counter);
}


void  main(void)
{
    char  line[1024];          
    char  **cmdline[64]; 
    while (1) {    
        printf("lsh -> ");   
        gets(line);     
        printf("\n");
        parsePipe(line, cmdline);
    }
}

因为 cmd 所使用的内存都没有被分配。

所以

*cmd++ = line;

失败,因为cmd无处指向,但被取消引用,代码尝试写入它所指向的位置,但无处可去,即无效内存。

<小时/>

可以通过将 char*** 传递给 parse(char *** pcmd) 并计算找到的标记来解决此问题

size_t nlines = 0;

...

++nlines.

并且正在做

*pcmd = realloc(*pcmd, nlines + 1); /* Allocate one more as needed to later find the end of the array. */
(*pcmd)[nlines -1] = line;
(*pcmd)[nlines] = NULL; /* Initialise the stopper, marking the end of the array. */

对于找到的每个 token 。

显然你需要这样调用它:

 parse(cmd, cmdline++);

要完成所有这些工作,初始数组需要正确初始化(无论如何你都应该这样做):

char  **cmdline[64] = {0};

关于c - 将行解析为 ***char 时出现段错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27091723/

相关文章:

c - C 中的二进制分解

json - Swift,当 key 未知/动态时,如何使用 Decodable 和 Codable 解析/解码 JSON

c - 为什么这个程序有意外的指针值?

c++ - 指针 vector 的运算符<<重载抛出错误

c - libcurl 下载文件大小超过缓冲区大小

c++ - 如何在 C++ 中初始化指向特定内存地址的指针

c - 用于蓝牙传输的 Ruby 字符数组到字节数组(十六进制字符)

c++ - 如何在不跳过 eol 的情况下使用 skipper ascii::space?

java - 如何从 Java 中的 HTML 文件中获取值?

c - int * 和 int [] 之间的实际区别是什么?