strtok fail at finding new line character ("\n") - c

Here is the function:
int parse_headers(c_request *req, char *raw_headers) {
char *command_line;
char *raw_header;
req->headers = NULL;
command_line = strtok_r(raw_headers, "\\n", &raw_headers);
printf("command line = [%s]\n", command_line);
if (parse_command(req, command_line) < 0)
return -1;
while ((raw_header = strtok_r(raw_headers, "\\n", &raw_headers))) {
printf("\nraw header = [%s]\n", raw_header);
parse_header(req, raw_header);
}
return 0;
}
raw_headers equal :
POST www.google.fr HTTP/1.1\nUser-Agent: Mozilla/4.0 (compatible; MSIE5.01; Windows NT)\nHost: www.tutorialspoint.com\nContent-Type: text/xml; charset=utf-8\nContent-Length: 38\nAccept-Language: en-us\nAccept-Encoding: gzip, deflate\nConnection: Keep-Alive\r\n\r\n<?xml version='1.0' encoding='utf-8'?
So strtok find the first \n (command_line equal POST www.google.fr HTTP/1.1), but in the while loop, when I print the raw_header, it print me raw header = [User-Age] instead of raw header = [User-Agent: Mozilla/4.0 (compatible; MSIE5.01; Windows NT)]
What can I do to fix that?

The delimiter "\\n" specified for strtok_r consists of two characters: '\\' and 'n'. There is a n after User-Age, so the data is cut there.
You should use "\n" to have strtok_r search for LF.
If you actually want to separate the data by a multi-charcter string "\\n", then strtok_r is not for that. You should do it manually, maybe using strstr().

