繁体   English   中英

用scanf()从括号中读取逗号分隔的值

[英]read comma separated values from brackets with scanf()

我有以下输入:

((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");

但是当我尝试打印这些值时,我得到了一些奇怪的字符

错误使用scanf()

  1. scanf("%[^, ()],%d", ...)希望扫描并形成字符串( "%[^, ()]" )和int"%d" )。 代码仅用于保存int

  2. 代码没有检查表单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);
    }
  }
}

出现奇怪字符的原因是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;
 }
#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;;
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM