2014-10-10 143 views
1

我不明白为什么第二个printf循环输出的数据不同于在函数作用域内完成的第一个printf循环。难道是指针在函数内部以某种方式改变,所以当它返回时它会返回一个不同的值?使用函数内部的calloc,更改指针作为函数参数传递

输出:

第一个printf内部功能:
零件TMP | 01245
零件X | 40001
零件Y | 98760

第二个printf以外的功能,在主:
它返回jiberish并且与在函数内打印时不一样。 我试着fprintf,这样我就可以在这里快速粘贴结果,但后来我收到了一个无法解释的调用堆栈错误。

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

void ProtocolParse_Start(int *numParts,char **parts, char *str, const char* partsDelim) 
{ 
    int partCount = strChrCount(str,'~'); 
    *numParts = partCount; 

    parts = (char**)calloc(partCount,sizeof(char)); 
    char *tempPart; 


    tempPart = strtok (str,partsDelim); 
    parts[0] = (char*)calloc(strlen(tempPart),sizeof(char)); 
    strcpy(parts[0],tempPart); 


    int i =1; 
    for(; i < partCount; i++) 
    { 
     tempPart = strtok (NULL, partsDelim); 
     parts[i] = (char*)calloc(strlen(tempPart),sizeof(char)); 
     strcpy(parts[i],tempPart); 
    } 

    i =0; 
    for(; i < partCount; i++) 
    { 
     printf ("%Parts %s\n",parts[i]); 
    } 

} 

void ProtocolParse_End(int numParts,char **parts) 
{ 
    int i = 0; 
    for (; i < numParts; i++) 
     free (parts[i]); 

    free (parts); 
} 


int main() 
{ 
    char proto[32] = "TMP|01245~X|40001~Y|98760~"; 

    char **parts; 
    int numParts; 
    ProtocolParse_Start(&numParts, parts,proto,"~"); 


    int i =0; 
    for(; i < numParts; i++) 
    { 
      printf ("%Parts %s\n",parts[i]); 
    } 

    ProtocolParse_End(numParts,parts); 

    return 0; 
} 

任何人都可以请说明我的问题。因为我不确定我在做什么错误?

+0

删除了C++标记,以避免每个人都告诉你使用'std :: string',因为这显然是C代码。 – Borgleader 2014-10-10 18:44:49

+0

抱歉,只需快速点击自动建议的标签。 – 2014-10-10 18:49:09

回答

2

该函数内parts的赋值对的char **parts没有影响。为了修改它,你需要传递一个指向parts的指针,并添加一个额外的间接级别(是的,你会得到三个星号)。

将数据分割为字符串的代码也不正确:您需要分配一组字符指针,然后将每个令牌分别复制到该数组中。

void ProtocolParse_Start(int *numParts, char ***parts, char *str, const char* partsDelim) 
{ 
    int partCount = strChrCount(str,'~'); 
    *numParts = partCount; 

    *parts = malloc(partCount * sizeof(char*)); 

    char *tempPart; 
    tempPart = strtok (str,partsDelim); 
    (*parts)[0] = malloc(strlen(tempPart)+1); 
    strcpy((*parts)[0], tempPart); 

    int i =1; 
    for(; i < partCount; i++) 
    { 
     tempPart = strtok (NULL, partsDelim); 
     (*parts)[i] = malloc(strlen(tempPart)+1); 
     strcpy((*parts)[i],tempPart); 
    } 

    i =0; 
    for(; i < partCount; i++) { 
     printf ("%Parts %s\n", (*parts)[i]); 
    } 

} 

我进行了三次修改了代码:

  • 替换callocmalloc:初始化每个元素无论如何,所以没有理由去填零块
  • 在前面去掉石膏malloc - 这不是必需的C
  • 增加一个到strlen(tempPart) - 你需要这个空字符串。
+0

谢谢,我还是个蚱蜢:)。我使用malloc而不是calloc的理解。我只是这样写的,所以当我将代码移动到Mbed C++项目时,我不必稍后再进行更改。我读到strtok返回该标记并自动终止它,但在定位大小时忘记添加+1。感谢您的帮助。 – 2014-10-10 19:16:11

+0

我试过你的代码,但是当试图做第三个malloc时:(* parts)[i] = malloc(strlen(tempPart)+1);我是1,失败了。有什么想法吗 ? – 2014-10-10 19:47:26

+0

@DR。你在'ProtocolParse_Start(&numParts,&parts,proto,“〜”);'call中传递一个地址,对吧? – dasblinkenlight 2014-10-10 20:08:06

0

有不同的错误:

当您将参数传递给函数它总是被复制。 你给了char **parts,它被复制。

函数内部用覆盖指针calloc ed的新地址覆盖复制的输入。

考虑一个简单的例子:

void doSomething(int a){ 
    a=5; 
} 
///... 
int b = 6; 
doSomething(b); 

当你调用doSomething(b),你的B没有改变。 如果您想要更改它,您必须将指针传递给b

void doSomething(int* a){ 
    *a=5; 
} 
///... 
int b = 6; 
doSomething(&b); 

这与你的char*阵列一样。

你在你的主中有char** parts,你想要设置为分配数组。 所以你必须通过它的指针。并将获得的地址写入解除引用的指针。

另一个大错误是,你歪歪斜撞到第一个calloc。它应该是sizeof(char*)

你的例程应该像这样开头:

void ProtocolParse_Start(int *numParts,char ***parts, char *str, const char* partsDelim) 
{ 
    int partCount = strChrCount(str,'~'); 
    *numParts = partCount; 

    *parts = (char**)calloc(partCount,sizeof(char*)); 
    char *tempPart; 
    //... 

(所有进一步访问的功能部件已提领部分)

和呼叫必须看起来像:

ProtocolParse_Start(&numParts, &parts,proto,"~"); 
+0

我的印象是,当传递一个字符指针时,它通过引用传递。但它似乎是通过阅读你的答案的价值传递? – 2014-10-10 19:19:43

+0

我不明白为什么我应该像sizeof(char *)而不是sizeof(char)那样使用sizeof(char *)。因为sizeof(char *)不一定等于8位或1个字节,这取决于它是在32位还是64位计算机上运行。所以我认为使用sizeof(char)是正确的,因为它肯定意味着1个字节? – 2014-10-10 19:24:13