gpt4 book ai didi

c - scanf 格式说明符,用于从一组字符中读取零个或多个字符

转载 作者:太空狗 更新时间:2023-10-29 15:04:17 25 4
gpt4 key购买 nike

对于读取字符串中可以包含的字符,我需要非常严格。

我有一系列空格,后面跟着一个字符,后面跟着一系列空格。
示例:"c""c"""""

我需要找到一个允许我忽略字符的格式说明符,但前提是它是这个特定字符而不是任何其他字符。此序列 "e " 应该被中止。

我尝试了 "%*[c] " 但我的单元测试在某些情况下失败了 - 让我相信 "%*[c] " 正在寻找一个或多个 'c' 而不是零个或多个 'c'

我写了一个小例子来帮助更好地说明我的问题。请记住,这只是一个最小的示例。核心问题是我如何解析一个零或一个字符的数量。

#include <stdio.h>
#include <string.h>

unsigned match(const char * formula){
unsigned e = 0, found = 0, s;
char del;
int parsed, pos, len = (int) strlen(formula);
const size_t soc = sizeof( char );
del = ' ';
parsed = sscanf_s( formula, " \" %*[(] X%*[^>]>> %u %*[)] %c %n", &s, &del, soc, &pos );// (X >> s )
if( ( 2 == parsed ) && ( pos == len) && ( '"' == del ) ){
printf("%6s:%s\n", "OK", formula);
}else{
printf("%6s:%s\n", "FAIL", formula);
e += 1;
}
return e;
}

unsigned main( void )
{
unsigned e = 0;

printf("SHOULD BE OK\n");
e += match(" \"X >> 3\""); //This one does not feature the optional characters
e += match(" \"( X >> 3 ) \"");
e += match(" \"( X >> 3 ) \"\r");

printf("SHOULD FAIL\n");
if ( 0 == match(" \"( Y >> 3 ) \"") ) e += 1;
if ( 0 == match(" \"g X >> 3 ) \"") ) e += 1;
if ( 0 == match(" \"( X >> 3.3-4.2 ) \"") ) e += 1;

if( 0 != e ){ printf( "ERRORS: %2u\n", e ); }
else{ printf( "all pass\n", e ); }
return e;
}

最佳答案

正如其他人向您指出的那样,使用 sscanf不建议为此目的。它无法捕获的情况是“可选”(这可能会或可能不会出现在 " 之间和 X .与 scanf ,如果有一个可选字段没有任何类型的分隔符来指示它丢失,那么确定它丢失的唯一方法是尝试解析它,注意它不存在,然后尝试再次解析它不同的扫描格式字符串。

parsed = sscanf( formula, " \" %*[(] X%*[^>]>> %u %*[)] %c %n", &s, &del, &pos );
if (parsed != 2) {
parsed = sscanf( formula, " \" X%*[^>]>> %u %c %n", &s, &del, &pos );
}

此解决方案的其余部分描述了如何使用 POSIX <regex.h>解析它的基本正则表达式。

首先,您需要定义正则表达式并编译它。

const char *re =
"[ \t]*\"" /* match up to '"' */
"[ \t]*(\\{0,1\\}[ \t]*" /* match '(' if present */
"X[ \t]*>>[ \t]*" /* match 'X >>' */
"\\([0-9][0-9]*\\)" /* match number as subexpression */
"[ \t]*)\\{0,1\\}[ \t]*" /* match ')' if present */
"\\(.\\)" /* match final delimiter as subexpression */
"[ \t\r\n]*"; /* match trailing whitespace */
regex_t reg;
int r = regcomp(&reg, re, 0);
if (r != 0) {
char buf[256];
regerror(r, &reg, buf, sizeof(buf));
fprintf(stderr, "regcomp: %s\n", buf);
/*...*/
}

现在,您需要针对要匹配的字符串执行表达式。编译器将跟踪正则表达式中子表达式的数量,并将该数字放入 reg.re_nsub 中。 .但是,有一个隐式子表达式不包括在该计数中。这是与提供的表达式匹配的完整字符串。这总是出现在第一场比赛中。因此,当您创建匹配数组时,请考虑到这一点。这就是为什么 matches array 比 reg.re_nsub 中的多 1 .

unsigned match(const regex_t *preg, const char * formula){
/*...*/
int r;
const int NSUB = preg->re_nsub + 1;
regmatch_t matches[NSUB];

r = regexec(preg, formula, NSUB, matches, 0);
if (r == 0) {
/* success */
parsed = preg->re_nsub;
s = atoi(formula + matches[1].rm_so);
del = formula[matches[2].rm_so];
pos = matches[0].rm_eo;
} else {
parsed = 0;
}
/*...*/

当你用完正则表达式后,你应该释放它(如果它被成功编译)。

regfree(&reg);

关于c - scanf 格式说明符,用于从一组字符中读取零个或多个字符,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16719469/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com