1

I'm working on a program in C for a class that requires me to take a request-line and break it down into its subsequent pieces. It's for learning purposes, so I can expect a fairly standard request-line.

Thinking about the problem, I was going to march through each char in the request-line with some sort of for() loop that creates a new string every time it encounters a SP, but I was wondering if there was a way to use strchr() to point to each "piece" of the request-line?

Since a request-line looks like method SP request-target SP HTTP-version CRLF where SP is a single space, is there some way I could create a function that uses strchr(request-line, ' ') to create a string (or char* or char[ ]) that then ENDS at the next SP ?

edit:

So I could do something like

char method = strchr(request-line, ' ');

But then, wouldn't "method" be every char after the SP? How can I "trim" what gets put into my variable? Or am I totally misunderstanding how this function works?

Caleb Jay
  • 2,159
  • 3
  • 32
  • 66
  • 3
    Do you think strtok() would be helpful here? – a3.14_Infinity Oct 13 '15 at 17:48
  • I haven't heard about that before, but it looks interesting. I'm googling to find some more usage examples than just the man page, but do you have any good ones you know of off the top of your head? – Caleb Jay Oct 13 '15 at 17:51
  • 1
    @komali_2 [Refer here](http://en.cppreference.com/w/c/string/byte/strtok) – ameyCU Oct 13 '15 at 17:52
  • `strtok()` basically takes a string and chops it up (one token at a time) and gives you a pointer to each token. Internally, it's putting a `0` where the delimiter was found, and remembering the pointer past the delimeter, and passing a pointer to the start of the token. It isn't thread safe, btw. – Russ Schultz Oct 13 '15 at 17:54
  • 1
    The trouble with `strtok` is it modifies the buffer you pass. With nothing more than `strchr` you can easily find the beginning and end of each string, and that's all you need to create the null-terminated strings you need. – Carey Gregory Oct 13 '15 at 17:55
  • Yes , therefore don't pass string literal to it . – ameyCU Oct 13 '15 at 17:56
  • You should give an `input` example and an `output` example – Jay Oct 13 '15 at 18:00
  • What's this `SP` malarky? Is it a single space or 3 spaces as shown? Why not just put one space to be clear? – Weather Vane Oct 13 '15 at 18:08
  • @Weather-Vane Clarity for students I would imagine. `methodSPrequest-targetSPHTTP-versionCRLF` – Caleb Jay Oct 13 '15 at 18:10
  • @Carey-Gregory I'm trying to put something together along the lines of what you're bringing up, but I'm having difficulty. If it isn't too much trouble, could you elaborate? – Caleb Jay Oct 13 '15 at 18:25
  • @komali_2 See Weather Vane's answer for an example. – Carey Gregory Oct 13 '15 at 21:00

2 Answers2

2

You can technically use strtok but it will modify the request line in place, which may be acceptable, but not in every situation. Here is a generalized solution:

char *method, *target, *version;
const char *p = request_line, *p1;

while (*p != ' ')
{
   p++;
}
method = strndup(request_line, p - request_line);
p1 = ++p;
while (*p != ' ')
{
   p++;
}
target = strndup(p1, p - p1);
p1 = ++p;
while (*p != '\r')
{
   p++;
}
version = strndup(p1, p - p1);

As you expect only well-formatted input, I omitted all error checks.

Phil Krylov
  • 531
  • 4
  • 8
  • What is meant by `const char *p = request_line, *p1;` ? I've never seen that syntax before (comma within a declaration) – Caleb Jay Oct 13 '15 at 20:26
  • @komali_2 That's just two `char *` variables being declared. The first one (`p`) is initialized and the second one (`p1`) isn't. It is kind of confusing syntax, which is why I prefer to make them two separate lines. – Carey Gregory Oct 13 '15 at 20:58
1

This shows how to use the strchr() function you mentioned. I assume there is a single space between each element of the string as you say. I have glossed over a few things, as I don't provide a complete homework answer. One of them is whether the space before the CRLF you show does exist - I assume it does as you show it, but if not, you'll have to deal with that, perhaps by using strcspn() instead of strchr(). The other glosss is to assume a maximum length, in real life you would malloc() (and later free()) the memory required by substring.

#include <stdio.h>   
#include <string.h>   

#define MAXLEN 100

int main(void)
{
    char input[] = "method request-target HTTP-version \r\n";
    char substring[MAXLEN+1];
    char *sptr, *lptr;
    int len;

    lptr = input;                                   // start of search
    while ((sptr = strchr(lptr, ' ')) != NULL) {
        len = sptr - lptr;                          // length of phrase
        if (len > MAXLEN)
            return 0;                               // simple precaution
        memcpy(substring, lptr, len);               // copy the substring
        substring[len] = 0;                         // nul-terminate it
        printf("Substring is '%s'\n", substring);   // tell us what it is
        lptr = sptr + 1;                            // advance to next search
    }
    return 0;
}

Program output:

Substring is 'method'
Substring is 'request-target'
Substring is 'HTTP-version'
Weather Vane
  • 33,872
  • 7
  • 36
  • 56