2

这是第一次发帖,如有任何困惑,我深表歉意:

我正在编写这样的函数:

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,因为:

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

  3. 最后一件事:在myfunc退出之前,我检查了 and 的值,argCTemp它们argVTemp有有效的内容。我正在设置argCtempargVtemp就像这样:

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

在函数退出之前,它似乎工作得很好。由于我在内存中的其他位置设置指针,我很困惑为什么引用失败。我在设置指针时尝试使用mallocINSIDE myFunc,但它在结束时仍然变成垃圾myFunc并被调用函数读取。

如果有任何令人困惑的地方,我很抱歉,并提前感谢您的帮助。

4

3 回答 3

1

由于“不知道我的输入的参数数量或每个参数的长度”,您也可以使用malloc。当你的缓冲区快满时,你应该realloc缓冲。更好的方法:您不需要存储整个输入。一条线,一个令牌或一个块更好。只需设置一个静态数组来存储它们。如果您的输入超过 100 mb,则哈希可能会更好。

我为我糟糕的英语感到抱歉。

于 2012-03-19T05:52:17.910 回答
0

一般来说,由于您不知道结果中有多少标记,因此您需要使用 和/或等效方法动态分配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(),但这使您可以灵活地执行更复杂的事情(例如为令牌分配内存,这样您就不必破坏输入字符串)。
于 2012-03-19T15:19:20.073 回答
0

你向函数发送一个未初始化的指针(你调用 is 也不正确,你不需要 & ),这个指针指向一些随机的地方,这就是你得到垃圾的原因,你也可能得到分段错误。

你可以做两者之一。

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

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

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


假设你当时的令牌int n数量

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

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

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

例如(*argVTemp)[0] = ;

(当不再需要数组时,不要忘记通过调用 free(arr) 来释放它)

于 2012-03-19T05:29:28.477 回答