Microsoft Developer Network >
Forums Home
>
Visual Studio Express Editions Forums
>
Visual C++ Express Edition
>
a function that receives a string and returns an array of strings after some parsing
a function that receives a string and returns an array of strings after some parsing
- Dear All,
I wrote a simple function that receives a string and returns an array of strings after some parsing.
The header of my function:
int parseXML(char* inputXML, int requestType, char **poutputResponse)
the function parseXML receive the string inputXML and the requestType, it does some parsing and fill each strings in a different position of poutputResponse.
how can i call this function?
in my code, I called the function as below, but it returned null as values for poutputResponse:
char* testtest[10];
ret = parseXML(pXMLresponse, reqType, testtest);
printf("%s\n", testtest[0]);
Please I need your help,
Thank you,
Solange.
Answers
- Solange Saad:
Describe what you're trying to do during the parsing. Maybe strstr() or
sscanf() would be a better match. Show an example of text to be parsed
and what you want to extract/display from that text.
As I commented in my first post, parsing XML strings is not a "simple" task
(unless you're looking for a single value or substring). I concur with Llelan D.
that using an existing XML parsing library may be the easiest approach.
The XML C parser and toolkit of Gnome
http://xmlsoft.org/xml.html
Recursive XML Parser in C
http://www.codeguru.com/cpp/data/data-misc/xml/article.php/c4549/
Parsing XML with Xerces-C C++ API
http://www.yolinux.com/TUTORIALS/XML-Xerces-C.html
- Wayne- Marked As Answer byNancy ShaoMSFT, ModeratorThursday, November 05, 2009 2:56 AM
All Replies
- Hello Solange,
One possibility is to declare a double dim array as follows,
// Declare a double dim array. const int MAX_STRINGS = 10; const int MAX_STRING_LEN = 100; char testtest[MAX_STRINGS][MAX_STRING_LEN]; ret = parseXML(pXMLresponse, reqType, testtest); printf("%s\n", testtest[0]);
If possible, avoid raw char** and use std::string array. That will make your life easier.
Best Regards,
Jijo.
http://weseetips.com[^] Visual C++ tips and tricks. Updated daily. - Thank you Jijo for your response,
I did as you recommended, but i got the below warning:
warning C4047: 'function' : 'char ** ' differs in levels of indirection from 'char [10][100]'
warning C4024: 'parseXML' : different types for formal and actual parameter 3
And i can't use std::string array, because i'm using C language and not C++. - I'm a little puzzled by your problem. You say *you* wrote the function
but you can't figure out how to call it. Seems implausible. You say it's
a "simple" function, which apparently parses an XML string - not a
"simple" task. You say you're using C but give no explanation why you
can't use C++. If you can't figure out how to use one of your own
functions, why don't you rework it into something that you *can* use?
Try this:
#include <stdlib.h>
int parseXML(char* inputXML, int requestType, char **poutputResponse);
#define maxsubstrings 300
int main(int argc, char* argv[])
{
char pXMLresponse[] = "</xml>";
int x, ret, reqType=1;
char *testtest[maxsubstrings];
const unsigned maxstringsize = 500;
for(x = 0; x<maxsubstrings; ++x)
{
testtest[x] = (char*)calloc(maxstringsize, sizeof(char));
}
ret = parseXML(pXMLresponse, reqType, testtest);
return 0;
}
- Wayne - <sheesh> Yeah, it's a simple task and lots of contracts require the use of C instead of C++.
The problem with your question is that it is not possible to tell you why your parseXML function returns a null in your char * *testtest argument without knowing the implementation of that function.
You are providing an array of character pointers with no array count so the function must assume what that count is. Apparently your function will only return up to 10 strings.
Your function would have to allocate storage for each string using malloc or calloc, fill that allocated string with characters, and then assign that string to the next index of your testtest argument. Since you only get a null, either you are doing an allocation but it failed and returned a null, or you did not assign the allocated string to the next index of your testtest argument.
Consider this generic example
#include <stdlib.h> #include <stdio.h> #define StringArraySize 10 #define StringBufferLen 9 int getStrings(char * * stringArray) { int iString; for (iString = 0; iString < StringArraySize; iString += 1) { char *string = (char *)calloc(StringBufferLen, sizeof(char)); if (string == NULL) return -1; sprintf_s(string, StringBufferLen, "String %d", iString); stringArray[iString] = string; } return 0; } void main() { char *strings[StringArraySize]; int iString; getStrings(strings); for (iString = 0; iString < StringArraySize; iString += 1) { puts(strings[iString]); } }
It would, of course, be better if your function required an additional argument with the size of the given char * array so the function knew not to overrun the array, to re-allocate the array to a larger size, or to allocate a new array if the given array pointer was null.
I hope that helps. - Solange Saad: both my example and Llelan D.'s potentially leak memory.
To eliminate the leak in mine, free() the allocations before leaving
main. (The allocations will be released automatically by the OS when
the program terminates - at least for Windows - but it's good practice
to explicitly free the memory as it avoids developing careless coding
habits.) Note that successive calls to parseXML may use the same allocations
without the need to allocate again or free between calls. However, using
the same allocations may require reinitialization or some other method of
signaling the end of the substrings if an empty string in the array signals
the end of the list. If the return value from parseXML gives the number of
substrings then no reinitializing is needed.
Llelan D.'s example uses a deprecated design: the function which allocates
the memory cannot free it, so the onus is passed to the caller to free
the memory which is allocated within the function each time it is called.
All calls of getStrings(strings) will leak memory unless the *caller* frees
the allocations from each invocation.
Llelan D.'s example may also leak memory if a calloc fails as it does not
internally free any prior successful allocations before returning.
Llelan D.'s getStrings() example uses values which are defined external to
the function and not passed to it as arguments. A better design would pass
these values as arguments, so the function is "self-contained" and not
dependent on the existence of external defines or variables/constants.
Llelan D.:
Quote>void main()
<sheesh>
http://www.research.att.com/~bs/bs_faq2.html#void-main
http://www.parashift.com/c++-faq-lite/newbie.html#faq-29.3
http://www.gidnetwork.com/b-66.html
http://lmgtfy.com/?q=faq+c%2B%2B+void+main
- Wayne - Dear All,
thank you for your time,
actually, i have a code, that already exists, and it is written in C.
this application communicate with another application using socket.
The other application changed it's communication from socket to SOAP XML.
so i wrote a code, using the wininet library, to send my request and receive the xml soap response.
the function parseXML, parse the response, and return some useful information.
int parseXML(char* inputXML, int requestType, char **poutputResponse)
{
char* stag = (char *)calloc(MAX_STRINGS, sizeof(char));
stag = strtok (NULL, "<Price>");
poutputResponse[0] = stag;
printf("%s\n", poutputResponse[0]);
...
}
Note, that for the case of price, one value will be returned, but if the search is for the available services, it will be a list.
Dear LIelan, my code, is like your code, but the value of the returned is zero.
Note: the value inside the function parseXML is not value (300$ for example) - What are you doing here?
Quote>stag = strtok (NULL, "<Price>");
The first argument is supposed to be a pointer to the string to be parsed
on the first call to strtok. Only subsequent calls to continue parsing the
same string should use NULL as the first argument.
Also, when and where do you free the memory allocated by calloc?
- Wayne - You have misunderstood the operation of the strtok function. The first argument should be the string from which you wish to extract the token, and the second is a string of single-character delimiters that separate the tokens. The function modifies the input string, inserting a null after each token and returning a pointer to the start of that token. You are getting a null return because strtok has no input string to search.
A functioning example of what you wrote would be:
#include <stdio.h> #include <stdlib.h> #include <string.h> int parseXML(char* inputXML, int requestType, char **poutputResponse) { char * stag = strtok(inputXML, "<Price>"); poutputResponse[0] = stag; printf("%s\n", poutputResponse[0]); return 0; } void main() { char strXMLInput[] = "<Price>$300</Price>"; char * testtest[10]; int ret = parseXML(strXMLInput, 0, testtest); printf("%s\n", testtest[0]); } Output: $300 $300
You must supply the input string to strtok instead of NULL , and you do not need to allocate a string since the string pointer returned by strtok points to a character in the input string that has been modified by strtok . Also note that strtok is deprecated as unsecure and you should be using the secure version strtok_s .
However, this example is misleading in that the second argument to strtok is actually a list of single-character delimiters and not a single delimiting string.. If the text in the Price element included any of those delimiter characters (say "$P300"), strtok would only return a token up to that delimiter character (only "$", up to the 'P').
XML can not be parsed by simple delimiter characters. It would probably be better if you used an existing XML parsing library instead of trying to reinvent the XML wheel.
I hope that helps. - Solange Saad:
Describe what you're trying to do during the parsing. Maybe strstr() or
sscanf() would be a better match. Show an example of text to be parsed
and what you want to extract/display from that text.
As I commented in my first post, parsing XML strings is not a "simple" task
(unless you're looking for a single value or substring). I concur with Llelan D.
that using an existing XML parsing library may be the easiest approach.
The XML C parser and toolkit of Gnome
http://xmlsoft.org/xml.html
Recursive XML Parser in C
http://www.codeguru.com/cpp/data/data-misc/xml/article.php/c4549/
Parsing XML with Xerces-C C++ API
http://www.yolinux.com/TUTORIALS/XML-Xerces-C.html
- Wayne- Marked As Answer byNancy ShaoMSFT, ModeratorThursday, November 05, 2009 2:56 AM

