Reputation: 593
I do not understand why the second printf loop outputs different data than the first printf loop that was done inside the function scope. Can it be that the pointer is changed somehow inside the function so that when it returns it returns a different value?
Output:
First printf inside function:
Parts TMP|01245
Parts X|40001
Parts Y|98760
Second printf outside function, in main:
It returns jiberish and not the same as when printing inside the function.
I tried to fprintf so that I can quickly paste the results in here ,but then I received an uninformative call stack error.
#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;
}
Can anyone please shed some light onto my problem. Because I am not sure what I'm doing wrong ??
Upvotes: 1
Views: 1598
Reputation: 6883
There are different mistakes:
When you pass a parameter to a function it is always copied.
You gave a char **parts
and it is copied.
Inside the function you overwrite the copied input with the new address of the calloc
ed pointer.
Consider an easier example:
void doSomething(int a){
a=5;
}
///...
int b = 6;
doSomething(b);
When you call doSomething(b)
, your b is not changed.
If you want it to be changed, you have to pass a pointer to b
.
void doSomething(int* a){
*a=5;
}
///...
int b = 6;
doSomething(&b);
The same is with your char*
array.
You have char** parts
in your main, that you want to be set to the allocated array.
so you have to pass its pointer. and write the obtained address to the dereferenced pointer.
The other big mistake is, that you gibe the wrong soze to the first calloc
. It should be sizeof(char*)
.
Your routine should start like this:
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;
//...
(all further accesses to parts in the function have to dereference parts)
and the call have to look like:
ProtocolParse_Start(&numParts, &parts,proto,"~");
Upvotes: 0
Reputation: 726809
The assignment of parts
inside the function has no effect on the char **parts
from main
. In order to modify it, you need to pass a pointer to parts
, and add an extra level of indirection (yes, you'd get three asterisks now).
The code that partitions the data to strings is incorrect, too: you need to allocate an array of character pointers, and then copy each token into that array individually.
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]);
}
}
I made three changes to your code:
calloc
with malloc
: you initialize every element anyway, so there is no reason to zero-fill the blockmalloc
- this is not necessary in Cstrlen(tempPart)
- you need this for null terminated strings.Upvotes: 2