繁体   English   中英

通过引用传递指针数组

[英]Passing an array of pointers by reference

我试图以与命令行 args int main( int argc, char *argv[] )类似的方式从键盘获取命令,但在一个单独的函数中。 当我在getCmd()函数的范围内解析和打印它们时,所有的外观和行为都符合预期,但是一旦它们返回主函数,它们就会变成一堆垃圾。 我的问题在代码下方。

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

void getCmd(char *cmd, char *args[])
{
    char input[81] = { 0 };
    char *next_token = NULL;
    printf("$ ");
    fgets(input, 81, stdin);
    input[strcspn(input, "\n")] = 0;
    cmd = strtok_s(input, " ", &next_token);
    if (!strcmp(cmd, "mv"))
    {
        args[0] = strtok_s(NULL, " ", &next_token);
        args[1] = strtok_s(NULL, " ", &next_token);
        printf("\n\n%s\n%s\n%s\n\n", cmd, args[0], args[1]);
    }
}

int main(void)
{
    char *cmd = NULL, *args[5];

    cmd = (char *)calloc(20,sizeof(char));
    for (size_t i = 0; i < (size_t)5; i++)
    {
        args[i] = (char *)calloc(20,sizeof(char));
    }
    getCmd(cmd, args);
    printf("\n\n%s \n%s\n%s", cmd, args[0], args[1]);
    return 0;
}

我不认为它相关,但我在 64 位处理器 Windows 7 操作系统上使用 VS 2015 社区和 Visual C++ 编译器。

我的问题:

  • 我应该如何通过引用传递 cmd 和 args[] ?
  • 是否有任何被广泛接受的成语来处理这种情况?

我已经查看了一些类似的问题,但找不到在这种情况下有效的解决方案,如果问题是重复的,请告诉我,我将关闭它。因为我是 stackoverflow 任何问题格式的新手提示将不胜感激。 干杯! (:

有许多不同的方法可以解决这个问题。 虽然您可以自由地为cmdargs数组动态分配内存,但实际上没有必要,对于这个有限的内存量,您可以对所有内存使用静态声明。 不需要单独的input数组,您需要为此使用cmd ,然后标记cmd 这提供了在调用strtok后在cmd中保留第一个以null 结尾的标记的好处。

注意:在下面的示例中,使用了strtokstrtok_s是 C11 中的一个可选编译器添加项,不幸的是,我没有实现该选项的编译器,因此我使用strtok测试。 您可以轻松地对 VS 进行更改。

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

enum { NARGS = 5, MAXC = 128 };

size_t getcmd (char *cmd, char (*args)[MAXC]);

int main (void) {

    char cmd[MAXC] = "", args[NARGS][MAXC] = { "" };
    size_t i, n;

    if (!(n = getcmd (cmd, args))) return 1;

    printf ("  %s", cmd);
    for (i = 0; i < n; i++)
        printf(" %s", args[i]);
    putchar ('\n');

    return 0;
}

size_t getcmd (char *cmd, char (*args)[MAXC])
{
    char *delim = " ,.\t\n";
    char *p = NULL;
    size_t idx = 0;

    printf ("$ ");
    if (!fgets (cmd, MAXC, stdin)) {
        fprintf (stderr, "error: invalid input.\n");
        return 0;
    }

    strtok (cmd, delim);            /* terminate after 1st token */

    for (p = strtok (NULL, delim); p; p = strtok (NULL, delim)) {
        strncpy (args[idx++], p, MAXC);  /* limit to avail chars */
        if (idx == NARGS) break;    /* limit to available bounds */
    }

    return idx;
}

注意上面, getcmd的返回类型是size_t 总是选择一个有意义的类型来返回成功/失败的指示以及返回一些需要的信息(这里的参数数量)。 另请注意,C 风格指南不赞成驼峰式变量/函数名称,而更喜欢全部小写。 为 C++ 保留驼峰命名。 参见例如NASA - C 风格指南,1994

示例使用/输出

$ ./bin/getcmd
$ mv /this/here/file /that/there/file
  mv /this/here/file /that/there/file

$ ./bin/getcmd
$ mv -i --strip-trailing-slashes /this/here/file /that/there/file
  mv -i --strip-trailing-slashes /this/here/file /that/there/file

看看它,如果您有任何其他问题,请告诉我。

strtok_s()返回指向它正在解析的缓冲区的指针(此处input )。

input存在于getCmd()堆栈中。 它在getCmd()返回的那一刻就死了。 从那时起,指向input并存储在args元素中的地址不再指向有效内存。

代码需要分配新内存并复制strtok_s()返回的指针。

看看现在可以这样做:

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

void getCmd(char **pcmd, char *args[], size_t s)
{
    char input[81] = { 0 };
    char *next_token = NULL;
    printf("$ ");
    fgets(input, 81, stdin);
    input[strcspn(input, "\n")] = 0;
    (*pcmd) = _strdup(strtok_s(input, " ", &next_token));
    if (!strcmp(*pcmd, "mv"))
    {
        args[0] = _strdup(strtok_s(NULL, " ", &next_token));
        args[1] = _strdup(strtok_s(NULL, " ", &next_token));
        printf("\n\n%s\n%s\n%s\n\n", *pcmd, args[0], args[1]);
    }
}


#define ARGS_MAX (5)

int main(void)
{
    char *cmd, *args[ARGS_MAX] = {0};

    getCmd(&cmd, args, ARGS_MAX);
    printf("\n\n%s \n%s\n%s", cmd, args[0], args[1]);

    /* Clean up. */
    free(cmd);
    for (size_t i = 0; i < ARGS_MAX; ++i)
    {
      free(args[i]);
    }

    return 0;
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM