1

我正在编写一个通过 wpa_cli 执行 SCAN 和 SCAN_RESULTS 命令并获取 wifi 扫描结果的 C 代码。我在解析 SCAN_RESULTS 输出以捕获某些场景下的密钥管理和 SSID 字段时遇到问题

我用来读取所有参数的代码是

sscanf(buf, "%s \t %s \t %s \t %s \t %[^\n]s", bssid, freq, siglevel, keymgmt, ssid);

wpa_cli SCAN_RESULTS 命令的输出将是

bssid / frequency / signal level / flags / ssid
00:00:00:00:00:00 2462 -49 [WPA2-PSK-CCMP][ESS] MYSSID
11:11:11:11:11:11 2437 -64 [WPA2-PSK-CCMP][ESS] ANOTHERSSID

字段由制表符(\ t)分隔的地方,上面的输出我的代码工作正常。但是当我的扫描结果有一些开放的网络时,我的代码就会中断,我不知道如何更改代码以满足我的要求

开放网络的 wpa_cli SCAN_RESULTS 命令的输出

bssid / frequency / signal level / flags / ssid
00:00:00:00:00:00 2462 -49 [WPA2-PSK-CCMP][ESS] MYSSID
22:22:22:22:22:22 2437 -72  OPENSSID

通过上面的输出,我的代码报告了持有“OPENSSID”的 keymgmt 变量,而 ssid 变量为空。但我想让 keymgmt 变量为空,ssid 来保存“OPENSSID”。当我尝试将上述输出捕获到文件并尝试使用 hexdump 时,我可以看到“信号级别”和“ssid”之间存在两个连续的选项卡(\t\t)。有关如何更改 sscanf 代码以使其工作的任何指示

4

1 回答 1

1

sscanf()格式未按预期工作。

恕我直言,没有一种sscanf()格式可以用""(或跳过它)填充目标字符串,然后用文本填充后续目标字符串。一旦scanf()在目标字符串中找不到任何内容,扫描就会停止。

提供了替代代码。

int ScanTabbedData(const char *s, char *data[], size_t n) {
  size_t i = 0;
  const char *Start = s;
  while (1) {
    if ((*s == '\t') || (*s == '\0')) {
      if (i >= n) {
        return -1;  // More than n data
      }
      size_t Length = s - Start;
      memcpy(data[i], Start, Length);
      data[i][Length] = '\0';
      i++;
      if (*s == '\0') {
        return i;
      }
      s++;
      Start = s;
    }
    else s++;
  }
  return 0;
}

int main() {
  char *str1= "Test\tHope\tHello";
  char *str2 = "Test\t\tHello";
  char *t[3];
  t[0] = malloc(100); t[1] = malloc(100); t[2] = malloc(100);
  int n;
  n = ScanTabbedData(str1, t, 3);
  printf("%d:%s:%s:%s\n", n,t[0], t[1], t[2]);
  n = ScanTabbedData(str2, t, 3);
  printf("%d:%s:%s:%s\n", n,t[0], t[1], t[2]);
}

第二种选择,使用strtok(). 我不确定它是否可以处理\tOP 可能想要的领先/连续。

以下是我的原始答案,不符合 OP 的需要。


**原始答案**

首先,任何的结果都sscanf()应该被评估为

if (3 != sscanf(buf, "%s\t%s\t%[^\n]s", a, b, c)) handle_error();

如果正如 OP 所建议的那样,这些字段确实是\t分开的,请使用

if (3 != sscanf(buf, "%[^\t]%*1[\t]%[^\t]%*1[\t]%[^\n]", a, d, c)) handle_error();

"%[^\t]"扫描直到找到选项卡。
"%*1[\t]" 扫描 1 个选项卡,不保存也不添加到 sscanf() 结果。
"%[^\n]"扫描直到找到行尾。

注意:
为简单起见,使用 3 而不是 OP 的 5 个参数。
sscanf()中," \t "做与 相同的事情" "
"%[^\n]s中,当然s不需要。

于 2013-10-15T21:10:20.757 回答