如何仅使用C语言中的sscanf从具有以下格式的字符串中提取所有数字:
“(3,2,4,5,10)”
空格可以无处不在,但数字之间当然不能。 每个位置可以有0个空格或更多。
字符串必须具有正确的格式或其错误。 “(3,2,”例如是错误。 不是空格或格式一部分的每个字符都是错误
仅使用sscanf(它不是可选的)
当然,我的想法是使用sscanf进行while循环,但是格式化是我的问题
编辑:方括号内的数字数量可以不同。因此,方括号内可以有0个数字或n个数字。 n是任何数字。 (a,a + 1,...,a + n)。
EDIT2:当然,它允许使用stdio.h中包含的所有内容,但不能使用扩展库
答案 0 :(得分:3)
似乎数据的格式可以概括为:任意位置的空白;开括号后跟一个或多个以逗号分隔并以小括号终止的纯整数(无符号,无小数点)的序列。另外,(
和)
之间可以有零个整数。
必须使用sscanf()
处理数据;没有关于单个调用sscanf()
的明确规则。与文件I / O替代方法(sscanf()
,scanf()
等相比)相比,使用fscanf()
的优势之一是可以根据需要重试扫描。
请注意,scanf()
系列不能很好地处理“可选项目”。空格大部分都很琐碎-%c
,%[…]
(扫描集)和%n
以外的所有转换说明符都跳过前导空格,并且格式字符串中的空格字符与零个或多个空格匹配输入中的空格字符。
函数string_analyzer()
完成任务;它具有适度复杂的接口,因为它本身不进行I / O操作-它分析字符串并将数字添加到传递给函数的数组结构中。它还会设置一条消息,告诉呼叫者发生了什么问题。其他功能是支持功能(用于struct int_array
类型)和测试工具(main()
加test_string_analyzer()
)。
#include <assert.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
struct int_array
{
char *base;
size_t maxlen;
size_t curlen;
};
static void dump_int_array(const char *tag, const struct int_array *array);
static void add_to_int_array(struct int_array *array, int data);
static void free_int_array(struct int_array *array);
static void test_string_analyzer(const char *str);
static int string_analyzer(const char *str, struct int_array *array, char **msg)
{
int offset;
int length = strlen(str);
int data;
char trailer;
if (sscanf(str, " ( %[)] %n", &trailer, &offset) == 1)
{
/* Empty list */
assert(trailer == ')');
if (offset == length)
{
*msg = "it is an empty list";
return 0;
}
else
{
*msg = "it has extra characters after an empty list";
return -1;
}
}
if (sscanf(str, " ( %d %c%n", &data, &trailer, &offset) != 2 ||
(trailer != ',' && trailer != ')'))
{
*msg = "it does not start correctly";
return -1;
}
add_to_int_array(array, data);
if (trailer == ')' && offset == length)
{
*msg = "it is valid";
return 0;
}
const char *source = str + offset;
while (sscanf(source, "%d %[,)] %n", &data, &trailer, &offset) == 2)
{
add_to_int_array(array, data);
length = strlen(source);
if (trailer == ')' && offset == length)
{
*msg = "it is valid";
return 0;
}
else if (trailer == ')')
{
*msg = "it does not end correctly";
return -1;
}
source += offset;
}
*msg = "it is incorrectly formatted";
return -1;
}
int main(void)
{
const char *samples[] =
{
/* Valid */
" (3, 2, 4,5, 10 )",
" ( 4 , 6 ) ",
"(4)",
"()",
/* random -n 15 10 99 | commalist -t -B 8 -b '"( ' -T ' )",' */
"( 65, 83, 81, 60, 61, 23, 48, 89, 67, 27, 73, 25, 92, 13, 67 )",
/* Invalid */
" (3,2, ",
"3,2",
" (3,2,1) apathy",
" () apathy",
" (3,X,1)",
" (3X,1)",
};
enum { NUM_SAMPLES = sizeof(samples) / sizeof(samples[0]) };
for (int i = 0; i < NUM_SAMPLES; i++)
test_string_analyzer(samples[i]);
return 0;
}
static void test_string_analyzer(const char *str)
{
struct int_array array = { 0, 0, 0 };
char *msg = 0;
printf("Analyzing [%s]\n", str);
int rc = string_analyzer(str, &array, &msg);
if (rc == 0)
printf("String '%s' OK: %s\n", str, msg);
else
printf("String '%s' is misformatted: %s\n", str, msg);
dump_int_array("List contents", &array);
free_int_array(&array);
}
static void dump_int_array(const char *tag, const struct int_array *array)
{
int length = printf("%s (%zu): ", tag, array->curlen);
const char *pad = "";
for (size_t i = 0; i < array->curlen; i++)
{
length += printf("%s%d", pad, array->base[i]);
pad = ", ";
if (length >= 64)
{
pad = " ";
length = 0;
putchar('\n');
}
}
if (length > 0)
putchar('\n');
}
static void add_to_int_array(struct int_array *array, int data)
{
if (array->curlen >= array->maxlen)
{
assert(array->curlen == array->maxlen);
size_t newlen = array->maxlen * 2 + 2;
void *newarr = realloc(array->base, newlen * sizeof(array->base[0]));
if (newarr == NULL)
{
}
array->base = newarr;
array->maxlen = newlen;
}
array->base[array->curlen++] = data;
}
static void free_int_array(struct int_array *array)
{
free(array->base);
array->base = 0;
array->maxlen = 0;
array->curlen = 0;
}
示例输出:
Analyzing [ (3, 2, 4,5, 10 )]
String ' (3, 2, 4,5, 10 )' OK: it is valid
List contents (5): 3, 2, 4, 5, 10
Analyzing [ ( 4 , 6 ) ]
String ' ( 4 , 6 ) ' OK: it is valid
List contents (2): 4, 6
Analyzing [(4)]
String '(4)' OK: it is valid
List contents (1): 4
Analyzing [()]
String '()' OK: it is an empty list
List contents (0):
Analyzing [( 65, 83, 81, 60, 61, 23, 48, 89, 67, 27, 73, 25, 92, 13, 67 )]
String '( 65, 83, 81, 60, 61, 23, 48, 89, 67, 27, 73, 25, 92, 13, 67 )' OK: it is valid
List contents (15): 65, 83, 81, 60, 61, 23, 48, 89, 67, 27, 73, 25
92, 13, 67
Analyzing [ (3,2, ]
String ' (3,2, ' is misformatted: it is incorrectly formatted
List contents (2): 3, 2
Analyzing [3,2]
String '3,2' is misformatted: it does not start correctly
List contents (0):
Analyzing [ (3,2,1) apathy]
String ' (3,2,1) apathy' is misformatted: it does not end correctly
List contents (3): 3, 2, 1
Analyzing [ () apathy]
String ' () apathy' is misformatted: it has extra characters after an empty list
List contents (0):
Analyzing [ (3,X,1)]
String ' (3,X,1)' is misformatted: it is incorrectly formatted
List contents (1): 3
Analyzing [ (3X,1)]
String ' (3X,1)' is misformatted: it does not start correctly
List contents (0):