【问题标题】:Shell in c using strtok and an array of pointers在 c 中使用 strtok 和指针数组的 Shell
【发布时间】:2014-11-21 21:40:03
【问题描述】:

对于这个 Shell 程序,我使用函数 strtok(参见 fragmenta.h 代码)来解析用户引入的字符串。 我需要使用 strok 函数删除空格并将它们引入指针数组的结构中。这是在fragmenta.h中制作的

在主程序(shell.c)中,需要引入字符串,这个被传递给fragmenta并存储在char **arg中。之后,我使用 execvp 函数来执行命令。

问题是程序存储了整个命令,但只执行第一个单独的命令。例如,如果我们引入“ls -al”,只执行 ls 命令,所以我理解这是指针的问题。

主程序shell.c

#include<string.h>
#include<stdlib.h>
#include<stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include "fragmenta.h"
//
char cadena[50];
int pid;
int i, status;
char **arg;
pid_t pid;
//
main()
{
    printf("minishell  -> ");
    printf("Introduce the command \n");
    scanf("%[^\n]", cadena);
    if (strcmp(cadena, "exit") == 0)
    {
        exit(0);
    }
    else
    {
        pid = fork();
        if (pid == -1)
        {
            printf("Error in fork()\n");
            exit(1);
        }
        else if (pid == 0) //child proccess
        {
            arg = fragmenta(cadena);
            if (execvp(*arg, arg) < 0)      /* execute the command  */
            {
                printf("*** ERROR: exec failed\n");
                exit(1);
            }
        }
        else                                   /* for the parent:      */
        {
            while (wait(&status) != pid);
        }
    }
}

int len;
char *dest;
char *ptr;
char *aux;
char **fragmenta(const char *cadena)
{
    //
    char *token;
    int i = 0;
    //
    len = strlen(cadena);
    char *cadstr[len + 1];
    dest = (char *)malloc((len + 1) * sizeof(char));
    strcpy(dest, cadena);
    //printf("Has introducido:%s\n",dest);
    token = strtok(dest, " ");
    while ( token != NULL)
    {
        cadstr[i] = malloc(strlen(token) + 1);
        strcpy(cadstr[i], token);
        token = strtok(NULL, " ");
        i++;
    }
    *cadstr[i] = '\0';
    ptr = *cadstr;
    i = 0;
    while (cadstr[i] != NULL)
    {
        //printf("almacenado: %s\n",cadstr[i]);
        i++;
    }
    return &ptr;
}

【问题讨论】:

  • 使用fgets 而不是scanfscanf 是一个可以使用的 PITA。
  • 你能显示片段吗

标签: c shell


【解决方案1】:

你至少有两个问题。

第一个是这样的:

ptr=*cadstr;

您已经经历了所有麻烦来创建一个参数数组,然后您只需复制第一个参数并返回指向该副本的指针。

你可以去掉ptrreturn cadstr,只是它是一个局部变量,所以一旦函数返回,它就可以被覆盖或释放。

由于出于某种原因您将宇宙中的所有其他内容都存储为全局变量,因此显而易见的解决方法是将 cadstr 也设为全局变量。 (当然,您不能以这种方式使用 C99 运行时长度数组,但由于您已编写代码以保证在输入超过 50 个字符时缓冲区溢出,因此您可以安全地将其分配给 50 个字符串。)

更好的解决方案是在堆上初始化一个新数组并将所有cadstr 复制到其中。或者首先在堆上初始化cadstr


其次,您永远不要将NULL 附加到cadstr 的末尾。相反,您可以这样做:

*cadstr[i] = '\0';

这使得cadstr 中的最后一个元素指向它所指向的任何未初始化的指针,但修改了0 的第一个字节。这可能会破坏重要的内存,或者导致段错误,或者完全无害,但它不能做的一件事是将cadstr[i] 设置为指向 NULL。

当你检查这个时:

i = 0;
while (cadstr[i] != NULL)
   i++;

……你只是因为运气而摆脱了那个循环;您在分配数组的末尾读取并继续读取,直到某个其他结构或某些未初始化的内存恰好是sizeof(void*) 0s。

当你把同样的东西传递给execvp时,谁知道它会做什么呢。


您还声明了 main 没有原型,该原型已被弃用,因此您可能会从接受其余代码的任何编译器那里收到警告。要解决这个问题,只需执行int main()

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-03-11
    • 2018-01-04
    • 2013-03-10
    • 2010-10-18
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多