【问题标题】:Can't seem to get sscanf() to work the way I want似乎无法让 sscanf() 以我想要的方式工作
【发布时间】:2012-12-05 15:19:26
【问题描述】:

我正在为我正在制作的程序使用 AT 命令,但无法使用 sscanf() 函数解析它们。

例如,如果我执行以下命令:

"AT\r\r\nOK\r\n"

我想: * 在第一次调用时,只获取“AT”部分,扔掉后面的“\r”字符并知道到目前为止已经读取了多少个字符。 * 在第二次调用中,只获取“OK”部分,丢弃“OK”字符串前后的“\r\n”字符,并知道到目前为止已经读取了多少个字符。

我写了以下 sscanf 函数调用:

index = 0;
sscanf(buffer + index, "%*[\r\n]%[^\r]\r%*[\n]%n", new_buffer, &count);
index += count;

为什么它不返回我请求的字符串?我做错了什么?

提前感谢您的帮助。

【问题讨论】:

    标签: c scanf


    【解决方案1】:

    也许问题在于sscanf 如何处理空格字符,例如回车和换行符,以及您的期望。 sscanf 需要忽略(跳过)前面的空格。

    另一个问题可能是回车永远不会到达您的缓冲区。需要 C 实现将 \r\n 映射到 \n 输入(用于文本流)。

    【讨论】:

    • 首先,我要感谢 Jens 的帮助。我不认为 sscanf() 对待回车或换行符与任何普通字符不同。此外,正如我在上面写的那样,内容会进入缓冲区(我在阅读您的回复后检查了缓冲区的内容)。想知道它还能是什么。我传递给函数的令牌似乎没问题,对吧?
    【解决方案2】:

    我们来分析一下格式:

    sscanf(buffer + index, "%*[\r\n]%[^\r]\r%*[\n]%n", new_buffer, &count);
    

    首先,跳过'\r''\n' 字符的初始序列 (%*[\r\n])。然后扫描到下一个'\r' 之前的以下字符并将其存储到new_buffer (%[^\r]) 中。

    接下来,将跳过所有后续的空白字符 (\r)。到"OK"'O' 之前的部分已经用完了。

    然后,直到下一个换行符之前的所有字符都将被忽略 (%*[^\n])。您现在只剩下最后一个未使用的换行符。然后将消耗的字符数存储在count中。

    您的问题是格式字符串中的任何空白(当然是字符集之外的)都会占用该位置出现的空白字符的整个序列(可能为空)。格式字符串中的\r不是“一个字符'\r'”的意思,而是“这里全是空格”的意思。

    您可以通过使其扫描(并忽略)任何字符(如果您的输入确实符合您的期望,则在您的情况下保证为'\r')来修复它(如果您的格式是严格的)。

    sscanf(buffer + index, "%*[\r\n]%[^\r]%*c%*[\n]%n", new_buffer, &count);
    

    【讨论】:

    • 感谢丹尼尔的帮助。我不同意你写的一些东西。我同意你写的第一段。但是,在第二段中,我认为 (\r) 不会使函数跳过所有后续的空白字符。它只是让它跳过一个 \r 字符。这就像写: sscanf(buffer,"%*[^:]:",只会让它跳过一个 ':' 字符,而不是所有字符。然后我添加了 (%*[^\n]) 部分因为有些命令行以“\r”结尾,有些以“\r\n”结尾,我想跳过这两个。
    • 问题是令牌末尾的 %n 将 0 放入计数中,并且根本没有将任何内容读入 new_buffer。
    • 好的,我再次测试了它,我同意你所说的。它确实对待 '\r' 字符与 ':' 字符不同。问题是,我该如何解决?例如,在此文本中:“AT\r\r\nOK\r\n”我希望它第一次读取“AT\r”,第二次读取“\r\nOK\r\n”。如何将 '\r' 与其后面的 '\r\n' 分开?
    • 这取决于你到底想要什么和给予什么。假设输入缓冲区正好包含"AT\r\r\nOK\r\n"。如果您希望存储“AT”并且使用但不存储以下'\r',则忽略一个字符 - %*c - 就可以了。如果您想存储"AT\r",则字段宽度可以为您提供。但是,如果您想对第二次扫描使用完全相同的格式字符串,那将是有问题的。如果您的要求足够复杂,编写自己的解析函数可能比获得sscanf 的正确格式更容易。您的具体要求是什么?
    • 我正在尝试创建一个通用函数,将初始和最终的“\r\n”从行中删除,然后只存储中间部分,在这种情况下,AT 在第一行,在第二个确定。问题是有时可能有初始的“\r\n”字符,有时可能没有(就像在 AT 情况下)。有时该行可能仅以“\r”结尾,有时以“\r\n”结尾。如何使解析器适用于每一行?对于不同的处理器,我确实构建了自己的解析器,但是那个处理器“较弱”,所以我不想用 sscanf 函数重载它。 PS:再次感谢您的帮助。
    猜你喜欢
    • 2014-07-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-11-29
    • 1970-01-01
    • 1970-01-01
    • 2021-04-12
    • 2011-11-30
    相关资源
    最近更新 更多