Author: Yang Shuo,Hua Qing vision embedded college lecturer.
An important criterion to test whether a C programmer is qualified is to check his ability to operate strings. A qualified C programmer should be able to skillfully split, combine, convert the format, and search and locate strings, extract valid information from a pile of data.
For example, to create a GPS navigation project, we need to read the data sent by the GPS module in the form of ASCII code, and then process the data to extract the information we need. This involves many operations on strings. The following example uses strstr and sscanf functions to parse GPS data.
The format of GPS output data is as follows:
$ Gpgga, 121252.000, 3937.3032, N, 11611.6046, E, 2.0, 45.9, 5.7, M,-0000, M, * 77
$ Gprs mc, 121252.000, A, 3958.3032, N, 11629.6046, E, 15.15, 359.95, 070306, A * 54
$ Gpvtg, 359.95, T, M, 15.15, N, 28.0, K, A * 04
$ Gpgga, 121253.000, 3937.3090, N, 11611.6057, E, 1.2, 44.6, 5.7, M,-0000, M, * 72
$ Gpgsa, A, 3, 14, 15, 05, 2.1, 18, 26, 1.2, 1.7 * 3D
$ Gpgsv, 84,067, 67,067, 49,312, 47,231, 30*70
$ Gpgsv, 32,199, 25,272, 21,140, 14,070, 20 * 7E
$ Gpgsv, 07,074, * 7d
We can see that the GPS module sends a lot of raw data, but usually we only need a part of the information to use it. For example, for the navigation function, we only need to start with $ gprs mc, it is enough to end a line with a linefeed. That is:
$ Gprs mc, 121252.000, A, 3958.3032, N, 11629.6046, E, 15.15, 359.95, 070306, A * 54
So what we need to do is to extract a row starting with $ gprs mc from the read data, and then parse the valid information such as the longitude and latitude, date and time.
Assume that the data read from the serial port is stored in the memory unit pointed to by a string pointer char * raw_buf. First, we use the strstr () provided by ansi c () the function finds the string ending with the linefeed '/N' starting with $ gprs mc:
/* Find "$ gprs mc" from raw_buf */
If (maid "))! = NULL)
{
For (I = 0; I <strlen (wellhandled_string); I ++)
{
If (wellhandled_string [I] = '/N ')
{
Wellhandled_string [I] = '/0'; // replace'/N' with null
}
}
}
The prototype of the strstr () function is declared as follows:
Char * strstr (const char * haystack, const char * needle );
The strstr () function can search for the first position of the string needle in the string haystack and return a pointer to the first address of the string needle. If no value is found, null is returned. Therefore, the above Code searches for the first position of $ gprs mc in the original data raw_buf and assigns the returned pointer to wellhandled_string. if the search is successful, wellhandled_string points to the string starting with $ gprs mc. Next, find the linefeed '/N' through a for loop and replace it with'/0', that is, the string Terminator. In this way, a string pointer wellhandled_string pointing to valid data is obtained.
The task is to extract the longitude and latitude, date and time information from wellhandled_string. This work can be implemented by powerful sscanf functions. The prototype of the sscanf function is as follows:
Int sscanf (const char * STR, const char * format ,...);
We are all familiar with the scanf function. scanf can read data that matches the specified format from the standard input stream. Sscanf reads data from const char * Str. It is powerful in that it can easily retrieve various types of data such as integers, floating points, and strings from strings, and it also has the matching function similar to regular expressions, by default, sscanf separates strings by spaces. If not, % [] can be used to specify the conditions for segmentation. For example, % [A-Z] indicates that all characters from A to Z are read, and % [^ A-Z] indicates that all characters between a-Z are filtered, that is, if any character between A and Z is encountered, the conversion immediately stops. For example:
Sscanf ("abcdefabcdef", "% [^ A-Z]", STR );
Printf ("% s/n", STR );
Result is: abcdef
Matching formats like % [^ A-Z] are strings that we encounter uppercase letters. With this matching method, we can operate strings flexibly to get the desired results.
Now we need to extract valid information from the following string:
$ Gprs mc, 121252.000, A, 3958.3032, N, 11629.6046, E, 15.15, 359.95, 070306, A * 54
The meaning of each field in the gprs mc is as follows:
$ Uplmc, <1>, <2>, <3>, <4>, <5>, <6>, <7>, <8>, <9>, <10>, <11>, <12> * hh <CR> <LF>
<1> UTC time, hhmmss (hour/minute/second) Format
<2> positioning status, A = valid, V = invalid
<3> latitude ddmm. Mmmm (degree) format (the preceding 0 will also be transmitted)
<4> latitude hemisphere N (northern hemisphere) or S (Southern Hemisphere)
<5> longitude dddmm. Mmmm (degree) format (the preceding 0 will also be transmitted)
<6> longitude hemisphere E (eastern longitude) or W (Western longitude)
<7> ground speed (000.0 ~ Section 999.9, the previous 0 will also be transmitted)
<8> ground heading (000.0 ~ 359.9 degrees. Based on the reference of zhenbei, the preceding 0 will also be transmitted)
<9> UTC date, in ddmmyy format
<10> magnetic angle (000.0 ~ 180.0 degrees, the previous 0 will also be transmitted)
<11> magnetic angle direction, E (East) or W (West)
<12> mode indication (output only in nmea0183 3.00, A = self-locating, D = differential, E = estimation, n = Invalid Data)
We extract 1 ~ 9. Store the information with a struct:
Typedef struct gps_info
{
Char utc_time [buf_size];
Char status;
Float latitude_value;
Char latitude;
Float longtitude_value;
Char longtitude;
Float speed;
Float azimuth_angle;
Char utc_data [buf_size];
} Gps_info;
Because each field is separated by a comma, we can use % [^,] to split the string so that the sscanf function can be used to extract valid information:
Sscanf (wellhandled_string, "$ uplmc, % [^,], % C, % F, % F, % [^,] ",
Rmc_info-> utc_time ,/
& (Rmc_info-> status), & (rmc_info-> latitude_value), & (rmc_info-> latitude ),/
& (Rmc_info-> longtitude_value), & (rmc_info-> longtitude), & (rmc_info-> speed ),/
& (Rmc_info-> azimuth_angle ),/
Rmc_info-> utc_data );
After this function is executed, the printed information stored in the struct gps_info struct is as follows:
Utc_time: 024813.640
Status:
Latitude: N latitude value: 3158.460693
Longtitude: E longtitude value: 11848.374023
Speed: 10.050000
Azimuth_angle: 324.269989
Utc_data: 150706
We can see that the sscanf function allows us to efficiently process strings.