Solved

sending integer array of data

Posted on 2007-11-17
22
217 Views
Last Modified: 2010-04-01
Hi,

I am generating some numbers in my server program. I would like to send this integer array to the client in the form of message.
I will retrieve the sent numbers using the header in client.

The generated numbers is in the form of integer array as:
int MyNumbers[10];
These numbers are put into message as:
char charArrData[100];
sprintf(charArrData, "<Message><MyNumbers><header>NumberSeries</header><data>
%d</data></MyNumbers></Message>", Numbers);
Here , I am facing the problem in forming the message using the inetger array by using sprintf().
Please help me like how to form the message using the sprintf( ) here and getting the value using the header at the client side.

Thanks,
shankarraj
0
Comment
Question by:shankarraj
  • 10
  • 6
  • 6
22 Comments
 
LVL 55

Expert Comment

by:Jaime Olivares
Comment Utility
to fill you message you will need a loop, use another little buffer:

char OneNumber[10]; /* add this */
int MyNumbers[10];
char charArrData[100];  /* I suggest you to use 200 */
int i;

strcpy(charArrData, "<Message><MyNumbers><header>NumberSeries</header><data>");
for (i=0; i<10; i++)
{
      sprintf(OneNumber, "%s%d", i>0?",":"", MyNumbers[i]);   /* add a comma, excepting 1st value */
      strcat(charArrData, OneNumber);
}
strcat(charArrData, "</data></MyNumbers></Message>");
0
 

Author Comment

by:shankarraj
Comment Utility
Hi,

Let us assume that I have sent following mesage from my server program and the message is received at my client program as:
<Message><MyNumbers><header>NumberSeries</header><data>20,41,57</data></MyNumbers></Message>

Also, I would like my API as:
HubMessage *ptrMessage;
int Numbers[3]=ptrHubMessage->getFieldValue("NumberSeries", 1);
Please tell me like how to I retrieve the array of integers from the message in the above case as the array of numbers are separated by a comma in the mesage?

Thanks,
shankarraj



0
 
LVL 55

Expert Comment

by:Jaime Olivares
Comment Utility
Do you need a pure C solution?
A C++ solution will be cleaner and easier.
0
 

Author Comment

by:shankarraj
Comment Utility
Hi,

I am looking for C++ solution.
I would like to retrieve all the array values at a stretch from the message in the client side as I mentioned earlier. i.e. int Numbers[3]=ptrHubMessage->getFieldValue("NumberSeries", 1);

Please help me to do this.

Thanks,
shankarraj
0
 
LVL 55

Expert Comment

by:Jaime Olivares
Comment Utility
>> int Numbers[3]=ptrHubMessage->getFieldValue("NumberSeries", 1);
How you will know that there are 3 elements before parsing the values?
A pure C solution will require a malloc() or calloc() allocation;
A C++ solution will require to create the array with a new operator.

so, it could be something like:
int *Numbers = ptrHubMessage->getFieldValue("NumberSeries", 1);
don't know what 1 means.

But Numbers will not tell you the array size. A more C++ like solution will be:

std::vector<int> *Numbers = ptrHubMessage->getFieldValue("NumberSeries", 1);

To acomplish this, you will have to parse the message itself, and extract the numbers array as a string. a STL std::string will be easier to process.
Then you have to split the string into values.  Something like this:

vector<int>* ParseValues(const string& str)
{
    vector<int>* tokens = new vector<int>();

    // Skip delimiters at beginning.
    string::size_type lastPos = str.find_first_not_of(",", 0);
    // Find first "non-delimiter".
    string::size_type pos  = str.find_first_of(",", lastPos);

    while (string::npos != pos || string::npos != lastPos)
    {
        // Found a token, add it to the vector.
        tokens.push_back(atoi(str.substr(lastPos, pos - lastPos).c_str()));
        // Skip delimiters.  Note the "not_of"
        lastPos = str.find_first_not_of(",", pos);
        // Find next "non-delimiter"
        pos = str.find_first_of(",", lastPos);
    }
}
0
 

Author Comment

by:shankarraj
Comment Utility
Hi,
 int Numbers[3]=ptrHubMessage->getFieldValue("NumberSeries", 1);
where 1 is the row number.
Also, as you have told, I will not be knowing that there are 3 elements before parsing the values. There may be any number of elements in the array.

Thanks,
shankarraj

0
 
LVL 55

Expert Comment

by:Jaime Olivares
Comment Utility
Being 1 the row number, you have to scan all the file until you reach the desired row.
but in an XML document, a row is an ambigous term, maybe a record, or Message number would be more exact, because a Message can occupy more than 1 text rows, or maybe 2 messages can occupy 1 single text rows.

Sounds like you will require some xml parser ...
0
 
LVL 39

Expert Comment

by:itsmeandnobodyelse
Comment Utility
>>>> int Numbers[3]=ptrHubMessage->getFieldValue("NumberSeries", 1);
That cannot work for different reasons:

1. A fixed array variable like 'int Numbers[3]' only can be initialized by a const array:

   int Numbers[3] = { 1, 2, 3};

but not by a function return value.

2. The function at the right side of an assignment doesn't know the size of the array to return. If it is dynamic we need a dynamic array at the left side of the assignment as well.

You can heal both by something like

   int Numbers[3];
   if (ptrHubMessage->getFieldValue(Numbers, 3, "NumberSeries", 1))
   {
         // ok we got 3 values from serialized message
   }

where the getFieldValue has overloads for different result types.

Regards, Alex



0
 

Author Comment

by:shankarraj
Comment Utility
Hi jaime_olivares:,

Please tell me like how to read the integer  array values from the vector: tokens in the following program which is given by you in your earlier answer:

std::vector<int> *Numbers = ptrHubMessage->getFieldValue("NumberSeries", 1);

To acomplish this, you will have to parse the message itself, and extract the numbers array as a string. a STL std::string will be easier to process.
Then you have to split the string into values.  Something like this:

vector<int>* ParseValues(const string& str)
{
    vector<int>* tokens = new vector<int>();

    // Skip delimiters at beginning.
    string::size_type lastPos = str.find_first_not_of(",", 0);
    // Find first "non-delimiter".
    string::size_type pos  = str.find_first_of(",", lastPos);

    while (string::npos != pos || string::npos != lastPos)
    {
        // Found a token, add it to the vector.
        tokens.push_back(atoi(str.substr(lastPos, pos - lastPos).c_str()));
        // Skip delimiters.  Note the "not_of"
        lastPos = str.find_first_not_of(",", pos);
        // Find next "non-delimiter"
        pos = str.find_first_of(",", lastPos);
    }
}

Please help me here to read the integer array values from the vector tokens .

Thanks,
shankarraj
0
 
LVL 55

Expert Comment

by:Jaime Olivares
Comment Utility
vector<> is similar to an array. Easiest way to access is with direct indexing, like:

int a;
for (int i=0; i<theVector.size(); i++)
{
     a= theVector[i];
     // do something with a
}
0
 
LVL 55

Expert Comment

by:Jaime Olivares
Comment Utility
Also, assumming you will hold the vector object with a pointer, it shoul be:

int a;
for (int i=0; i<pVector->size(); i++)
{
     a= (*pVector)[i];
     // do something with a
}

finally you have to discard the vector object when you no longer need it, to avoid a memory leak:

delete pVector;
0
Better Security Awareness With Threat Intelligence

See how one of the leading financial services organizations uses Recorded Future as part of a holistic threat intelligence program to promote security awareness and proactively and efficiently identify threats.

 

Author Comment

by:shankarraj
Comment Utility
Hi jaime_olivares,

<Message><MyNumbers><header>NumberSeries</header><data>9,5,26,30,43,39,31,30,40,10,32</data></MyNumbers></Message>
For the above message, when I used following vector program:
I am getting the output value as: 0 5 26 30 43 39 31 30 40 10 32

Note: I am using cout<<atoi(str.substr(lastPos, pos - lastPos).c_str()); in your program to display the values.  

I am observing value: 0 instead of 9. Please tell me the problem for receiving value 0 instead of 9 here.

vector<int>* ParseValues(const string& str)
{
    vector<int>* tokens = new vector<int>();

    // Skip delimiters at beginning.
    string::size_type lastPos = str.find_first_not_of(",", 0);
    // Find first "non-delimiter".
    string::size_type pos  = str.find_first_of(",", lastPos);

    while (string::npos != pos || string::npos != lastPos)
    {
        // Found a token, add it to the vector.
        tokens.push_back(atoi(str.substr(lastPos, pos - lastPos).c_str()));
        // Skip delimiters.  Note the "not_of"
        lastPos = str.find_first_not_of(",", pos);
        // Find next "non-delimiter"
        pos = str.find_first_of(",", lastPos);
    }
}



0
 
LVL 55

Expert Comment

by:Jaime Olivares
Comment Utility
you cannot pass all the string to the ParseValues function, you have to separate first to have just:
9,5,26,30,43,39,31,30,40,10,32
0
 

Author Comment

by:shankarraj
Comment Utility
Hi jaime olivares,

I need to retrieve all the values from the message:
<Message><MyNumbers><header>NumberSeries</header><data>9,5,26,30,43,39,31,30,40,10,32</data></MyNumbers></Message>
Please help me to do this using your vector program.

Thanks,
shankarraj
0
 
LVL 55

Expert Comment

by:Jaime Olivares
Comment Utility
could be something like this:
std::string full = "<Message><MyNumbers><header>NumberSeries</header><data>9,5,26,30,43,39,31,30,40,10,32</data></MyNumbers></Message>"

int start = full.find("<data>",0);
int end = full.find("</data",0);
if (start!=std::string::npos && end!=std::string::npos)
{
      std:string portion = full.substr(start+6, start-end-6);
      vector<int> *list = ParseValues(portion);
}


0
 
LVL 39

Expert Comment

by:itsmeandnobodyelse
Comment Utility
Better use:

int ParseValues(const string& s, vector<int>& tokens)
{
    string str = s;  // take a writeable copy
    s += ',';    // add a delimiter at end

    string::size_type lastPos = 0;
    string::size_type pos  = 0;

    while ((pos = str.find(',', lastPos)) != string::npos)
    {
        // Found a token, add it to the vector.
        if (pos > lastPos)
        {
             int i;
             istringstream iss(str.substr(lastPos, pos - lastPos));
             if (iss >> i)
             {
                   tokens.push_back(i);
             }
             lastPos = pos+1;
         }
    }
     return tokens.size();
}

Regards, Alex
0
 
LVL 39

Expert Comment

by:itsmeandnobodyelse
Comment Utility
correction:

int ParseValues(const string& s, vector<int>& tokens)
{
    string str = s;  // take a writeable copy
    s += ',';    // add a delimiter at end

    string::size_type lastPos = 0;
    string::size_type pos  = 0;

    while ((pos = str.find(',', lastPos)) != string::npos)
    {
        // Found a token, add it to the vector.
        if (pos > lastPos)
        {
             int i;
             istringstream iss(str.substr(lastPos, pos - lastPos));
             if (iss >> i)
             {
                   tokens.push_back(i);
             }
         }
         lastPos = pos+1;   // must be done in every case
    }
     return tokens.size();
}

0
 
LVL 55

Accepted Solution

by:
Jaime Olivares earned 125 total points
Comment Utility
Alex,
the problem is that the author is sending the full xml string to the Parse function, without extracting the data portion.
0
 
LVL 39

Expert Comment

by:itsmeandnobodyelse
Comment Utility
>>>> the problem is that the author is sending the full xml string to the Parse function
The above parser should work beside of the very first number cause it only extracts numbers separated by comma. To make it valid when passing all xml string it is:

int ParseValues(const string& s, vector<int>& tokens)
{
    string::size_type pos  = s.find("<data>");
    string::size_type lastPos = s.find("</data>");
    if (pos == string::npos || lastPos == string::npos || lastPos < pos)
          return -1;  // invalid xml  

    pos += sizeof("<data>")-1;
    string str = s.substr(pos, lastPos - pos);  // take data portion
    str += ',';    // add a delimiter at end

    while ((pos = str.find(',', lastPos)) != string::npos)
    {
        // Found a token, add it to the vector.
        if (pos > lastPos)
        {
             int i;
             istringstream iss(str.substr(lastPos, pos - lastPos));
             if (iss >> i)
             {
                   tokens.push_back(i);
             }
         }
         lastPos = pos+1;   // must be done in every case
    }
     return tokens.size();
}

That should do it.

0
 
LVL 39

Expert Comment

by:itsmeandnobodyelse
Comment Utility
Correction:

    lastPos = 0;  // reset lastPos before while loop
0
 
LVL 55

Expert Comment

by:Jaime Olivares
Comment Utility
my ParseValues proposal is just to parse a clean list, not the entire XML, I think mixing both tasks does not contribute to legibility.
That's why I have put in a separted post.
0
 
LVL 39

Expert Comment

by:itsmeandnobodyelse
Comment Utility
>>>> I think mixing both tasks does not contribute to legibility.
You are right. But if the xml is only 'boxing' and is not intended to provide a full independent and enhanceable xml document, parsing it that way maybe is a pragmatical approach. I am pretty sure that there are much more self-written parsers like the one I posted than full xml parsers. But the asker has to decide.
0

Featured Post

What Should I Do With This Threat Intelligence?

Are you wondering if you actually need threat intelligence? The answer is yes. We explain the basics for creating useful threat intelligence.

Join & Write a Comment

Templates For Beginners Or How To Encourage The Compiler To Work For You Introduction This tutorial is targeted at the reader who is, perhaps, familiar with the basics of C++ but would prefer a little slower introduction to the more ad…
This tutorial is posted by Aaron Wojnowski, administrator at SDKExpert.net.  To view more iPhone tutorials, visit www.sdkexpert.net. This is a very simple tutorial on finding the user's current location easily. In this tutorial, you will learn ho…
The goal of this video is to provide viewers with basic examples to understand recursion in the C programming language.
The goal of the tutorial is to teach the user how to use functions in C++. The video will cover how to define functions, how to call functions and how to create functions prototypes. Microsoft Visual C++ 2010 Express will be used as a text editor an…

744 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

17 Experts available now in Live!

Get 1:1 Help Now