v2000
asked on
Dynamic strings / malloc
Greetings
I have a function that needs to return a pointer to an array of characters that contains five tab-delimited strings, for example:
"string1\tstring2\tstring3 \tstring4\ tstring5"
Each of the five strings' size is dynamically allocated inside a while loop before being assigned. Here is a simple version of what I have. Let's assume RecoLabelToString properly malloc()s and returns an array of characters:
TCHAR * string;
TCHAR * retString;
while (iterator) {
string = RecoLabelToString();
}
return string;
This does work, and returns the last iteration's version of string, which is "string5" in my example above. However, I need to dynamically size retString each iteration of the loop, add a tab, and concatenate string to it. I'm having a lot of trouble. I've tried a bunch of things like:
TCHAR * string[5]
TCHAR * retString;
int iterResults = 0;
int totalLength = 0;
int numResults;
while (iterator) {
string[iterResults] = RecoLabelToString();
totalLength = totalLength + sizeof(string[iterResults] );
iterResults++;
}
numResults = iterResults;
retString = malloc(totalLength);
for (iterResults = 0; iterResults < numResults; iterResults++) {
if (iterResults == 0) {
retString = strcat(retString, "\t");
}
retString = strcat(retString, string[iterResults]);
}
return retString;
I've tried many versions of the above, always to some form of crash or heap error. I have never worked with C-style strings before and I really don't know where to begin troubleshooting. Any help would be very appreciated.
Thanks
I have a function that needs to return a pointer to an array of characters that contains five tab-delimited strings, for example:
"string1\tstring2\tstring3
Each of the five strings' size is dynamically allocated inside a while loop before being assigned. Here is a simple version of what I have. Let's assume RecoLabelToString properly malloc()s and returns an array of characters:
TCHAR * string;
TCHAR * retString;
while (iterator) {
string = RecoLabelToString();
}
return string;
This does work, and returns the last iteration's version of string, which is "string5" in my example above. However, I need to dynamically size retString each iteration of the loop, add a tab, and concatenate string to it. I'm having a lot of trouble. I've tried a bunch of things like:
TCHAR * string[5]
TCHAR * retString;
int iterResults = 0;
int totalLength = 0;
int numResults;
while (iterator) {
string[iterResults] = RecoLabelToString();
totalLength = totalLength + sizeof(string[iterResults]
iterResults++;
}
numResults = iterResults;
retString = malloc(totalLength);
for (iterResults = 0; iterResults < numResults; iterResults++) {
if (iterResults == 0) {
retString = strcat(retString, "\t");
}
retString = strcat(retString, string[iterResults]);
}
return retString;
I've tried many versions of the above, always to some form of crash or heap error. I have never worked with C-style strings before and I really don't know where to begin troubleshooting. Any help would be very appreciated.
Thanks
ASKER CERTIFIED SOLUTION
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Hi v2000,
If you take the branch to the clear: label, iterResults will be set to its default value of 1. The concatenation loop will only insert string[0]. This sounds like what you are seeing.
Also, string[] is defined as an array of 4 pointers. Does it need to be 5?
Kent
If you take the branch to the clear: label, iterResults will be set to its default value of 1. The concatenation loop will only insert string[0]. This sounds like what you are seeing.
Also, string[] is defined as an array of 4 pointers. Does it need to be 5?
Kent
ASKER
Thanks _nn_ -- While your exact edits didn't do the trick, the use of the unicode character functions was the key, I believe. I had some more pointer issues that I didn't catch at first, and I believe I also had a problem finding the length of any of the string[]s. I implemented another function and it did the trick, in combination with the T functions.
I haven't written in C in four years... and it shows. Thanks again.
I haven't written in C in four years... and it shows. Thanks again.
ASKER
Thanks for the response. Unfortunately I'm still having some trouble -- the malloc() seems to be destroying whatever data is in the string[] array, even if I don't return retString. Here's my source of the entire function:
TCHAR * Recognizer_RecognizeInk(Re
{
/* Local data */
InkStroke * pStroke;
Long retval;
HIterator it;
HIterator segIt;
HIterator wholeIt;
Long length;
int totalLength = 0;
TCHAR * string[4];
int numResults = 5;
int iterResults = 1;
int iterStrings = 0;
UShort * label = Null;
TCHAR * retString = Null;
TCHAR * tempString;
/* Add ink to the handwriting context */
pStroke = pInk->pFirstStroke;
while (pStroke)
{
voAddStroke(This->hApi, This->hhc, COORD__LONG, &pStroke->points[0].x, sizeof(InkPoint), &pStroke->points[0].y, sizeof(InkPoint), (UShort)pStroke->n_points)
pStroke = pStroke->pNextStroke;
}
/* Recognize */
voRecognize(This->hApi, This->hhc, voNull, 0);
if (voGetResultEx(This->hApi,
goto clear;
}
/* Let's try segments */
if (voGetResultEx(This->hApi,
goto clear;
}
while (segIt)
{
iterResults = 1;
voGetResultEx(This->hApi, This->hhc, segIt, VO_RC_EX__FIRST_CANDIDATE,
while (it)
{
length = 0;
retval = voGetResultEx(This->hApi, This->hhc, it, RC_EX__LABEL, Null);
label = TRealloc(UShort, label, length + (retval / sizeof(UShort)));
retval = voGetResultEx(This->hApi, This->hhc, it, RC_EX__LABEL, &label[length]);
length += retval / sizeof(UShort);
string[iterResults - 1] = RecoLabelToString(This->hA
if (++iterResults == numResults)
{
voGetResultEx(This->hApi, This->hhc, segIt, VO_RC_EX__STOP_ITERATION, &it);
}
else
{
voGetResultEx(This->hApi, This->hhc, segIt, VO_RC_EX__NEXT_CANDIDATE(V
}
}
voGetResultEx(This->hApi, This->hhc, wholeIt, VO_RC_EX__NEXT_SEGMENT, &segIt);
}
clear:
/* Clear ink from the handwriting context */
voClearInk(This->hApi, This->hhc, False, True);
for (iterStrings = 0; iterStrings < iterResults; iterStrings++) {
totalLength = totalLength + _tcslen(string[iterStrings
}
totalLength += 5 * sizeof(TCHAR);
retString = (TCHAR *)malloc(totalLength);
retString[0] = 0;
_tcscat(retString, string[0]);
TFree(TCHAR, string[0]);
for (iterStrings = 0; iterStrings < iterResults; iterStrings++) {
_tcscat(retString, _T("\t"));
_tcscat(retString, string[iterStrings]);
TFree(TCHAR, string[iterStrings]);
}
return retString;
}
As you asked, I'll also include the RecoLabelToString function:
TCHAR * RecoLabelToString(HApi hApi, HRes hresAK, UShort * label, Long length)
{
Long i;
Word wClassId;
TCHAR buffer[1024];
Long str_len;
TCHAR * string;
str_len = 0;
for (i = 0; i < length; i++)
{
wClassId = AlphabetIndexToClassId(hAp
ClassIdToString(wClassId, buffer);
str_len += _tcslen(buffer);
}
string = TAlloc(TCHAR, str_len+2);
if (string)
{
str_len = 0;
for (i = 0; i < length; i++)
{
wClassId = AlphabetIndexToClassId(hAp
ClassIdToString(wClassId, &string[str_len]);
str_len += _tcslen(&string[str_len]);
}
string[str_len] = _T('\0');
}
return string;
}
We needn't concern ourselves with any other function called in these functions -- rest assured, the code works if I comment out the mallocing business and the concatenate business and just return string[0]. But of course I only get one string then, instead of the tab-delimited bunch that the application using this DLL will expect.
Any help is appreciated.