Currently I'm trying this, which is printing out nothing (but there are no compilation problems):
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
void parseGprmc(char* gprmc) {
printf("test");
char* ptr;
ptr = strtok(gprmc, ",");
while(ptr != NULL) {
printf("%s\n", ptr);
ptr = strtok(gprmc, ",");
}
}
int main() {
char* gprmc = "$GPRMC,081836,A,3751.65,S,14507.36,E,000.0,360.0,,,E*62";
printf("%s", gprmc);
parseGprmc(gprmc);
printf("%s", gprmc);
return 1;
}
What am I doing wrong?
Ideally, parseGprmc
would print out:
$GPRMC
081836
A
3751.65
S
14507.36
E
000.0
360.0
E*62
Considering the null values as valid as well but I don't think that strtok
does that.
CodePudding user response:
There are two serious issues in your code. First (as pointed out in the comments), the strtok
function modifies the string given as its first argument – but you have declared gprmc
as a pointer to a constant (immutable) string literal. To fix this, change the declaration to a char
array that is initialized with a copy of the literal:
char gprmc[] = "$GPRMC,081836,A,3751.65,S,14507.36,E,000.0,360.0,,,E*62";
Second, only the first call to strtok
for parsing a given string should have that string as its first argument; subsequent calls (on the same string) should use a NULL
first argument (see this cppreference, particularly the part beginning with If str is not a null pointer, ….
Here is a 'fixed' version of your parseGprmc
function:
void parseGprmc(char* gprmc)
{
printf("test");
char* ptr;
ptr = strtok(gprmc, ","); // First call, use string address
while (ptr != NULL) {
printf("%s\n", ptr);
ptr = strtok(NULL, ","); // Subsequent calls, use NULL
}
}
Note that it is not directly possible to extract empty (null) tokens using the strtok
function, as the function searches for the first character which is not contained in delim (quoted from the same cppreference page). To do this, you have to add some 'tricks', comparing the returned address of each token with the address of the end of the previous token, and counting how many delimiter characters were in the 'gap'. Here is a possible modification of your function to do just that:
void parseGprmc(char* gprmc)
{
printf("test");
char* ptr;
char* lastend;
ptrdiff_t nBlanks;
ptr = strtok(gprmc, ","); // First call, use string address
while (ptr != NULL) {
lastend = ptr strlen(ptr); // Address of last character in token
printf("%s\n", ptr);
ptr = strtok(NULL, ","); // Subsequent calls, use NULL
nBlanks = ptr ? ptr - lastend : -1; // Number of delimiters found
while (--nBlanks >= 1) { // One empty token for each gap > 1
printf("<null token>\n");
}
}
}
CodePudding user response:
One remark about strtok is that you must use NULL for the second and next calls. This is because after the first call the contents of gprmc is modified and has an \0 in place of first ,
ptr = strtok(gprmc, ","); // for first call before the loop
ptr = strtok(NULL, ",");// for the call following in the loop
CodePudding user response:
homework? inside the loop you don't pass strtok
a pointer, you pass NULL. See help on that function. But perhaps what you're wanting is to use strchr
instead and change ',' to '\n' ?
CodePudding user response:
strcspn
can be used to parse a literal string.
The specifer %s
precision field %.*s
is used to print only span
characters from the string.
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
void parseGprmc(char* gprmc) {
int span = 0;
printf("test\n");
while( *gprmc) {
span = strcspn ( gprmc, ",");
if ( span) {
printf("%.*s\n", span, gprmc);
}
else {
printf("empty field\n");
}
gprmc = span 1;
}
}
int main() {
char* gprmc = "$GPRMC,081836,A,3751.65,S,14507.36,E,000.0,360.0,,,E*62";
printf("%s\n", gprmc);
parseGprmc(gprmc);
printf("%s\n", gprmc);
return 1;
}