简体   繁体   English

通过引用传递指针数组

[英]Passing an array of pointers by reference

I'm trying to get commands from the keyboard in a similiar fashion as command line args int main( int argc, char *argv[] ) but in a separate function.我试图以与命令行 args int main( int argc, char *argv[] )类似的方式从键盘获取命令,但在一个单独的函数中。 When I parse and print them within the scope of the getCmd() function all looks and behaves as intended, but as soon as they return to the main function they become a bunch of garbage.当我在getCmd()函数的范围内解析和打印它们时,所有的外观和行为都符合预期,但是一旦它们返回主函数,它们就会变成一堆垃圾。 My questions are below the code.我的问题在代码下方。

#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;
}

I don't think its relevant but I'm using VS 2015 Community with the Visual C++ compiler on a 64 bit processor, Windows 7 OS.我不认为它相关,但我在 64 位处理器 Windows 7 操作系统上使用 VS 2015 社区和 Visual C++ 编译器。

My questions:我的问题:

  • How should I pass the cmd and args[] by reference?我应该如何通过引用传递 cmd 和 args[] ?
  • Are there any widely accepted idioms that deal with this sort of situations?是否有任何被广泛接受的成语来处理这种情况?

I've looked trough a few of the similiar questions and couldn't find a solution that works in this context, if the question is a duplicate, tell me and I'll close it.Since I'm new to stackoverflow any question formatting tips would be greatly appreciated.我已经查看了一些类似的问题,但找不到在这种情况下有效的解决方案,如果问题是重复的,请告诉我,我将关闭它。因为我是 stackoverflow 任何问题格式的新手提示将不胜感激。 Cheers!干杯! (: (:

There are a number of different ways to approach the problem.有许多不同的方法可以解决这个问题。 While you are free to dynamically allocate memory for cmd and your args array, there is really no need, for this limited amount of memory you can use a static declaration for all.虽然您可以自由地为cmdargs数组动态分配内存,但实际上没有必要,对于这个有限的内存量,您可以对所有内存使用静态声明。 There is no need for a separate input array, you cause use cmd for that purpose and then tokenize cmd .不需要单独的input数组,您需要为此使用cmd ,然后标记cmd This provides the benefit of leaving the first token nul-terminated in cmd after strtok is called.这提供了在调用strtok后在cmd中保留第一个以null 结尾的标记的好处。

note: in the example below, strtok is used, strtok_s was an optional compiler addition in C11, and unfortunately, I don't have a compiler that implements that option, so I test with strtok .注意:在下面的示例中,使用了strtokstrtok_s是 C11 中的一个可选编译器添加项,不幸的是,我没有实现该选项的编译器,因此我使用strtok测试。 You can easily make the change for VS.您可以轻松地对 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;
}

Note above, the return type of getcmd is size_t .注意上面, getcmd的返回类型是size_t Always choose a meaningful type to return an indication of success/failure as well as returning some needed information (the number of arguments here).总是选择一个有意义的类型来返回成功/失败的指示以及返回一些需要的信息(这里的参数数量)。 Also note the C-Style Guide disfavors camelCase variable/function names preferring all lower-case instead.另请注意,C 风格指南不赞成驼峰式变量/函数名称,而更喜欢全部小写。 Leave camelCase names for C++.为 C++ 保留驼峰命名。 See eg NASA - C Style Guide, 1994参见例如NASA - C 风格指南,1994

Example Use/Output示例使用/输出

$ ./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

Look it over and let me know if you have any additional questions.看看它,如果您有任何其他问题,请告诉我。

strtok_s() return pointer into the buffer it's parsing ( input here). strtok_s()返回指向它正在解析的缓冲区的指针(此处input )。

input lives on getCmd() stack. input存在于getCmd()堆栈中。 It dies the moment getCmd() returns.它在getCmd()返回的那一刻就死了。 From then on the addresses pointing into input and that had been stored in args 's elements does not point to valid memory any more.从那时起,指向input并存储在args元素中的地址不再指向有效内存。

The code needs allocate fresh memory and copy what strtok_s() returned a pointer to.代码需要分配新内存并复制strtok_s()返回的指针。

Have a look on ow this can be done:看看现在可以这样做:

#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