将字符串解析为整数并将它们存储在 C 中的数组(范围值)中
Parse the string into integers and store them in array (range values) in C
{s20-s23,s25-s28,s30,s31}
以上是输入的字符串,需要解析并存储到数组中。数组应该如下-
20, 22, 23, 25, 26, 27, 28, 30, 31
即范围内的值也应该被存储(s20-s23,s25-s28)。我试图做同样的事情,但找不到办法。请参考以下程序并建议更改以获得相同的输出。提前致谢。
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
int main(void) {
char *str = "{s20-s23,s30,s31}", *p = str;
int arr[100];
int i = 0;
int flag = 0;
while (*p) {
if (isdigit(*p)) {
int val = strtol(p, &p, 10);
arr[i] = val;
i++;
printf("%ld\n", val);
} else {
p++;
}
}
printf("\n");
for(int j=0; j<i;j++){
printf("%d\n",arr[j]);
}
return 0;
}
以上程序的输出是(缺失范围内的值)
20, 23, 25, 28, 30, 31
您的输入 "{s20-s23,s25-s28,s30,s31}"
是以 {
开头的字符串,后跟零个或多个范围,然后是终止词 }
。每个 range
都是一个 cell
,带有一个可选的 -
,后跟另一个 cell
和一个分隔符 ,
,除非它是最后一个范围。单元格是 s
后跟一个无符号数。这个讨论将是一个非正式的指定语法。然后你只是实现了一个函数来处理每个术语:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
const char *parse_chr(const char *s, char c) {
if(*s != c) return NULL;;
return s + 1;
}
const char *parse_cell(const char *s, unsigned *v) {
s = parse_chr(s, 's');
if(!s) return s;
// assumes values is between 0 and UINT_MAX
*v = strtol(s, (char **) &s, 10);
return s;
}
const char *parse_range(const char *s, unsigned *start, unsigned *end) {
s = parse_cell(s, start);
if(!s) return s;
if(*s != '-') {
*end = *start;
goto out;
}
s = parse_cell(s + 1, end);
if(!s) return s;
out:
return *s == ',' ? s + 1 : s;
}
// assumes v is sufficently large
const char *parse(const char *s, unsigned *n, unsigned *v) {
s = parse_chr(s, '{');
if(!s) return s;
*n = 0;
for(;;) {
if(*s != 's') break;
unsigned start, end;
s = parse_range(s, &start, &end);
if(!s || (start > end)) return s;
for(; start <= end; (*n)++, v++, start++) *v = start;
}
s = parse_chr(s, '}');
return parse_chr(s, '[=10=]');
}
int main() {
unsigned values[100];
unsigned len;
if(!parse("{s20-s23,s25-s28,s30,s31}", &len, values)) {
printf("parse failed\n");
return 1;
}
for(int i = 0; i < len; i++) {
printf("%u%s", values[i], i + 1 < len ? ", " : "\n");
}
return 0;
}
这会产生预期的结果(假设示例输出中缺少的 21 是规范错误):
20, 21, 22, 23, 25, 26, 27, 28, 30, 31
我更喜欢 parser()
returns struct ranges
的数组,然后让另一个函数扩展该列表。 parser()
可能应该采用 max length
所以我们不会向 v
写入太多元素,也许像 snprintf()
允许 v
为 NULL 这样你就可以得到一个计数。另一个不错的选择是让它分配一个数组,如果需要,可以使用 realloc()
来增加数组。改进错误报告也是一个好主意,这样解析就会告诉您失败的位置和原因。
{s20-s23,s25-s28,s30,s31}
以上是输入的字符串,需要解析并存储到数组中。数组应该如下-
20, 22, 23, 25, 26, 27, 28, 30, 31
即范围内的值也应该被存储(s20-s23,s25-s28)。我试图做同样的事情,但找不到办法。请参考以下程序并建议更改以获得相同的输出。提前致谢。
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
int main(void) {
char *str = "{s20-s23,s30,s31}", *p = str;
int arr[100];
int i = 0;
int flag = 0;
while (*p) {
if (isdigit(*p)) {
int val = strtol(p, &p, 10);
arr[i] = val;
i++;
printf("%ld\n", val);
} else {
p++;
}
}
printf("\n");
for(int j=0; j<i;j++){
printf("%d\n",arr[j]);
}
return 0;
}
以上程序的输出是(缺失范围内的值)
20, 23, 25, 28, 30, 31
您的输入 "{s20-s23,s25-s28,s30,s31}"
是以 {
开头的字符串,后跟零个或多个范围,然后是终止词 }
。每个 range
都是一个 cell
,带有一个可选的 -
,后跟另一个 cell
和一个分隔符 ,
,除非它是最后一个范围。单元格是 s
后跟一个无符号数。这个讨论将是一个非正式的指定语法。然后你只是实现了一个函数来处理每个术语:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
const char *parse_chr(const char *s, char c) {
if(*s != c) return NULL;;
return s + 1;
}
const char *parse_cell(const char *s, unsigned *v) {
s = parse_chr(s, 's');
if(!s) return s;
// assumes values is between 0 and UINT_MAX
*v = strtol(s, (char **) &s, 10);
return s;
}
const char *parse_range(const char *s, unsigned *start, unsigned *end) {
s = parse_cell(s, start);
if(!s) return s;
if(*s != '-') {
*end = *start;
goto out;
}
s = parse_cell(s + 1, end);
if(!s) return s;
out:
return *s == ',' ? s + 1 : s;
}
// assumes v is sufficently large
const char *parse(const char *s, unsigned *n, unsigned *v) {
s = parse_chr(s, '{');
if(!s) return s;
*n = 0;
for(;;) {
if(*s != 's') break;
unsigned start, end;
s = parse_range(s, &start, &end);
if(!s || (start > end)) return s;
for(; start <= end; (*n)++, v++, start++) *v = start;
}
s = parse_chr(s, '}');
return parse_chr(s, '[=10=]');
}
int main() {
unsigned values[100];
unsigned len;
if(!parse("{s20-s23,s25-s28,s30,s31}", &len, values)) {
printf("parse failed\n");
return 1;
}
for(int i = 0; i < len; i++) {
printf("%u%s", values[i], i + 1 < len ? ", " : "\n");
}
return 0;
}
这会产生预期的结果(假设示例输出中缺少的 21 是规范错误):
20, 21, 22, 23, 25, 26, 27, 28, 30, 31
我更喜欢 parser()
returns struct ranges
的数组,然后让另一个函数扩展该列表。 parser()
可能应该采用 max length
所以我们不会向 v
写入太多元素,也许像 snprintf()
允许 v
为 NULL 这样你就可以得到一个计数。另一个不错的选择是让它分配一个数组,如果需要,可以使用 realloc()
来增加数组。改进错误报告也是一个好主意,这样解析就会告诉您失败的位置和原因。