简体   繁体   English

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

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

I have the following input: 我有以下输入:

((1828,299),(2729,2553),(2797,2929),(2200,1383),(2894,876))

and following struct: 和以下结构:

struct x{
int a;
int b;
}

How can I read the input with scanf() to create an array of my structs? 如何使用scanf()读取输入以创建结构数组?

I have tried 我努力了

scanf("%[^, ()],%d", &arr);
    if (i % 2 == 0){
        arr[i].x = scanf("%d");
    }else
        arr[i].y = scanf("%d");

But when I tried to print these values out I got some strange characters 但是当我尝试打印这些值时,我得到了一些奇怪的字符

Incorrect use of scanf() 错误使用scanf()

  1. scanf("%[^, ()],%d", ...) expects to scan and form a string ( "%[^, ()]" ) and an int ( "%d" ). scanf("%[^, ()],%d", ...)希望扫描并形成字符串( "%[^, ()]" )和int"%d" )。 Code only provided for a place to save the int . 代码仅用于保存int

  2. Code did not check the return value form scanf() , so code if not aware of any scanning issues. 代码没有检查表单scanf()的返回值,因此如果不知道任何扫描问题,则代码。

When data is a line , recommend to use fgets() , then parse it. 当数据为一行时 ,建议使用fgets()然后对其进行解析。 Could use strtok() strtol() sscanf() . 可以使用strtok() strtol() sscanf() Various pros/cons to each. 每个都有各种优点/缺点。 Example: 例:

#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);
    }
  }
}

The reason you got strange characters is that scanf() does not return the scanned value, it returns the number of items that matched the format. 出现奇怪字符的原因是scanf()不返回扫描的值,它返回与格式匹配的项目数。

You are invoking scanf() in a way that invokes undefined behavior. 您正在以调用未定义行为的方式调用scanf() It expects a pointer to an integer as a parameter when you use the "%d" specifier, so the correct way would be 当您使用"%d"说明符时,它期望指向整数的指针作为参数,因此正确的方法是

if (scanf("%d", &arr[i].x) == 1)
    /* succesful */
else
    /* error */

The *scanf() family of functions, are not capable of matching the pattern you want, either use a regular expressions library, or parse the string by splitting the (value, value) and then their contents separately. *scanf()系列函数不能使用所需的模式,请使用正则表达式库,或者通过分别拆分(value, value)和它们的内容来解析字符串。

One way that comes to my mind is to use strtok() with ")," but that wouldn't count the last element and would easily fail if there is a white space between the ")" and "," so, a state machine and parsing the string one character at a time might be the best way to do it. 我想到的一种方法是将strtok()"),"一起使用"),"但这不会计算最后一个元素,并且如果")"","之间有空格,则很容易失败。机器并一次解析一个字符的字符串可能是最好的方法。

This is an example of what I mean, I enjoyed writing this 这是我的意思的一个例子,我很喜欢写这篇

#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