【问题标题】:How to get sscanf to start scanning after \r\n\r\n in C?如何让 sscanf 在 C 中 \r\n\r\n 之后开始扫描?
【发布时间】:2015-11-18 03:28:44
【问题描述】:

我正在用 C 语言编写一个 HTTP 客户端/服务器,我想将内容(不是 http 标头)读入一个字符串。因为标题中的最后一件事是 \r\n\r\n 序列,所以我需要告诉 sccanf 跳过所有内容直到 \r\n\r\n,然后从 \r\n 之后的第一个字符串开始扫描\r\n 。我从来没有真正理解复杂的 printf 和 scanf 格式描述符,每次我尝试阅读文档时,我都会很快感到困惑。我最好的尝试是sscanf(str, [^\r\n\r\n]%s, mystr);,但它不起作用。

【问题讨论】:

  • 试试这个 -> sscanf(str, %*[\r\n\r\n]%s, mystr);.
  • 第一部分使用 strtok(str,"\r\n\r\n"),第二部分使用 strtok(NULL,"\r\n\r\n")跨度>
  • 不要使用scanf()/sscanf()。它们几乎从不合适,而且在大多数情况下,还有很多更明智的选择。对于标记化,有strtok_r()

标签: c scanf


【解决方案1】:

scanf 的语法与 printf 的语法几乎相同。因此,您要使用的是:

sscanf(str, "%s\r\n\r\n%s", dummystr, mystr);

当然,您需要分配足够大的 dummystr 和 mystr 以避免缓冲区溢出(strlen(str) 都可以)。

【讨论】:

  • "\r\n\r\n" 匹配 0 个或更多空格。不是解决方案。
【解决方案2】:

类似这样的:

#include <stdio.h>

int main()
{
   char const* testString = "abcd\r\n\r\nthe rest";
   char str[20] = {};
   sscanf(testString, "%*[^\r\n]%*[\r]%*[\n]%*[\r]%*[\n]%[^\n]", str);
   printf("%s\n", str);
}

输出:

the rest

格式字符串说明:

"%*[^\r\n]%*[\r]%*[\n]%*[\r]%*[\n]%[^\n]" 
 |<-   ->| Read and discard everything that is not a \n or \r

"%*[^\r\n]%*[\r]%*[\n]%*[\r]%*[\n]%[^\n]" 
          |<-->| Read and discard the first \r

"%*[^\r\n]%*[\r]%*[\n]%*[\r]%*[\n]%[^\n]" 
                |<-->| Read and discard the first \n

"%*[^\r\n]%*[\r]%*[\n]%*[\r]%*[\n]%[^\n]" 
                      |<-->| Read and discard the second \r

"%*[^\r\n]%*[\r]%*[\n]%*[\r]%*[\n]%[^\n]" 
                            |<-->| Read and discard the second \n

"%*[^\r\n]%*[\r]%*[\n]%*[\r]%*[\n]%[^\n]" 
                                  |<-->| Read and save all the characters until the next \n

【讨论】:

  • 注意:%*[^\r\n]%*[\r]%*[\n]%*[\r]%*[\n]%[^\n]" 会失败 "abc\r\r\n\r\nthe rest",但应该会通过。
  • @chux,我的理解是期望的序列正好是"\r\n\r\n",而不是由'\r''\n' 组成的四个标记的任意组合。这不正确吗?
  • 字符串"abc\r\r\n\r\nthe rest" 中有一个精确的"\r\n\r\n"。同意 OP 不清楚 可能 存在于字符串中。
  • 我的意思是 "\r\n\r\n"。 "\r\n\r\n" 就是那个确切的字符串,内容就是我想要的
  • @glen4096 挑战在于&lt;anything&gt; 后面可以跟"\r\r\n\r\n",这意味着配对"\r\r" 中的第一个'\r' 应该被忽略,因为它实际上是&lt;anything&gt; 的一部分.剩下的 4 个char 匹配该模式。这是模式的重新开始,一旦代码部分匹配,它就是挑战。一切尽在您的掌控中。
【解决方案3】:

也许使用状态机的另一种方法

const char *rnrn(const char *s) {
  const char *pat = "\r\n\r\n";
  int ch;
  int i = 0;
  while (i<4) {
    ch = *s++;
    if (ch == '\0') return NULL;
    if (ch == pat[i]) i++;
    else if (ch == pat[0]) i = 1;
    else i = 0;
  }
  // Success ....
  return s;
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-06-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-09-26
    相关资源
    最近更新 更多