服用newline后,未终止scanf()或get()

发布于 2025-02-07 18:57:49 字数 675 浏览 2 评论 0原文

我必须在一个字符串中进行三个输入。
要接受输入的代码是:

char msg_send[1000];
gets(msg_send);

输入就像

GET /api HTTP/1.1  

id=1&name=phoenix&[email protected]

这意味着拳头行之后有一个newline get/api http/1.1。下一行是一个空的新线。输入功能应在获得第三个新线后终止。

另外,如果该行在的位置上没有/api Word,我必须在第一行get/http/1.1之后终止输入。 /某物 word。

但是,当我使用get get()时,它在服用get/api http/1.1一部分输入后终止字符串。使用SCANF时,它仅在第一个get Word中终止。有什么方法可以将输入作为一个字符串?

I have to take three inputs in a single string.
The code to take the input is:

char msg_send[1000];
gets(msg_send);

The input is like

GET /api HTTP/1.1  

id=1&name=phoenix&[email protected]

That means there is a newline after the fist line GET /api HTTP/1.1. The next line is an empty newline. The input taking function should terminate after taking the 3rd newline.

Also, I have to terminate the input after the first line GET /something HTTP/1.1 if the line doesn't have a /api word at the place of /something word.

But when I'm using gets(), it terminates the string after taking GET /api HTTP/1.1 part of the input. When using scanf, it terminates after taking only the first GET word. Is there any way to take the input as a single string?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

廻憶裏菂餘溫 2025-02-14 18:57:49

file *中读取应使用fgets(),而不是get> get> get> get> get()无法安全使用。适当的URL的测试应严格:strstr(msg_send,“/api”)不够:get/sosings/sosings/api将匹配。将请求与get/api http/1.1进行比较,或者可能省略/1.1似乎更安全。

这是一个修改版本:

// read the HTTP request, return the number of lines
int get_http_request(FILE *fp, char *buf, size_t size) {
    char line2[100];
    char line3[4096];

    *buf = '\0';
    if (!fgets(buf, size, fp))
        return 0;  // fp at end of file

    if (strncmp(buf, "GET /api HTTP/", 14))
        return 1;  // not the proper protocol or URL

    size_len = strlen(buf);
    if (!fgets(buf + len, size - len, fp))
        return 1;  // missing blank line

    size_len += strlen(buf + len);
    if (!fgets(buf + len, size - len, fp))
        return 2;  // missing contents

    return 3;  // 3 lines were read
}

Reading from the FILE * should be done with fgets(), not gets() which cannot be used safely. Testing for the proper URL should be strict: strstr(msg_send, "/api") is not sufficient: GET /something/api will match. Comparing the request to GET /api HTTP/1.1 or possibly omitting the /1.1 seems safer.

Here is a modified version:

// read the HTTP request, return the number of lines
int get_http_request(FILE *fp, char *buf, size_t size) {
    char line2[100];
    char line3[4096];

    *buf = '\0';
    if (!fgets(buf, size, fp))
        return 0;  // fp at end of file

    if (strncmp(buf, "GET /api HTTP/", 14))
        return 1;  // not the proper protocol or URL

    size_len = strlen(buf);
    if (!fgets(buf + len, size - len, fp))
        return 1;  // missing blank line

    size_len += strlen(buf + len);
    if (!fgets(buf + len, size - len, fp))
        return 2;  // missing contents

    return 3;  // 3 lines were read
}
嗳卜坏 2025-02-14 18:57:49

在这种情况下,您应该只在循环中使用getchar:

#define MAX_MSG_BUF 1000

char char msg_send[MAX_MSG_BUF];    

// you should wrap the below code in a function, like get3lines(buf, buf_size)
unsigned index = 0;
unsigned line_count = 0; 
const unsigned buf_size = MAX_MSG_BUF;
do {
    int tmp = getchar();
    if (tmp < 0) break; // end of file or error
    msg_send[index++] = tmp;
    if (tmp == '\n') {
        ++line_count;
        if (line_count == 1) {
            // check that first line contains /api                
            if (!first_line_valid(msg_send, index)) break;
        }
    }
} while (index < (MAX_MSG_BUF-1) && line_count < 3;
msg_send[index] = '\0';
// print error if line_count < 3 ?

first_line_valid函数可能看起来像这样(注意:需要#include&lt; stdbool.h&gt; for bool类型):

bool starts_with(const char *str, size_t length, const char *prefix) {
    size_t i = 0;
    for(;;) {            
        if (i == length || prefix[i] == '\0') return true;
        if (str[i] != prefix[i]) return false; // does catch end of str
        ++i;
     }
}

bool first_line_valid(const char *buf, size_t buf_size) {
    // note: buf might not be NUL-terminated so use buf_size
    if (starts_with(buf, buf_size, "GET /api ")) return true;
    if (starts_with(buf, buf_size, "GET /api/")) return true;
    return false;
}

In cases like these, you should just use getchar in a loop:

#define MAX_MSG_BUF 1000

char char msg_send[MAX_MSG_BUF];    

// you should wrap the below code in a function, like get3lines(buf, buf_size)
unsigned index = 0;
unsigned line_count = 0; 
const unsigned buf_size = MAX_MSG_BUF;
do {
    int tmp = getchar();
    if (tmp < 0) break; // end of file or error
    msg_send[index++] = tmp;
    if (tmp == '\n') {
        ++line_count;
        if (line_count == 1) {
            // check that first line contains /api                
            if (!first_line_valid(msg_send, index)) break;
        }
    }
} while (index < (MAX_MSG_BUF-1) && line_count < 3;
msg_send[index] = '\0';
// print error if line_count < 3 ?

The first_line_valid function might look like this (note: needs #include <stdbool.h> for bool type):

bool starts_with(const char *str, size_t length, const char *prefix) {
    size_t i = 0;
    for(;;) {            
        if (i == length || prefix[i] == '\0') return true;
        if (str[i] != prefix[i]) return false; // does catch end of str
        ++i;
     }
}

bool first_line_valid(const char *buf, size_t buf_size) {
    // note: buf might not be NUL-terminated so use buf_size
    if (starts_with(buf, buf_size, "GET /api ")) return true;
    if (starts_with(buf, buf_size, "GET /api/")) return true;
    return false;
}
菩提树下叶撕阳。 2025-02-14 18:57:49

因此,我想出了答案。
答案是,如果命令中的/api,我应该使用条件。
该代码就像:

char msg_send[1000], blank[4], data[300];
fgets(msg_send, 1000, stdin);
        char *header = strstr(msg_send, "/api");

        if (header)
        {
            fgets(blank, 4, stdin);
            fgets(data, 300, stdin);
            strcat(msg_send, " ");
            strcat(msg_send, data);
        }

我应该将第一部分作为字符串作为字符串,然后判断它是否具有/api。如果不包含,则输入应结束。感谢大家的有用意见。

So, I figured out the answer.
The answer is I should use a condition if there is /api in the command.
The code is like:

char msg_send[1000], blank[4], data[300];
fgets(msg_send, 1000, stdin);
        char *header = strstr(msg_send, "/api");

        if (header)
        {
            fgets(blank, 4, stdin);
            fgets(data, 300, stdin);
            strcat(msg_send, " ");
            strcat(msg_send, data);
        }

I should take the first part as a string and then judge if it has the word /api. If it doesn't contain, the input taking should end. Thanks to everyone for your useful opinions.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文