繁体   English   中英

使用 sscanf 验证字符串输入

[英]Using sscanf to validate a string input

在 Java 和 Python 编码后,我刚刚开始学习 C。

我想知道如何“验证”一个字符串输入(如果它符合某个标准),我偶然发现了sscanf() function。

我的印象是它的行为类似于正则表达式,但是我不太清楚如何用它创建相当复杂的查询。

例如,假设我有以下字符串:

char str[]={"Santa-monica 123"}

我想使用sscanf()检查字符串中是否只有字母、数字和破折号。

有人可以详细说明吗?

sscanf允许看起来有点像字符 class 的事实绝不意味着它完全像正则表达式库。 事实上,Posix 甚至不需要scanf函数来接受字符类中的字符范围,尽管我怀疑它在您将遇到的任何实现上都可以正常工作。

但是您遇到的扫描问题也不需要正则表达式。 您所需要的只是一个重复的字符 class 匹配, sscanf当然可以做到这一点:

#include <stdbool.h>

bool check_string(const char* s) {
  int n = 0;
  sscanf(s, "%*[-a-zA-Z0-9]%n", &n);
  return s[n] == 0;
}

scanf 格式背后的想法是,第一次转换将匹配并丢弃由有效字符组成的最长初始序列。 (如果第一个字符无效,它可能会失败。感谢@chux 指出。)如果成功,它会将n设置为当前扫描点,即下一个字符的偏移量。 如果下一个字符是 NUL,那么所有字符都是好的。 (此版本对空字符串返回 OK,因为它不包含非法字符。如果您希望空字符串失败,请将返回条件更改为return n && s[n] == 0;

您也可以使用标准正则表达式库(或任何更复杂的库,如果您愿意,但 Posix 库通常无需额外工作即可使用)来执行此操作。 这需要更多的代码来编译正则表达式。 为了提高效率,以下尝试只编译一次正则表达式,但为了简单起见,我省略了同步以避免初始化期间的数据竞争,因此不要在多线程应用程序中使用它。

#include <regex.h>
#include <stdbool.h>

bool check_string(const char* s) {
  static regex_t* re_ptr = NULL;
  static regex_t re;
  if (!re_ptr) regcomp((re_ptr = &re), "^[[:alnum:]-]*$", REG_EXTENDED);
  return regexec(re_ptr, s, 0, NULL, 0) == 0;
}

我想使用sscanf()检查字符串中是否只有字母、数字和破折号。

@rici的变化很好的答案。

为字母、数字和破折号创建一个扫描集

//v              The * indicates to scan, but not save the result.
//  v            Dash (or minus sign), best to list first.
"%*[-0-9A-Za-z]"
//      ^^^^^^   Letters a-z, both cases
//   ^^^         Digits  

使用"%n"来检测扫描的距离。

现在我们可以使用确定

  1. 由于null 字符导致扫描停止(整个字符串有效)

  2. 由于无效字符而停止扫描


int n = 0;
sscanf(str, "%*[-0-9A-Za-z]%n", &n);

bool success = (str[n] == '\0');

sscanf没有此功能,您所指的参数是格式说明符,不用于验证。 见这里: https://www.tutorialspoint.com/c_standard_library/c_function_sscanf.htm

正如还提到的sscanf用于不同的工作。 有关更多信息,请参阅此链接 您可以使用isalphaisdigit遍历字符串以检查字符串中的字符是否为数字和字母字符。

    char str[]={"Santa-monica 123"}
    for (int i = 0; str[i] != '\0'; i++)
    {
        if ((!isalpha(str[i])) && (!isdigit(str[i])) && (str[i] != '-'))
            printf("wrong character %c", str[i]);//this will be printed for spaces too
    }

我想...检查字符串中是否只有字母、数字和破折号。

在 C 中,传统上使用isalnum (3) 和朋友完成。

bool valid( const char str[] ) {
  for( const char *p = str; p < str + strlen(str); p++ ) {
    if( ! (isalnum(*p) || *p == '-') )
      return false;
  }
  return true;
}

您也可以使用友好的邻居正则表达式(3),但您会发现需要大量代码才能进行简单扫描。

在 sscanf() 上检索值后,您可以使用正则表达式来验证该值。

请参阅正则表达式ic C

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM