c - sscanf 和 scanset 停止读取十六进制数字
问题描述
我尝试验证 UUID v4。我尝试使用 sscanf 执行此操作,如果可以使用 sscanf 完整读取 UUID(= 读取的字符总数 - 36),我认为这是一个正确的 UUID。到目前为止我的代码:
#include <stdio.h>
int main()
{
char uuid[ 37 ] = "da4dd6a0-5d4c-4dc6-a5e3-559a89aff639";
int a = 0, b = 0, c = 0, d = 0, e = 0, g = 0;
long long int f = 0;
printf( "uuid >%s<, variables read: %d \n", uuid, sscanf( uuid, "%8x-%4x-4%3x-%1x%3x-%12llx%n", &a, &b, &c, &d, &e, &f, &g ) );
printf( " a - %x, b - %x, c - %x, d - %x, e - %x, f - %llx, total number of characters read - %d \n", a, b, c, d, e, f, g );
return 0;
}
返回以下输出
uuid >da4dd6a0-5d4c-4dc6-a5e3-559a89aff639<, variables read: 6
a - da4dd6a0, b - 5d4c, c - dc6, d - a, e - 5e3, f - 559a89aff639, total number of characters read - 36
到目前为止,一切正常。现在我想包括,第三个连字符之后的第一个字符必须是 [89ab] 之一。所以我%1x%3x
改为%1x[89ab]%3x
. 但是现在,第一个字符被读取,其余的不再读取。输出:
uuid >da4dd6a0-5d4c-4dc6-a5e3-559a89aff639<, variables read: 4
a - da4dd6a0, b - 5d4c, c - dc6, d - a, e - 0, f - 0, total number of characters read - 0
我错过了什么?语法有什么问题?可以这样读吗?我尝试了扫描集和说明符的几种组合,但没有任何效果。
解决方案
sscanf()
您可以编写一个简单的专用函数,而不是用于此任务:
#include <ctype.h>
#include <string.h>
int check_UUID(const char *s) {
int i;
for (i = 0; s[i]; i++) {
if (i == 8 || i == 13 || i == 18 || i == 23) {
if (s[i] != '-')
return 0;
} else {
if (!isxdigit((unsigned char)s[i])) {
return 0;
}
}
if (i != 36)
return 0;
// you can add further tests for specific characters:
if (!strchr("89abAB", s[19]))
return 0;
return 1;
}
如果你坚持使用sscanf()
,这里是简洁的实现:
#include <stdio.h>
int check_UUID(const char *s) {
int n = 0;
sscanf(s, "%*8[0-9a-fA-F]-%*4[0-9a-fA-F]-%*4[0-9a-fA-F]-%*4[0-9a-fA-F]-%*12[0-9a-fA-F]%n", &n);
return n == 36 && s[n] == '\0';
}
如果要细化第三个连字符后第一个字符的测试,请添加另一个字符类:
#include <stdio.h>
int check_UUID(const char *s) {
int n = 0;
sscanf(s, "%*8[0-9a-fA-F]-%*4[0-9a-fA-F]-%*4[0-9a-fA-F]-%*1[89ab]%*3[0-9a-fA-F]-%*12[0-9a-fA-F]%n", &n);
return n == 36 && s[n] == '\0';
}
笔记:
*
后面的手段%
不存储转换,只是跳过字符,1
手段最多消耗1
字符。- 要使解析的字符数
sscanf
达到 36,所有十六进制数字序列必须具有完全指定的宽度。 %n
导致scanf
将到目前为止读取的字符数存储到int
下一个参数所指向的值中。- 您的转换规范对于获取实际的 UUID 数字很有用,但
%x
格式接受前导空格、可选符号和可选0x
或0X
前缀,所有这些在 UUID 内都是无效的。您可以先验证 UUID,然后在需要时将其转换为单独的部分。
推荐阅读
- powershell - 找不到 dir /b 的文件路径错误 - 复制所有文件名脚本
- salesforce - 每当文件移动到特定文件夹时,如何使用 talend 自动执行上传过程
- django - Wagtail:向 PageModel 添加方法以获取检查 url
- python - 剪刀石头布,学校作业,python 3.7
- mysql - 如何将 Oracle sql 文件导入 MySQL
- javascript - fullcalendar 后台事件 resourceIds 事件丢失时配置错误
- csv - 如何使用 Proc Transpose 将数据从多行翻转到列?
- python - Python - 将数组中存在的值推送到字典
- javascript - 在具有数组的对象内获取值并与另一个数组进行比较
- python - python的Tkinter packge,如何返回选择的选项?