繁体   English   中英

从函数C返回填充的字符串数组

[英]Returning populated string array from function C

这是第一次发布,因此给您带来的任何困惑我深表歉意:

我在写这样的函数:

int myFunc(char* inputStr, int *argCTemp, char** argVTemp[]);

我函数的目的是获取输入字符串的副本(基本上是任何用户输入),然后使用strtok将其转换为令牌,并通过数组指针( argV )填充数组。 myFunc完成时,希望我可以从我的inputStr字符串中获取参数计数和字符串数组。

这是我如何称呼它的一个例子:

int main(int argc, char** argv[])
{
    int argCTemp = -1;
    char** argVTemp; 

    // 1 Do Stuff
    // 2 Get input string from user 
    // 3 then call myfunc like this:

    myFunc(inputStr, &argCTemp, &argVTemp);

    // 4: I get garbage whenever I try to use "argVTemp[i]" 
}

我的问题:如何最好地以安全且一致的方式执行此操作。 专业人士如何做到这一点?


  1. 我不使用malloc是因为:

    • 我不知道输入的参数数量或每个参数的长度(动态分配空间)。 我知道这就是为什么我使用指针
    • 因为我在main函数中声明了它,所以我认为argCTempargVTemp所使用的指向/内存的指针在范围内就可以了,即使它们在堆栈中也可以。
  2. 我知道myFunc退出时会使它创建的任何堆栈引用无效,所以这就是为什么我从调用函数向其发送了指针。 我应该使用指针和malloc等等吗?

  3. 最后一件事:在myfunc退出之前,我检查以查看argCTempargVTemp的值以及它们是否具有有效的内容。 我正在这样设置argCtempargVtemp

     (*argCTemp) = argCount; (*argVTemp)[0] = "foo"; 

在功能退出之前,它似乎工作正常。 由于我将指针设置在内存中的其他位置,因此我很困惑为什么引用失败。 我尝试在设置指针时使用malloc INSIDE myFunc ,但是当myFunc结束并由调用函数读取时,它仍然变得很垃圾。

如果有任何令人困惑的情况,我们深表歉意,并在此先感谢您的帮助。

由于“不知道输入的参数数量或每个参数的长度”,因此还可以使用malloc 当你的缓冲abouting满,你应该realloc你的缓冲区。 更好的方法:您不必存储整个输入。 行,令牌或块更好。 只需设置一个静态数组即可存储它们。 如果您输入的内容超过100 mb,则哈希值可能会更好。

对不起,我的英语不好。

您向该函数发送一个未初始化的指针(调用也不正确,不需要&),该指针指向某个随机位置,这就是为什么会出现垃圾的原因,也可能导致分段错误。

您可以做两个之一。

每个分配足够大的数组,例如可以是静态的

static char * arr[MAX SIZE]并在函数调用中将其发送(char **)&arr ,或者运行两次并使用malloc。

您还应该传递最大大小,或使用常量并确保不传递它。


假设您在int n的令牌数量

char * arr [] = malloc(sizeof(int *)* n);

这将创建一个指针数组,现在您通过调用将其传递给填充函数

(char **)&arr使用,并像在代码中一样使用它

例如(*argVTemp)[0] = ;

(当不再需要该数组时,请不要忘记通过校准free(arr)来释放它)

一般而言,由于您不知道结果中将包含多少个令牌,因此需要使用malloc()realloc()和/或等效项来动态分配数组。 另外,您可以让调用方将数组以及数组的大小传递给数组,并在数组不够大的情况下返回错误指示(我对动态分配不合适的嵌入式系统上的简单命令解析器执行此操作)。

这是一个以较小的增量分配返回数组的示例:

static
char** myFunc_realloc( char** arr, size_t* elements)
{
    enum {
        allocation_chunk = 16
    };

    *elements += allocation_chunk;
    char** tmp = (char**) realloc( arr, (*elements) * sizeof(char*));

    if (!tmp) {
        abort();  // or whatever error handling
    }

    return tmp;
}

void myFunc_free( char** argv)
{
    free(argv);
}

int myFunc(char* inputStr, int *argCTemp, char** argVTemp[])
{
    size_t argv_elements = 0;
    size_t argv_used = 0;
    char** argv_arr = NULL;


    char* token = strtok( inputStr, " ");

    while (token) {
        if ((argv_used+1) >= argv_elements) {
            // we need to realloc - the +1 is because we want an extra 
            //  element for the NULL sentinel
            argv_arr = myFunc_realloc( argv_arr, &argv_elements);
        }

        argv_arr[argv_used] = token;
        ++argv_used;

        token = strtok( NULL, " ");
    }

    if ((argv_used+1) >= argv_elements) {
        argv_arr = myFunc_realloc( argv_arr, &argv_elements);
    }
    argv_arr[argv_used] = NULL;

    *argCTemp = argv_used;
    *argVTemp = argv_arr;

    return argv_used;
}

一些注意事项:

  • 如果分配失败,程序将终止。 您可能需要不同的错误处理。
  • 传入的输入字符串“已损坏”。 这可能不是适合您的函数的接口(通常,我希望这样的函数不会破坏输入数据)。
  • 该函数的用户应调用myFunc_free()来取消分配返回的数组。 当前,这是free()的简单包装器,但是这使您可以灵活地执行更复杂的事情(例如为令牌分配内存,因此您不必破坏输入字符串)。

暂无
暂无

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

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