Solved

sending integer array of data

Posted on 2007-11-17
22
223 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
[X]
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
  • 10
  • 6
  • 6
22 Comments
 
LVL 55

Expert Comment

by:Jaime Olivares
ID: 20306709
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
ID: 20306784
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
ID: 20306803
Do you need a pure C solution?
A C++ solution will be cleaner and easier.
0
Industry Leaders: We Want Your Opinion!

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

 

Author Comment

by:shankarraj
ID: 20306817
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
ID: 20306851
>> 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
ID: 20306864
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
ID: 20306882
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
ID: 20312757
>>>> 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
ID: 20312826
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
ID: 20312906
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
ID: 20312921
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
 

Author Comment

by:shankarraj
ID: 20313139
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
ID: 20313207
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
ID: 20313314
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
ID: 20314001
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
ID: 20314011
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
ID: 20314018
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
ID: 20314042
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
ID: 20314317
>>>> 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
ID: 20314330
Correction:

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

Expert Comment

by:Jaime Olivares
ID: 20314382
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
ID: 20314527
>>>> 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

Technology Partners: We Want Your Opinion!

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Article by: SunnyDark
This article's goal is to present you with an easy to use XML wrapper for C++ and also present some interesting techniques that you might use with MS C++. The reason I built this class is to ease the pain of using XML files with C++, since there is…
An Outlet in Cocoa is a persistent reference to a GUI control; it connects a property (a variable) to a control.  For example, it is common to create an Outlet for the text field GUI control and change the text that appears in this field via that Ou…
Video by: Grant
The goal of this video is to provide viewers with basic examples to understand and use nested-loops in the C programming language.
The viewer will learn how to clear a vector as well as how to detect empty vectors in C++.

752 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