【问题标题】:how to fill character pointer array with pointers to strings stored in another array?如何用指向存储在另一个数组中的字符串的指针填充字符指针数组?
【发布时间】:2013-10-22 17:13:26
【问题描述】:

我正在尝试创建一个 shell,但在尝试用用户输入填充 *argv[] 数组时遇到了麻烦。我调用我的解析函数,并将每个单词存储到一个二维数组中。我尝试了许多不同的方法将它直接存储到 *argv[] 中,但最终决定尝试使用 2d 数组。无论如何用指向存储在二维数组中的字符串的指针填充 *argv[] 吗?或者用指向字符串的指针填充 *argv[] 而不使用二维数组?

我尝试了很多其他方法,但我目前的尝试是调用 parse 函数后的 while 循环。

int main() {
   int status, fRedirect, i;
   pid_t pid;
   char s[STORAGE];
   char p[MAXITEM][STORAGE];
   char *argv[MAXITEM];
   for(;;) {
       printf("\2: ");
       scanf("%s", s);
       parse(s, p);
       while(p[i] != '\0') {
           args[i] = *p[i];
       }
       if(p[0] == EOF)
           break;
       if(p[0] == '\0')
          continue;
    pid = fork();
    if(pid == 0) {
        if(execvp(*p, p) == -1) {
            printf("Execution failed!\n");
            exit(9);
        }
    }
    if(pid != 0) {
        wait(-1, &status, 0);
    }
    else {
        fRedirect = open("/dev/null", O_WRONLY);
        dup2(fRedirect, STDOUT_FILENO);
    }

}
/*killpg(getpid(), SIGTERM);*/
printf("p2 terminated. \n");
exit(0);
}

void parse(char *s, char p[][STORAGE]) {
    int i, j = 0;
    while(*s != EOF && *s != '&' && *s != '\n' && *s != ';' && *s != '\0') {
        for(i=0; i < strlen(s); i++)
            p[j][i] = s[i];
        i = i+getword(s);
        j++;
    }
}

【问题讨论】:

  • 提示:您的解析函数应该从 s 填充 argv,可能对每个条目使用 strdup,然后您的 execvp 应该看起来像 execvp(argv[0], argv);。请注意,从 scanf 扫描的字符串永远不会包含 EOF。
  • 在上面的评论中我应该说“strtok 和 strdup”而不仅仅是 strdup
  • 我的解析函数应该返回 char ** 吗?还是它也在解析函数之外填充?
  • 好奇,是否要求您在主函数中填写*argv[]?还是可以从命令行与argc一起填写?如果您需要在 main() 中填充它,那么我相信您需要先进行一些内存分配。如果以传统方式使用,主函数定义会在从命令行读取参数时为您处理。
  • 进行了全面检查,现在 argv 似乎充满了争论。我试图发布我更新的代码作为答案,但我不能再等 5 个小时,因为我没有足够的声誉!我会在晚上结束时将其发布回来。 @ryyker 我想使用 argv[] 来执行命令,我现在正在处理。

标签: c arrays shell pointers


【解决方案1】:

我在您的代码中看到您已将 char *argv[MAXITEM]; 包含在 main() 的函数体中。这不是传统上使用*argv[] 的方式。主函数定义中包含处理*argv[] 的内存的代码。使用 main() 中的字符串解析和转换函数,可以按照通常的方式将命令行参数解析为字符串、整数、浮点数。如果您有兴趣,这里有一篇解释 char *argv[] 的帖子,其中包含更多细节,

对于字符串参数的简单示例(类似于您正在执行的操作),请看下面如何使用它,它可能会立即为您解决几个问题,例如简化您获取和解析的方式你的输入。

首先,回答你的问题:有没有办法填充*argv[]用指向存储在二维数组中的字符串的指针? 或者填充 *argv[] 使用指向字符串的指针而不使用二维数组?

没有。

但是,您可以用字符串常量填充它。 char *Argv[] 本身就是一个变量,在 main 中使用时可以包含字符串数组(指向字符串数组的指针),如下所示:

#include <ansi_c.h>
int main(int argc, char *argv[]) //Note: the`[]` blank brackets allow any string length.  
                                 // the `*` allows multiple arguments
{
     int i;
     for(i=0;i<argc;i++)         //argc contains the count of cmd line arguments
    {
        printf("%s\n", argv[i]); //*argv[] holds multiple string arguments 
    }                         

     getchar();                  //optional - pauses execution so I can see output
    return 0;
}

测试:
构建为 play.exe,然后使用命令行参数运行它,例如:

“argument1”“argument2”“你好”

输出应该是:(本质上是把你的输入解析成可变字符串)

【讨论】:

  • 我使用你的 for 循环的想法来打印 *argv[] 的内容,现在似乎可以正常工作了。谢谢
【解决方案2】:

好的,在进行了更多工作并添加了更多功能之后,这就是我目前正在使用的内容。据我所知,parse() 命令现在用从命令行获取的单词填充 *argv[]。

int main() {
    pid_t pid, child_pid;
    int argc, inputRedirect;
    char *devNull;
    devNull = (char *) malloc(10);
    strcpy(devNull, "/dev/null");
    char *argv[MAXITEM];
    char commandLine[STORAGE];

    signal(SIGTERM, myhandler);

    for (;;) {
        printf("p2: ");
        scanf("%s", commandLine);
        if(commandLine == EOF)
            break;
        argc = parse(commandLine, argv);
        if (argv[0] == '\0')
            continue;
        if(argv[0] = "cd")
            changeDir(argv[1]);
        child_pid = fork();
        if (child_pid < 0) {
            printf("Cannot fork! Terminating...");
            exit(1);
        } else if (child_pid == 0) {
            CHK(inputRedirect = open(devNull, O_RDONLY));
            CHK(dup2(inputRedirect, STDIN_FILENO));
            CHK(close(inputRedirect));
            CHK(execvp(*argv, argv));
        }
        else {
            for(;;) {
                CHK(pid = wait(NULL));
                if(pid == child_pid)
                    break;
            }
            printf("Child's pid is %d\n", child_pid);
        }
    }
    killpg(getpid(), SIGTERM);
    printf("p2 Terminated.\n");
    exit(0);
}

int parse(char *commandLine, char *argv[]) {
    int argc = 0;
    char *commandPointer = commandLine;
    while (*commandPointer != '\0') {
        *argv = commandPointer;
        argc++;
        getword(commandPointer);
    }
    *commandPointer = '\0';
    *argv = '\0';
    return argc;
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2021-06-28
    • 1970-01-01
    • 2014-11-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-06-22
    相关资源
    最近更新 更多