-1

All:

I got one question in string parsing:

For now, if I have a string like "+12+400-500+2:+13-50-510+20-66+20:"

How can I do like calculate total sum of each segment( : can be consider as end of one segment). For now, what I can figure out is only use for to loop through and check +/- sign, but I do not think it is good for a Universal method to solve this kind of problem :(

For example, the first segment, +12+400-500+2 = -86, and the second segment is
+13-50-510+20-66+20 = -573

1) The number of operand is varied( but they are always integer) 
2) The number of segment is varied
3) I need do it in C++ or C.

I do not really think it as a very simple question to most newbie, and also I will claim this is not a homework. :)

best,

Kuan
  • 11,149
  • 23
  • 93
  • 201

4 Answers4

3

Since the string ends in a colon, it is easy to use find and substr to separate out parts of the string partitioned by ':', like this:

string all("+12+400-500+2:+13-50-510+20-66+20:");
int pos = 0;
for (;;) {
    int next = all.find(':', pos);
    if (next == string::npos) break;
    string expr(all.substr(pos, (next-pos)+1));
    cout << expr << endl;
    pos = next+1;
}

This splits the original string into parts

+12+400-500+2:

and

+13-50-510+20-66+20:

Since istreams take leading plus as well as leading minus, you can parse out the numbers using >> operator:

istringstream iss(expr);
while (iss) {
    int n;
    iss >> n;
    cout << n << endl;
}

With these two parts in hand, you can easily total up the individual numbers, and produce the desired output. Here is a quick demo.

Sergey Kalinichenko
  • 714,442
  • 84
  • 1,110
  • 1,523
  • Thanks, dasblinkenlight!, I will try this. – Kuan May 02 '13 at 13:54
  • this is amazing, I am newbie to C++, can you tell me how and where can I find this kind of special usage? Or can you give me some link about something like "C++ secret"? – Kuan May 02 '13 at 14:05
  • @Kuan There's absolutely, definitely, no secret to C++, it just takes a while to "get" it. You can find info on the various C++ classes online. For example, `std::string` is described [here](http://www.cplusplus.com/reference/string/string/); `std::istringstream` is [here](http://www.cplusplus.com/reference/sstream/istringstream/). – Sergey Kalinichenko May 02 '13 at 14:12
  • Yeah, thanks, I read the link and also I read some more tutorial about I/O stream class, but when they talked about istringstream, all they say is use space as delimiter, so that is why I am surprise +/- can also be delimiter, and this is the most thing I am really interested that how do you find +/- can also use as delimiter? Can you give me some clue how to efficiently read to get more from those reference? Thnaks so much! – Kuan May 02 '13 at 14:23
  • @Kuan `+` and `-` are not used as delimiters, they are used as signs in front of an integer. Streams expect integers with an optional sign and a string of one or more digits. As soon as the digits after the sign end, the stream stops parsing. The sign right after the string of digits happens to be the one for the next number, though. – Sergey Kalinichenko May 02 '13 at 14:28
  • I'm wondering shouldn't this be string expr(all.substr(pos, (next-pos)+1)), since substr expects position and length as arguments? – dev_nut Oct 07 '13 at 20:59
  • @dev_nut You're right, thanks for the correction! I edited the answer to fix this problem. Thank you! – Sergey Kalinichenko Oct 07 '13 at 21:13
1

You need to seperate operands and operators. To do this you can use two queue data types one for operands and one for operators

Ozan Deniz
  • 1,087
  • 7
  • 22
0

split by :, then by +, then by -. translate into int and there you are.

Elazar
  • 20,415
  • 4
  • 46
  • 67
0

Your expression language seems regular: you could use a regex library - like boost::regex - to match the numbers, the signs, and the segments in groups directly, with something like

 ((([+-])([0-9]+))+)(:((([+-])([0-9]))+))+
didierc
  • 14,572
  • 3
  • 32
  • 52