我有以下输入:
((1828,299),(2729,2553),(2797,2929),(2200,1383),(2894,876))
以及结构:
struct x{
int a;
int b;
}
如何使用scanf()读取输入以创建我的结构数组?
我试过了
scanf("%[^, ()],%d", &arr);
if (i % 2 == 0){
arr[i].x = scanf("%d");
}else
arr[i].y = scanf("%d");
但是当我试图打印这些值时,我得到了一些奇怪的字符
答案 0 :(得分:3)
scanf()
scanf("%[^, ()],%d", ...)
期望扫描并形成字符串("%[^, ()]"
)和int
("%d"
)。代码仅提供用于保存int
。
代码未检查返回值表单scanf()
,因此代码如果不知道任何扫描问题。
如果数据是行,建议使用fgets()
,然后解析它。可以使用strtok() strtol() sscanf()
。每个人的各种利弊。例如:
#include <limits.h>
#include <stdio.h>
#include <stdlib.h>
#define MAXN (5)
// maximum size needed to print and `int`
#define INTSIZE (sizeof (int )* CHAR_BIT / 3 + 3)
// Expect buffer size needed
#define EXPECTEDSIZE (1+(2*INTSIZE + 4) + 3)
void fooo() {
int i;
struct x {
int a;
int b;
} xx[MAXN];
char buf[EXPECTEDSIZE * 2]; // I favor 2x size buffers
while (fgets(buf, sizeof buf, stdin)) {
char *p = buf;
if (*p++ != '(') {
exit(EXIT_FAILURE);
}
for (i = 0; i < MAXN; i++) {
int n; // use %n to locate scan completion
int cnt = sscanf(p, " (%d ,%d ) %n", &xx[i].a, &xx[i].b, &n);
fprintf(stderr, "cnt = %d '%s'\n", cnt, p);
if (cnt != 2) {
exit(EXIT_FAILURE);
}
p += n;
if (p[0] != ',') {
if (p[0] == ')') {
i++;
break; // Successfully reached the end
}
exit(EXIT_FAILURE);
}
p++;
}
int j;
for (j=0; j< i; j++) {
printf("%d (%d ,%d )\n", j, xx[j].a, xx[j].b);
}
}
}
答案 1 :(得分:1)
你得到奇怪字符的原因是scanf()
没有返回扫描值,它返回与格式匹配的项目数。
您正在以调用未定义行为的方式调用scanf()
。当你使用"%d"
说明符时,它期望一个指向整数的指针作为参数,所以正确的方法是
if (scanf("%d", &arr[i].x) == 1)
/* succesful */
else
/* error */
*scanf()
系列函数无法匹配您想要的模式,可以使用正则表达式库,也可以通过拆分(value, value)
然后分别拆分它们的内容来解析字符串。
我想到的一种方法是将strtok()
与"),"
一起使用但不计算最后一个元素,如果")"
之间有空格,则很容易失败和","
所以,状态机和一次解析一个字符的字符串可能是最好的方法。
这是我的意思的一个例子,我喜欢写这个
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
struct point
{
int x;
int y;
};
struct stack
{
char *top;
char **stack;
size_t count;
size_t size;
};
void
stackinit(struct stack *stack)
{
if (stack == NULL)
return;
stack->top = NULL;
stack->stack = NULL;
stack->count = 0;
stack->size = 0;
}
void
stackfinish(struct stack *stack)
{
if (stack == NULL)
return;
free(stack->stack);
stack->stack = NULL;
}
char *
stacktop(struct stack *stack)
{
if ((stack == NULL) || (stack->count == 0))
return NULL;
return stack->stack[stack->count - 1];
}
void
stackpush(struct stack *stack, char *value)
{
void *pointer;
if (stack == NULL)
return;
if (stack->size == stack->count)
{
pointer = realloc(stack->stack, (stack->size + 100) * sizeof(char *));
if (pointer == NULL)
return;
stack->stack = pointer;
stack->size += 100;
}
if (stack->stack == NULL)
return;
stack->stack[stack->count] = value;
stack->count += 1;
}
void
stackpop(struct stack *stack)
{
if ((stack == NULL) || (stack->count <= 0))
return;
stack->count -= 1;
stack->stack[stack->count] = NULL;
}
void
extractpoint(char *string, struct point **points, size_t *count)
{
struct point point;
void *pointer;
char *tail;
if ((string == NULL) || (points == NULL) || (count == NULL))
return;
tail = strchr(string, ')');
if (tail == NULL)
return;
if (sscanf(string, "%d,%d", &point.x, &point.y) != 2)
return;
pointer = realloc(*points, (1 + count[0]) * sizeof(*points));
if (pointer == NULL)
return;
points[0] = pointer;
points[0][count[0]++] = point;
}
void
parse(char *input, struct point **points, size_t *count)
{
struct stack stack;
stackinit(&stack);
while (*(input++) != '\0')
{
char *top;
switch (*input)
{
case '(':
stackpush(&stack, input + 1);
break;
case ')':
stackpop(&stack);
break;
case ',':
top = stacktop(&stack);
if (top == NULL)
continue;
extractpoint(top, points, count);
break;
default:
break;
}
}
stackfinish(&stack);
return;
}
int
main(void)
{
char input[] = "((1828,299),((2729,2553),(2797,2929),(2200,1383),(2894,876))";
size_t count = 0;
struct point *points = NULL;
size_t index = 0;
parse(input, &points, &count);
for (index = 0 ; index < count ; ++index)
fprintf(stdout, "%zu: %d, %d\n", index, points[index].x, points[index].y);
free(points);
return 0;
}
答案 2 :(得分:1)
#include <stdio.h>
#include <stdlib.h>
struct x{
int a;
int b;
};
int count(const char *s){
if(s == NULL || *s != '(')
return 0;//bad
int n, a, b, count = 0;
for(;;){
n = -1;
if(2!=sscanf(++s, "(%d,%d)%n", &a, &b, &n) || n < 0){
return 0;
} else {
s += n;
++count;
if(*s == ',')
continue;
else if(*s == ')')
return count;
else
return 0;
}
}
}
void set(struct x *a, const char *s){
int n, c = 0;
while(2==sscanf(++s, "(%d,%d)%n", &a[c].a, &a[c].b, &n)){
s += n;
++c;
}
}
int main(void) {
char *input = "((1828,299),(2729,2553),(2797,2929),(2200,1383),(2894,876))";
int i, n = count(input);
if(n == 0){
printf("invalid format!\n");
exit(EXIT_FAILURE);
}
struct x arr[n];
set(arr, input);
for(i = 0; i < n; ++i){
printf("(%4d, %4d)\n", arr[i].a, arr[i].b);
}
return 0;;
}