首页 > 解决方案 > 我的令牌功能出现意外行为

问题描述

我正在尝试用 C 编写一个简单的 Shell。最终,我将实现进程和管道等的分叉。但是,现在,我只是想弄清楚所有的逻辑。

我有一个部分工作的外壳:当我键入 exit 时,它退出了......但是,我的令牌函数似乎无法正常工作。

我在这里做错了什么?我不确定它为什么会出现段错误。

Token在循环中打印一次,while然后它会出现段错误并崩溃。

#include <stdio.h>
#include <sys/wait.h>
#include <stdlib.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <stdbool.h>

#define MAX_BUF_SZ 1024

void checkForPipe(char *string, bool *pipe_bool);
void checkForRedirect(char *string, bool *redirect_bool);
void tokenizeInput(char *string, bool pipe, bool redirect);
int main()
{
    char *ptr;
    bool is_pipe = 0;
    bool is_redirect_out = 0;
    bool is_exit = 0;

    ptr = (char*)malloc(MAX_BUF_SZ);

    while(!is_exit)
    {
        // Diplay prompt
        char cur_dir[MAX_BUF_SZ];
        getcwd(cur_dir, MAX_BUF_SZ);
        printf("SHELL:%s$ ", cur_dir);

        fgets(ptr, MAX_BUF_SZ, stdin);
        checkForPipe(ptr, &is_pipe);
        checkForRedirect(ptr, &is_redirect_out);
        printf("pipe flag = %d\n", is_pipe);
        printf("redirect flag = %d\n", is_redirect_out);
        if(strcmp(ptr, "exit\n") == 0)
        {
            is_exit = 1;
        }

        tokenizeInput(ptr, is_pipe, is_redirect_out);

    }

    return 0;

}

void checkForPipe(char *string, bool *pipe_bool)
{
    char *check_for_pipes;
    char *clean_compare;
    check_for_pipes = (char*)malloc(MAX_BUF_SZ);
    clean_compare = (char*)malloc(MAX_BUF_SZ);

    strcpy(check_for_pipes, string);
    strcpy(clean_compare, string);

    char * token = strtok(check_for_pipes, "|");

    if(strcmp(token, clean_compare) == 0)
        {
         free(clean_compare);
         free(check_for_pipes);
        }

    else
    {
        *pipe_bool = 1;
        free(clean_compare);
        free(check_for_pipes);
    }
}

void checkForRedirect(char *string, bool *redirect_bool)
{
    char *check_for_redirects;
    char *clean_compare;
    check_for_redirects = (char*)malloc(MAX_BUF_SZ);
    clean_compare = (char*)malloc(MAX_BUF_SZ);

    strcpy(check_for_redirects, string);
    strcpy(clean_compare, string);

    char * token = strtok(check_for_redirects, ">");

    if(strcmp(token, clean_compare) == 0)
        {
         free(clean_compare);
         free(check_for_redirects);
        }

    else
    {
        *redirect_bool = 1;
        free(clean_compare);
        free(check_for_redirects);
    }

}

void tokenizeInput(char *string, bool pipe, bool redirect)
{
    char *copy_string;
    copy_string = (char*)malloc(MAX_BUF_SZ);

    strcpy(copy_string, string);

    if(pipe == 0 && redirect == 0)
    {
        char  **args = {NULL};
        char *token = strtok(copy_string, " ");
        int i = 0;
        printf("%s\n", token);
        while(token != NULL)
        {
            args[i] = token;
            strtok(NULL, " ");
            printf("%s\n", token);
            i++;
        }
    }
    /* printf("%s\n%s\n%s\n", args[0], args[1], args[2]); */
}

标签: clinuxshellstrtok

解决方案


问题出在args[i] 我修改您的代码如下:

假设您有一个预先知道的令牌数量,即MAX_BUF_SZ. 您分配 MAX_BUF_SZ 类型的指针char*

 char **args = malloc(MAX_BUF_SZ * sizeof(char *));

在循环中,您仍然必须char*在使用每个指针之前分配它:

while(token != NULL)
 {
            args[i] = (char *)malloc(strlen(token)+1);
            printf("%s\n", token);
            args[i] = token;
            token = strtok(NULL, " ");
            i++;
  }

整个函数是这样的:

void tokenizeInput(char *string, bool pipe, bool redirect)
{

    char *copy_string;
    copy_string = (char*)malloc(MAX_BUF_SZ);

    strcpy(copy_string, string);
    // suppose we would have MAX_BUF_SZ tokens
    char **args = malloc(MAX_BUF_SZ * sizeof(char *));
    if(pipe == 0 && redirect == 0)
    {
        char *token = strtok(copy_string, " ");
        int i = 0;
        //printf("token %s\n", token);

        while(token != NULL)
        {
            args[i] = (char *)malloc(strlen(token)+1);
            printf("%s\n", token);
            args[i] = token;
            token = strtok(NULL, " ");
            i++;
        }
    }
    /* printf("%s\n%s\n%s\n", args[0], args[1], args[2]); */
}

这是我运行的示例:

SHELL:D:\Users\T0180694\Documents\Mes Outils Personnels\PAN\PAN_folder$ test is essai of you and me
pipe flag = 0
redirect flag = 0
test
is
essai
of
you
and
me

推荐阅读