c - sscanf 以非常特定的格式使用

标签 c

我尝试将 sscanf 与完全采用以下格式的字符串一起使用:

integer1 integer2

这样我就可以将 int1 和 int2 存储到数组中

我希望 sscanf 检查是否只输入了两个数字,仅用一个空格分隔,并且根本没有前导或尾随空格。 什么应该起作用和不应该起作用的示例:

应该

4 7

不应该

   4 7
4 7[WHITESPACE] 
4    7
4 7a

我一直在尝试按以下方式使用它

sscanf(str,"%d %d",&value1,&value2);

if (*STRING CONTAINS INVALID CHARACTERS OR WHITESPACE*){
    exit from parent function }

最佳答案

第 1 步:读取该行(注意 OP 暗示代码以字符串开头,因此此步骤是说明性的。)

char buf[100];
if (fgets(buf, sizeof buf, stdin) == NULL) Handle_EOF_or_Error();
// strip potential \n
buf[strcspn(buf, "\n")] = '\0';

check if only two numbers are entered separated by only ONE space, with no leading or trailing whitespace at all

第 2 步:按格式扫描。 "%d" 允许前导空格 - 因此代码需要查看数字文本之前的内容。使用 "%n" 存储扫描偏移量以供以后的空白检测。 %*1[ ] 扫描(不保存)1 个且正好 1 个空间。

int i[2];
int sep[3];
int cnt = sscanf(buf, "%n%d%*1[ ]%n%d%n", &sep[0], &i[0], &sep[1], &i[1], &sep[2]);

// 2 int            leading space?        leading space?        \0 ?
if (cnt != 2 || isspace(buf[sep[0]]) || isspace(buf[sep[1]]) || buf[sep[2]]) {
  Handle_Bad_Input();
} else {
  Success();
}

简化想法@Jonathan Leffler

int i[2];
int sep[2];
int cnt = sscanf(buf, "%d%*1[ ]%n%d%n", &i[0], &sep[0], &i[1], &sep[1]);

// 2 int        leading space?     leading space?          \0 ?
if (cnt != 2 || isspace(buf[0]) || isspace(buf[sep[0]]) || buf[sep[1]]) { 

注意:迂腐的代码会将 char 转换为 (unsigned char) 来处理负 char 作为 is...( ) 函数是为 unsigned char 范围和 EOF 定义的。

isspace(buf[...]) --> isspace((unsigned char) buf[...]) 

---

更强大的方法是调用辅助函数来评估整数 - 可以根据代码的需要来制作它。使用 strtol() 是定义性和溢出检测的良好起点。

#include <ctype.h>
#include <errno.h>
#include <limits.h>
#include <stdbool.h>
#include <stdlib.h>

// Return error status
bool scan_int(const char **input, int *dest) {
  errno = 0;
  const char *s = *input;

  if (isspace((unsigned char) *s) {
    // reject leading space
    return true;
  }

  char *endptr;
  long num = strtol(s, &endptr, 10);
  if (s == endptr) {
    // no conversion
    return true;
  }
  *input = (const char *) endptr;
  if (errno == ERANGE) {
    // Overflow
    return true;
  }
#if LONG_MAX > INT_MAX  || LONG_MIN < INT_MIN
  if (num > INT_MAX || num < INT_MIN) {
    errno = ERANGE;
    // Overflow
    return true;
  }
#endif
  *dest = (int) num;
  return false;
}

// Return error status - On success, return false
bool sz_int_space_int(const char *input, int *dest) {
  return scan_int(&input, &dest[0]) || *input++ != ' '
      || scan_int(&input, &dest[1]) || *input;
}

关于c - sscanf 以非常特定的格式使用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45718718/

相关文章:

c++ - 这是如何运作的?

c++ - Visual Studio for C++ 代码中异常的含义是什么

计算中的 C 结构

c - 使用C查找文件权限

c - 数组大小应该在编译时已知

c - 迷宫的结构错误

c - 通过引用 C 传递二维数组并修改值

c - 使用链表结构跟踪 C 程序中可能的内存泄漏

COVER FLOW功能!数字变为负数

c - 不兼容的整数到指针的转换将 'int' 传递给类型为 'const char *' 的参数