Hmm.... you are using a delimiter formed by a backslash (\) and the character n, not a new line (new line has to be written as \n, not \\n. You can try to check how it parses a string with n's or backslashes, and you'll see how it breaks the string at these two characters.

Related

Regular expressions with scanf in C

I'm trying to achieve the following without any success:
Removing the opening
message "
and trailing
"
while leaving the content in between, and saving it into my variable, using sscanf regular expressions.
I wrote the following code:
sscanf( buffer, "message \"%[^\"]", message)
Which works good when I have something like message "Hey there", but when I'm trying the following string, I get only the white space between the two quotation marks.
message " """ This is a Test """ "
The result for this should be """ This is a Test """
Is there a way to upgrade my expression so it will include this extreme event of message? I tried to look it up both in google and here, and couldn't find an elegant answer. I'm aware that it's possible using string manipulation with a lot lines of code, but I'm trying something more simple here.
P.S. The trailing " is the end of the expression, and is a must by the program, after that comes nothing.
Thanks in advance for the feedback!
If you're fine with not using regex for the whole thing:
Original version:
sscanf(buffer, "message \"%[^$]", message); // remove 'message "'
message[strlen(message) - 1] = '\0'; // remove trailing '"'
Safe, correct, and generic version:
char* buffer = ...;
const char* prefix = "message \"";
const char* suffix = "\"";
if (strstr(buffer, prefix) != buffer) {
// error, doesn't start with `prefix`
}
buffer += strlen(prefix);
char* suffixStart = strrchr(buffer, suffix[0]);
if (!suffixStart || strcmp(suffixStart, suffix) != 0) {
// error, doesn't end with `suffix`
}
*suffixStart = '\0'; // strip `suffix`

detect if a line is match to a format - in C

I have a file and I need to check if its lines are in the following format:
name: name1,name2,name3,name4 ...
(some string, followed by ":", then a single space and after that strings separated by ",").
I tried doing it with the following code:
int result =0;
do
{
result =sscanf(rest,"%[^:]: %s%s", p1,p2,p3);
if(result==3)
{
printf("invalid!");
fclose(fpointer);
return -1;
}
}while (fgets(rest ,LINE , fpointer) != NULL);
this works good for lines like: name: name1, name2 (with space between name1, and name2).
but it fails with the following line:
name : name1,name2
I want to somehow tell sscanf not to avoid this white space before the ":".
could someone see how ?
Thanks for helping!
This works for me:
result = sscanf(rest,"%[^*:]: %[^,],%s", p1, p2, p3);
Notice the * is used to consume the space (if any).

Breaking a string in C with multiple spaces

Ok, so my code currently splits a single string like this: "hello world" into:
hello
world
But when I have multiple spaces in between, before or after within the string, my code doesn't behave. It takes that space and counts it as a word/number to be analyzed. For example, if I put in two spaces in between hello and world my code would produce:
hello
(a space character)
world
The space is actually counted as a word/token.
int counter = 0;
int index = strcur->current_index;
char *string = strcur->myString;
char token_buffer = string[index];
while(strcur->current_index <= strcur->end_index)
{
counter = 0;
token_buffer = string[counter+index];
while(!is_delimiter(token_buffer) && (index+counter)<=strcur->end_index)//delimiters are: '\0','\n','\r',' '
{
counter++;
token_buffer = string[index+counter];
}
char *output_token = malloc(counter+1);
strncpy(output_token,string+index,counter);
printf("%s \n", output_token);
TKProcessing(output_token);
//update information
counter++;
strcur->current_index += counter;
index += counter;
}
I can see the problem area in my loop, but I'm a bit stumped as to how to fix this. Any help would be must appreciated.
From a coding stand point, if you wanted to know how to do this without a library as an exercise, what's happening is your loop breaks after you run into the first delimeter. Then when you loop to the second delimeter, you don't enter the second while loop and print a new line again. You can put
//update information
while(is_delimiter(token_buffer) && (index+counter)<=strcur->end_index)
{
counter++;
token_buffer = string[index+counter];
}
Use the standard C library function strtok().
Rather than redevelop such a standard function.
Here's the related related manual page.
Can use as following in your case:
#include <string.h>
char *token;
token = strtok (string, " \r\n");
// do something with your first token
while (token != NULL)
{
// do something with subsequents tokens
token = strtok (NULL, " \r\n");
}
As you can observe, each subsequent call to strtok using the same arguments will send you back a char* adressing to the next token.
In the case you're working on a threaded program, you might use strtok_r() C function.
First call to it should be the same as strtok(), but subsequent calls are done passing NULL as the first argument. :
#include <string.h>
char *token;
char *saveptr;
token = strtok_r(string, " \r\n", &saveptr)
// do something with your first token
while (token != NULL)
{
// do something with subsequents tokens
token = strtok_r(NULL, " \r\n", &saveptr)
}
Just put the process token logic into aif(counter > 0){...}, which makes malloc happen only when there was a real token. like this
if(counter > 0){ // it means has a real word, not delimeters
char *output_token = malloc(counter+1);
strncpy(output_token,string+index,counter);
printf("%s \n", output_token);
TKProcessing(output_token);
}

Extracting JSON text from char response buffer

I receive a large chunk of text from my Wi-Fi module.
Which is saved in my response buffer.
char wifiResponseBuffer[500];
The contents can be seen below :
AT+CIPSEND=84
> GET http://api.noteu.co.uk/v1/poll/get/?seria
SEND OK
+IPD,308:{"data":[{"line1":" Facebook Note ","line2":"Nathan Weighill also","line3":" commented on Harry ","line4":" Bailey's photo.","beep":1,"received_time":1424976639},{"line1":" Gmail Message ","line2":"","line3":"Noteu Error","line4":"","beep":1,"received_time":1424976640}],"summary":{"note_count":2}}
OK
OK
Unlink
I have a JSON parser library however need to extract the actual JSON text from the response before it can be parsed. This is at the first occurrence of { and last occurrence of }.
What combination of string functions can I use in C to find the indexes of these characters and then extract the JSON text.
Any help is greatly appreciated,
Jack
strchr is used to find the first occurrence of a character in a string. strrchr finds the last.
Here's a brief example of how you might use these:
int test(void)
{
char wifiResponseBuffer[500];
int wifi_len;
// get the WiFi data, leaving 1 byte for a NUL terminator
wifi_len = get_wifi_response(wifiResponseBuffer, sizeof(wifiResponseBuffer)-1);
if (wifi_len < 0)
return -1; // error
// NUL-terminate to use with strxxx functions
wifiResponseBuffer[wifi_len] = '\0';
// Find start of JSON data
const char *json_start = strchr(wifiResponseBuffer, '{');
if (json_start == NULL)
return -1;
json_start++; // advance past {
// Find end of JSON data
const char *json_end = strchr(json_start, '}');
if (json_end == NULL)
return -1;
// Pass the JSON data to the library
size_t json_len = json_end - json_start;
do_something_with_json_data(json_start, json_len);
}

The last character is not printed to a file

I am trying to figure out why using C function strtok is not working properly for me. Here's the problem:
I have a file which contains two types of information: headers and text descriptions. Each line in the file is either a header or part of a text description. A header starts with '>'. The description text follows the header and can span multiple lines. At the end of the text there is an empty line which separates the description from the next header. My aim is to write two separate files: one contains the headers on each line and the other contains the corresponding description on a line by itself. To implement the codes in C, I used fgets to read the file one line at a time into dynamically allocated memory. In order to write the description text on one single line, I used `strtok to get rid of any new line characters exists in the text.
My code is working properly for the header files. However, for the descriptions file, I noticed that the last character of the text is not printed out to the file even though it is printed to the stdout.
FILE *headerFile = fopen("Headers", "w"); //to write headers
FILE *desFile = fopen("Descriptions", "w"); //to write descriptions
FILE *pfile = fopen("Data","r");
if ( pfile != NULL )
{
int numOfHeaders =0;
char **data1 = NULL; //an array to hold a header line
char **data2 = NULL; //an array to hold a description line
char line[700] ; //maximum size for the line
while (fgets(line, sizeof line, pfile ))
{
if(line[0] =='>') //It is a header
{
data1 = realloc(data1,(numOfHeaders +1)* sizeof(*data1));
data1[numOfHeaders]= malloc(strlen(line)+1);
strcpy(data1[numOfHeaders],line);
fprintf(headerFile, "%s",line);//writes the header
if(numOfHeaders >0)
fprintf(desFile, "\n");//writes a new line in the desc file
numOfHeaders++;
}
//it is not a header and not an empty line
if(line[0] != '>' && strlen(line)>2)
{
data2 = realloc(data2,(numOfHeaders +1)* sizeof(*data2));
data2[numOfHeaders]= malloc(strlen(line)+1);
char *s = strtok(line, "\n ");
strcpy(data2[numOfHeaders],s);
fprintf(desFile, "%s",data2[numOfHeaders]);
printf(desFile, "%s",data2[numOfHeaders]);
}
} //end-while
fclose(desFile);
fclose(headerFile);
fclose(pfile );
printf("There are %d headers in the file.\n",numOfHeaders);
}
As mentioned in the comments:
fprintf(desFile, "%s",data2[numOfHeaders]); //okay
printf(desFile, "%s",data2[numOfHeaders]); //wrong
Second line should be:
printf("%s",data2[numOfHeaders]); //okay
Or, you could do this:
sprintf(buffer, "%s",data2[numOfHeaders]);
fprintf(desFile, buffer);
printf(buffer);
Other possible issues:
Without an input file it is not possible to know for certain what strtok() is doing, but here is a guess based on what you have described:
In these two lines:
data2[numOfHeaders]= malloc(strlen(line)+1);
char *s = strtok(line, "\n ");
if the string contained in data2 has any embedded spaces, s will only contain the segment occurring before that space. And because you are only calling it once before line gets refreshed:
while (fgets(line, sizeof line, pfile ))
only one token (the very first segment) will be read.
Not always, but Normally, strtok() is called in a loop:
char *s = {0};
s= strtok(stringToParse, "\n ");//make initial call before entering loop
while(s)//ALWAYS test to see if s contains new content, else NULL
{
//do something with s
strcpy(data2[numOfHeaders],s);
//get next token from string
s = strtok(NULL, "\n ");//continue to tokenize string until s is null
}
But, as I said above, you are calling it only once on that string before the content of the string is changed. It is possible then, that the segment not printing has simply not yet been tokenized by strtok().

Resources