3

我正在尝试制作一个提示用户输入命令的程序,然后使用 exec 执行该命令。

例如,如果他们给了我“ls -la”,我将不得不执行该命令。我试过以下代码:

#include <stdio.h>
#include <unistd.h>
#include <string.h>

int main()
{

    int ret, num_args;

    printf("Enter number of arguments (Example: \"ls -la\" has 1 argument): ");
    scanf("%d", &num_args);

    char *cmd[num_args];

    printf("Enter command name: ");
    scanf("%s", &cmd[0]);

    int i;
    for (i = 0; i < num_args; i++)
    {
            printf("Enter parameter: ");
            scanf("%s", &cmd[i]);
    }

    execvp(cmd[0], cmd);
}

但是,当我尝试以下运行时,它给了我一个“分段错误”

$ ./a.out 
Enter number of arguments (Example: "ls -la" has 1 argument): 2
Enter command name: ls
Enter parameter: -la
Enter parameter: .
Segmentation fault
$

有任何想法吗?

4

5 回答 5

3

您需要为字符串分配内存。以下行仅分配num_args指向 的指针char

char *cmd[num_args];

首先,您将获得num_args + 1字符串(不要忘记命令本身是cmd[0])。最简单的方法是将内存静态分配为字符缓冲区数组:

const unsigned int MAX_LEN = 512; // Arbitrary number
char cmd[num_args + 1][MAX_LEN];

但是,现在您不能使用scanf读取一行,因为用户可以输入一个比字符缓冲区长的字符串。相反,您必须使用fgets,它可以限制用户可以输入的字符数:

fgets(cmd[i], MAX_LEN, stdin);

请记住,它fgets也会读取换行符,因此请确保删除出现的任何杂散字符(但不要假设它们在那里)。

于 2009-08-24T00:39:52.613 回答
3

如果您的实现支持它,您应该在or上使用更安全的getline()代替。 将安全地处理长行和 NULL 字符。它将分配足够的内存以适应整行。 可以分配内存,因此您以后必须自己释放它。scanf()fgets()getline()getline()

这是glibcgetline()文档

这是使用 getline 的快速修改(它仍然需要工作,错误检查,我还没有完全检查它的正确性):

#include <stdio.h>
#include <unistd.h>
#include <string.h>

int main()
{

    printf("Enter number of arguments (Example: \"ls -la\" has 1 argument): \n");

    char *num = NULL;
    size_t sz = 0;
    getline(&num, &sz, stdin);

    int num_args;
    sscanf(num, "%d", &num_args);

    char *cmd[num_args+2];
    memset(cmd, 0, sizeof(char*) * (num_args+2));

    printf("Enter command name: \n");


    int len = getline(&cmd[0], &sz, stdin); 

    cmd[0][len-1] = '\0';

    int i;
    for (i = 1; i < num_args+1; i++)
    {
        printf("Enter parameter: \n");
        sz = 0;
        len = getline(&cmd[i], &sz, stdin);
        cmd[i][len-1] = '\0';
    }

    return execvp(cmd[0], cmd);

}
于 2009-08-24T00:59:18.453 回答
2

此外,您还需要在argv传递给的条目中添加一个条目execvp,这必须(char *)NULL让它知道它已到达列表的末尾。

于 2009-08-24T00:37:00.647 回答
1

您实际上并没有为 cmd 数组指向的字符串分配任何内存。

于 2009-08-24T00:27:22.280 回答
-1

查看 scanf() 的手册页。它可以做的最巧妙的事情之一是动态地自动分配字符串缓冲区,您需要提供指向字符串的指针,而不是仅仅传递字符串并提供 %as 格式。

char *my_string;
scanf("%as", &my_string);

Then you don't need to bother with preallocating, don't need to bother with buffer overflows, etc. Just remember to free() it after you're done with it.

于 2009-08-24T04:32:47.487 回答