【问题标题】:How to retrieve the telephone number from an AT CMGL response?如何从 AT CMGL 响应中检索电话号码?
【发布时间】:2010-11-21 15:31:26
【问题描述】:

我有一个用 C 语言编写的应用程序,它使用 AT 命令从调制解调器读取文本消息。来自调制解调器的典型 AT 响应如下所示:

+CMGL: 1,"REC READ","+31612123738",,"08/12/22,11:37:52+04"

该代码当前设置为仅从该行检索 id,这是第一个数字,它使用以下代码这样做:

sscanf(line, "+CMGL: %d,", &entry);

这里,“line”是一个字符数组,包含来自调制解调器的一行,“entry”是一个整数,其中存储了 id。我试着像这样扩展这段代码:

sscanf(line, "+CMGL: %d,\"%*s\",\"%s\",", &entry, phonenr);

我想我会使用 %*s 扫描第一对引号中的文本并跳过它,然后将下一对引号(电话号码)中的文本读入 phonenr 字符数组。

这不起作用(%*s 显然读取“REC”而下一个 %s 没有读取任何内容)。

一个额外的挑战是文本不限于“REC READ”,它实际上可以是很多东西,也是一个文本没有其中的空格。

【问题讨论】:

  • 也许您应该考虑编写自己的文本解析器?
  • 为您的特定需求量身定制。
  • 很抱歉之前无意重新标记了 quamrana,我认为我的浏览器发脾气了。

标签: c modem at-command scanf


【解决方案1】:

Sscanf 对解析不是很好,不如使用 strchr。没有错误处理:

#include <stdio.h>

int main(void)
{

        const char *CGML_text = "+CMGL: 1,\"REC READ\",\"+31612123738\",,\"08/12/22,11:37:52+04\"";
        char *comma, *phone_number_start, *phone_number_end;
        comma = strchr(CGML_text, ',');
        comma = strchr(comma + 1, ',');
        phone_number_start = comma + 2;
        phone_number_end = strchr(phone_number_start, '"') - 1;
        printf("Phone number is '%.*s'\n", phone_number_end + 1 - phone_number_start, phone_number_start);
        return 0;
}

(更新了经过测试的工作代码)

【讨论】:

  • Strchr 听起来是一个很好的解决方案,我也考虑过。但是,由于我不确定第一对引号之间的文本类型,我也无法预测它是否会有逗号,这会搞砸这个例程。可以扩展它来处理这种情况,但是我还必须考虑很多额外的异常情况。
  • 关于字符串中可能的逗号非常好,但是如果您在3gpp.org/ftp/Specs/html-info/27005.htm 中查找 AT+CMGL 命令的 定义,您会发现所有可能的值都没有 (" REC UNREAD”、“REC READ”、“STO UNSENT”、“STO SENT”、“ALL”)。
  • 感谢 hlovdal。我有我正在使用的调制解调器的数据表,尽管这些值被列为 AT+CMGL= 命令的可能输入,但它没有提供返回的 +CMGL 命令的可能值列表。我知道你在这个领域有一些经验。您会推荐自己的解决方案,还是我在答案中发布的解决方案? :)
  • 我强烈建议不要将 sscanf 用于任何事情。真的。搜索“sscanf crash”并查看所有返回的页面。 “GNU C 编程教程” (crasseux.com/books/ctutorial/index.html) 说:“sscanf 函数就像已弃用的父 scanf 函数一样,...。由于多种原因,scanf 函数被认为是危险的。”。请不要使用它。
  • 是的,我对 AT 命令有所了解(上周我刚刚共同编辑了 27.007 的变更请求)。关于参数解析,我还可以补充一点,保证字符串永远不会在内部包含 " 字符(即 " 被转义,但不是 \" 这在其他地方很常见),请参阅 V.250 中的“5.4.2.2 字符串常量”一章(itu.int/rec/T-REC-V.250-200307-I/en)。这意味着解析参数的安全和正确算法是在数字参数之间以逗号分隔,而对于字符串参数,您可以通过搜索终止符来推进。
【解决方案2】:

我现在解决的方法是使用以下代码:

sscanf(line, "+CMGL: %d,\"%*[^\"]\",\"%[^\"]", &entry, phonenr);

这将首先扫描一个数字 (%d),然后是一个非双引号的任意字符串(并跳过它们,因为有星号),对于电话号码也是如此。

但是,我还不确定这有多强大。

【讨论】:

    【解决方案3】:

    您可以使用 strchr() 查找字符串中“+”的位置,并提取其后的电话号码。您也可以尝试使用 strtok() 将字符串与 '"' 分开,并分析第 3 部分。

    【讨论】:

    • 绝对不能保证电话号码将包含“+”字符,因此这听起来不是一个可靠的建议。
    • 感谢您的建议,但实际上我已经遇到了电话号码中没有 + char 的情况。例如,从 Google 日历发送的短信来自“Google”,而不是数字。
    【解决方案4】:

    scanf() 中的%s 一直读取到空格。

    您已经非常接近解决方案了。

    阅读本文;

    +CMGL: 1,"REC READ"

    你需要;

    "+CMGL: %d,"%*s %*s"

    【讨论】:

    • 这是我首先考虑的事情之一,但这实际上并没有像我预期的那样工作,也无法让它发挥作用。
    • 但是,对于不包含空格的 值“ALL”,这将失败。
    猜你喜欢
    • 2011-05-14
    • 1970-01-01
    • 2012-05-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-09-26
    相关资源
    最近更新 更多