为什么 strtok() 不选择 '?'来自行的字符?

Why is strtok() not picking the '?' character from line?

下面是我在代码块版本 13:12 中的代码。它没有评论,因为我很快放下它在这里问我失去了我的头发!我担心的是我希望我的 char * 目标是 /cat.html?name=image 但我只得到 /cat.html!

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

int main() {
    const char *space = " ";
    const char *marker = "?";
    const char line[] = { "GET /cat.html?name=image HTTP/1.1" };
    int n = strlen(line), i, j, k, a;
    char string[n + 1];

    for (i = 0; i <= n; i++) {
        string[i] = line[i];
        string[n] = '[=10=]';
    }
    printf(" line has %i characters \n\n", n);
    char *method = strtok(string, space);
    char *target = strtok(NULL, space);
    char *version = strtok(NULL, space);

    char *abs_path = strtok(target, marker);
    char *query = strtok(NULL, marker);

    printf("\n line is:%s \n"
           "\n method is:%s \n"
           "\n target is:%s \n"
           "\n version     is:%s \n"
           "\n abs_path is:%s \n"
           "\n query is:%s \n\n\n",
           line, method, target, version, abs_path, query);

    int l = strlen(target);
    if (strcmp(method, "GET") != 0) {
        printf("wrong method error 405 \n\n");
    }

    printf(" target contains %i characters \n\n", l);
    for (j = 0; j <= l; j++) {
        if (target[0] != '/') {
            printf("wrong target does not start with \/error 501\n\n");
        }
        if (target[j] == '"') {
            printf("wrong target error 400 has a \" \n\n");
        }
    }
    if (strchr(abs_path, '.') == NULL) {
        printf("wrong absolute path has no \. \n\n");
    }
    if (strncmp(version, "HTTP/1.1", 8) != 0) {
        printf("wrong version not HTTP/1.1 error 505 \n\n");
    }
    return 0;
}
char * method = strtok(string, space);
char * target = strtok(NULL, space);
char * version = strtok(NULL, space);

在这些行之后,target 确实具有值 "/cat.html?name=image"。问题是您随后在 target 上再次调用 strtok,这将修改字符串:

abs_path = strtok(target, marker);

在该行之后,target 将具有值 "/cat.html"

如果您想保留 target 的原始值,您需要在第二个 strtok 之前复制它。在 target.

strtok() 修改作为第一个参数传递的缓冲区。在前 3 次调用后,methodtargetversion 要么是 NULL,要么指向 string 数组对应于第一、第二和第三个片段space 分隔部分。

char *method = strtok(string, space);
char *target = strtok(NULL, space);
char *version = strtok(NULL, space);

method 指向 "GET" at string+0, string[3] 已设置为 '[=24=]'
targetstring+4 指向 "/cat.html?name=image"string[24] 设置为 '[=24=]'
versionstring+25 处指向 "HTTP/1.1"

当您在 target 上进一步调用 strtok 时,string 数组将被修改并且 ? 将被 '[=24=]' 覆盖.

char *abs_path = strtok(target, marker);
char *query = strtok(NULL, marker);

abs_path指向"/cat.html"string+4string[13]设置为'[=24=]'
querystring+14 处指向 "name=image"

如果要保留 target 指向的字符串,则必须在对 `strtok() 的第二组调用之前制作一个副本:

char *saved_target = strdup(target);
char *abs_path = strtok(target, marker);
char *query = strtok(NULL, marker);

并在printf中使用它:

    printf("\n line is:%s \n"
           "\n method is:%s \n"
           "\n target is:%s \n"
           "\n version     is:%s \n"
           "\n abs_path is:%s \n"
           "\n query is:%s \n\n\n",
           line, method, saved_target, version, abs_path, query);