【问题标题】:How do I clear this array pointer in C?如何在 C 中清除此数组指针?
【发布时间】:2009-05-17 00:26:58
【问题描述】:

我正在尝试使用系统调用来做一个基本的 bash,但我在使用指针数组时遇到了一些小问题。

为了恢复我的代码,我使用 read() 从标准输入读取命令到缓冲区,然后使用 strsep() 将命令与参数分离,并将所有参数放入一个数组中。然后我使用 fork() 创建一个新进程,并使用 execvp() 使用相关参数执行该命令。

所有这一切都进入一个无限循环,直到用户键入“退出”(尚未编码)。问题是在第一次迭代之后,我需要 *pArgs 为空,用于下一个命令和参数。而且我不知道该怎么做...

这是我的代码:

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

int main(int argc, char **argv) {
    char bBuffer[BUFSIZ], *pArgs[10], *aPtr = NULL, *sPtr;
    int aCount;
    pid_t pid;

    while(1) {
        write(1, "\e[1;31mmyBash \e[1;32m# \e[0m", 27);
        read(0, bBuffer, BUFSIZ);

        sPtr = bBuffer;
        aCount = 0;

        do {
            aPtr = strsep(&sPtr, " ");
            pArgs[aCount++] = aPtr;
        } while(aPtr);

        pArgs[aCount-2][strlen(pArgs[aCount-2])-1] = '\0';

        // Debug code to output pArgs content
        write(1, "|>", 2);
        write(1, pArgs[0], strlen(pArgs[0]));
        write(1, "<|", 2);

        if(strlen(pArgs[0]) > 1) {
            pid = fork();

            if(pid == -1) {
                perror("fork");
                exit(1);
            }

            if(pid == 0) {
                execvp(pArgs[0], pArgs);
                exit(0);
            }
        }
    }

    return 0;
}

P.S:抱歉,我目前无法提供输入和输出测试用例。希望这并不难理解和修复,你们不需要它。如果需要的话,我会在稍后发布...

只是为了澄清:
我知道我问过如何清除数组,我得到了答案。但现在对我来说很明显我的问题不是那个,而是 litb 指出的缓冲区正在收集的垃圾。用空字符终止字符串比清除数组更有意义。这就是我将 litb 的答案标记为正确答案的原因。

【问题讨论】:

    标签: c arrays pointers


    【解决方案1】:
    int i;
    for (i = 0; i < 10; i++)
       pArgs[i] = NULL;
    

    【讨论】:

    • 我用 memset() 回答,然后删除了我的答案,因为很难解释为什么 sizeof(pArgs) 在这种情况下可以,但在其他情况下可能不行(例如,当类型pArgs 是 char**)。 +1 为“for”循环,-1 为 memset 在这种情况下。
    • 你应该把它留下来。 Memset 仍然是正确的,并且在速度成为问题时是更好的选择。 (请参阅:cppreference.com/wiki/c/string/memset)一个体面的编译器可能会将这个 for 循环优化为 memset 无论如何
    • 我同意,最好删除 memset。这并不总是正确的。循环始终有效。如果您知道空指针由空字节组成,您可以这样做,但绝不会注意到该外壳的速度差异!
    • 无法保证 memset() 会将指针的表示设置为 NULL。 “ptr = 空;”与“memset(&ptr, 0, sizeof(ptr)”不同。
    • 我刚刚重新阅读了 C 常见问题解答,Dingo 似乎是对的。尽管 NULL 必须等于 ((void *)0),但“零指针”的位模式可能与“零整数”的位模式不同。我将删除 memset,因为它在某些架构上无效。
    【解决方案2】:

    您的问题是您没有在读取数据后添加空字符。所以strsep 电话不知道在哪里停止。在 C 中,字符串必须以空字符(称为终止空字符)终止。

    // don't forget to add error handling at some point (s == -1)
    ssize_t s = read(0, bBuffer, BUFSIZ-1);
    bBuffer[s] = '\0';
    

    有了这个,我看不出现在应该清除哪个数组,因为execvp 将读取参数直到第一个空指针。但是,do 循环已经添加了该空指针,它是最后一次调用 strsep 返回的空指针。

    这个问题当然也可以通过清除 bBuffer(扫描第一个命令后*pArgs 指向的数据)来解决。请注意,在第一次扫描之前您也必须这样做,因为您不能假设 bBuffer 数组中的字符被初始化为任何合理的值。

    memset(bBuffer, 0, sizeof bBuffer);
    

    将它放在read 调用之前(但无论如何,最多只能读取BUFSIZE-1,因为终止的空字符也必须有空格!)。

    但正如我在上面所展示的,您不需要这个 memset 调用。只需手动添加终止空字符。

    【讨论】:

    • 我不明白为什么我的回答被否决了。显然,他的问题不是由于不清除指针数组而产生的,而是问题出在其他地方。因此,简单地展示清除该数组的正确方法是好的,但当然展示如何纠正错误至少同样重要!
    • 我认为他的“无限循环”是故意的,你误读了这个问题。但我赞成这一点,因为这是提交者应该注意的重要信息。
    • 我当然不打算打破无限循环。请参阅阅读内容,假设 BUFSIZ 为 255。然后您输入“echo hello”。然后缓冲区包含[echo helloblahblusomerandomdata.......]。 strsep 应该如何正常运行?只是清除指针数组是行不通的。他真正想要的是清除 bBuffer 数组。但这不是必要的,正如我在答案中所说的那样
    • 不过,我建议他可以去掉='\0'; do-while 循环之后的行当然是错误的。他这样做是为了摆脱 '\n' 字符。恐怕我完全忽略了那条线的目的。
    • 如果我使用 bBuffer[s-1] = '\0' 而不是 bBuffer[s] = '\0' 作为你建议。而且由于无论如何我都必须清除它,所以最好执行 s-1,而不是使用 strlen() 来清除那个大而令人困惑的行来清除 '\n' 字符。 :)
    猜你喜欢
    • 1970-01-01
    • 2020-07-10
    • 1970-01-01
    • 2022-06-11
    • 1970-01-01
    • 1970-01-01
    • 2018-09-12
    • 2017-11-17
    • 1970-01-01
    相关资源
    最近更新 更多