tags:

views:

180

answers:

7

I have to parse this string in C:

XFR 3 NS 207.46.106.118:1863 0 207.46.104.20:1863\r\n

And be able to get the 207.46.106.118 part and 1863 part (the first ip address).

I know I could go char by char and eventually find my way through it, but what's the easiest way to get this information, given that the IP address in the string could change to a different format (with less digits)?

+2  A: 

Depends on what defines the format of the document. In this case, it may be as simple as tokenizing the string and looking through the tokens for what you want. Simply use strtok and split on spaces to grab the 207.46.106.118:1863 and then you can tokenize that again (or simply scan for the : manually) to get the proper components.

Daniel DiPaolo
+2  A: 

You could use strtok to tokenize breaking on space, or you could use one of the scanf family to pull out data as well.

There is a big caveat in all of this though, these are functions that are notorious for security and mishandling bad input. YMMV.

Ukko
+9  A: 

You can use sscanf() from the C standard lib. Here's an example of how to get the ip and port as strings, assuming the part in front of the address is constant:

#include <stdio.h>

int main(void)
{
    const char *input = "XFR 3 NS 207.46.106.118:1863 0 207.46.104.20:1863\r\n";

    const char *format = "XFR 3 NS %15[0-9.]:%5[0-9]";
    char ip[16] = { 0 };  // ip4 addresses have max len 15
    char port[6] = { 0 }; // port numbers are 16bit, ie 5 digits max

    if(sscanf(input, format, ip, port) != 2)
        puts("parsing failed");
    else printf("ip = %s\nport = %s\n", ip, port);

    return 0;
}

The important parts of the format strings are the scanset patterns %15[0-9.] and %5[0-9], which will match a string of at most 15 characters composed of digits or dots (ie ip addresses won't be checked for well-formedness) and a string of at most 5 digits respectively (which means invalid port numbers above 2^16 - 1 will slip through).

Christoph
everything except the IP addresses and Port numbers. The ip address might change (more/less digits)... same as with port.
Luca Matteis
@Luca: do you want to get the ip address/port as strings or integers? do you care if the rest of the string is well-formed or are you only interested in the first ip address?
Christoph
yes, i need both address/port as strings. don't care about the rest.
Luca Matteis
@Luca: added example code
Christoph
@Christoph: +1. very nice usage of scanf. can you explain how it works, too?
kolistivra
@kolistivra: done
Christoph
Thanks a bunch. Exactly what I was looking for.
Luca Matteis
@Christoph: thanks for the explanation!
kolistivra
A: 

If the strings to be parsed are well-formatted then I'd go with Daniel and Ukko's suggestion to use strtok().

A word of warning though: strtok() modifies the string that it parses. Not always what you want.

Andy Johnson
+1  A: 

In this case, strok() is of trivial use and would be my choice. For safety, you might count the ':' in your string and proceed if there is exactly one ':'.

mico
+2  A: 

Loop through until you get the first '.', and loop back until you find ' '. The loop forward until you find ':', building sub-strings every time you meet '.' or ':'. You can check the number of substrings and their lengths as simple error checking. Then loop until you find a ' ' and you have the 1863 part.

This would be robust if the beginning of the string doesn't vary much. And also very easy. You could make it even simpler if the string always begins with "XFR 3 NS ".

John
A: 

This may be overkill, since you said you didn't want to use a regex library, but the re2c program will give you regex parsing without the library: it generates the DFSM for a regular expression as C code. The regexps are specified in comments embedded in C code.

And what seems like overkill now may become a comfort to you later should you have to parse the rest of the string; it is a lot easier to modify a few regexps to adjust or add new syntax than to modify a bunch of ad hoc tokenizing code. And it makes the structure of what you are parsing a lot clearer in your code.

Tim Schaeffer