【问题标题】:Reading a string with spaces and special character with sscanf使用 sscanf 读取带有空格和特殊字符的字符串
【发布时间】:2024-01-09 17:22:01
【问题描述】:

对于一个项目,我试图从字符串中读取一个 int 和一个字符串。这里唯一的问题是 sscanf 在看到空格和一些特殊字符时似乎无法读取%s。我只想打印特殊字符中存在的字符串。有没有办法绕过这个限制?这是我正在尝试做的一个示例:

类似于this link,变化不大

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

int main(int argc, char** argv) {
    int age;
    char* buffer;
    buffer = malloc(200 * sizeof(char));
    sscanf("19 cool kid >>> ram <<<", "%d %[^\t\n] >>> %*s <<<", &age, buffer);

    printf("%s is %d years old\n", buffer, age);
    return 0;
}

它打印的是:“cool child >>> ram 我需要 “ram 是 19 岁”。有什么解决办法吗?

注意:有时“coolkid”字符串也会变成“coolkid”。

【问题讨论】:

  • 好吧,您可以尝试从您传递给sscanf 的引用字符串中取出“19”以及&gt;&gt;&gt;&lt;&lt;&lt; 的两个实例来开始。如果你把它们放到字符串中,当你把它打印出来时它们就会在那里。
  • 使用sscanf()吗? strtok() 的一些额外努力会给你更多的灵活性,恕我直言。
  • 当调用 malloc() 1) 表达式:'sizeof(char)' 被定义为 1 并且对传递给 malloc 的值没有影响.. 整理代码删除无用的表达式。 2) 始终检查 (!=NULL) malloc() 的返回值以确保操作成功
  • this: '%[^\t\n]' 不正确,因为源字符串中没有制表符和换行符。

标签: c scanf


【解决方案1】:

你得到了它,你只是把你的弃牌放在了错误的地方(伴随着轻微的大写问题):

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

int main (void) {

    int age;
    char* buffer;
    if (!(buffer = malloc(200 * sizeof *buffer))) {
        fprintf (stderr, "error: virtual memory exhausted.\n");
        return 1;
    }
    sscanf("19 cool kid >>> ram <<<", "%d %*[^>] >>> %s <<<", &age, buffer);

    printf("%s is %d years old\n", buffer, age);

    free (buffer);

    return 0;
}

输出

$ ./bin/sscanf_strange
ram is 19 years old

【讨论】:

    【解决方案2】:

    可以使用sscanf(input, "%d%*[^&gt;]&gt;&gt;&gt;%199s", &amp;age, buffer);%s 之后的任何内容都与扫描 agebuffer 无关。不检查所有扫描是否会导致问题。

    建议检查整行是否按预期解析。简单的解决方案是在最后使用" %n"。如果扫描到那么远,这会节省扫描的char 的计数。

    const char *input =  "19 cool kid >>> ram <<<";
    int n = 0;
    sscanf(input, "%d%[^>]>>>%*199s <<< %n", &age, buffer, &n);
    if (n == 0 || input[n]) {
      puts("Bad Input");
    }
    

    【讨论】:

      【解决方案3】:

      您需要查找不是&gt; 的内容,并且需要禁止对正确位进行分配:

      sscanf("19 cool kid >>> ram <<<", "%d %*[^>] >>> %199s <<<", &age, buffer);
      

      格式中引用的长度比可用字符数少一;换句话说,它不计算终端空字节。

      【讨论】:

      • 原始输入在您感兴趣的位之前有一个 &gt;&gt;&gt; 字符序列。“扫描集”%*[^&gt;] 包含一个“分配抑制”*,然后是否定 (^) 字符集,&gt;。这会查找一个或多个不是&gt; 的字符。在上下文中,它位于19 之后,因此它与字符串" cool kid " 匹配。如果您需要匹配"19 cool kid &gt;&gt;&gt; &gt;&gt;&gt; ram &lt;&lt;&lt;" 中的单词ram,那么您需要更加努力地思考。输入中可能有哪些其他变化?你如何发现要匹配的部分? "19 cool &gt;&gt;&gt; ewe &gt;&gt;&gt; ram &lt;&lt;&lt;" 有效吗?等等。
      最近更新 更多