【问题标题】:C: How can I make it so scanf() input has one of two formats?C:我怎样才能使它的 scanf() 输入具有两种格式之一?
【发布时间】:2019-04-01 17:44:03
【问题描述】:

我需要做这个程序,它需要两个三角形并比较它们。

除了用户输入初始数据的部分外,基本上一切正常。我的主要问题是其中一个条件是用户可以输入三角形三个边的长度或三个顶点的 X、Y 坐标。


我需要它像以下任何一个一样工作:
这个输入意味着用户使用了边的长度:

{ 5 , 5 , 5 }

这个输入意味着用户使用了顶点的 X,Y 坐标:

{ [ 1 ; 1 ] , [ 3 ; 1 ] , [ 2 ; 2 ] }

这是我尝试解决它的代码,但由于某种原因,如果用户使用顶点输入第一个条件,即检查它是否不是边长,一切都会搞砸。

#include <stdio.h>

int main() {
    double a, b, c, A[2], B[2], C[2];
    char s;

    if(scanf(" { [ %lf ; %lf  ] , [ %lf ; %lf  ] , [ %lf ; %lf  ] }%c", 
            &A[0], &A[1], &B[0], &B[1], &C[0], &C[1], &s) != 7 && s != '\n') {
        s = ' ';

        if(scanf(" { %lf , %lf , %lf }%c", &a, &b, &c, &s) != 4 && s != '\n') {
            printf("error\n");
            return 1;
        }

    }

    // rest of the code...

    printf("success\n");
    return 0;
}

如果我交换这两个条件,它就会切换,并且它仅在用户使用顶点输入时才有效......

有没有可能让它像这样简单地工作?

【问题讨论】:

标签: c scanf


【解决方案1】:

最好使用char buf[big_enough * 2]; fgets(buf, sizeof buf, stdin) 读取 然后解析它,也许使用sscanf(buf, " { [ %lf ...sscanf(buf, " { %lf ...


如果代码必须保留在scanf()

OP 的第一个 scanf(" { [ %lf ... 消耗了第二个 scanf( " { %lf ... 中预期的 '{'

改为:

if(scanf(" { [ %lf ; %lf  ] , [ %lf ; %lf  ] , [ %lf ; %lf  ] }%c", 
        &A[0], &A[1], &B[0], &B[1], &C[0], &C[1], &s) != 7 && s != '\n') {
    s = ' ';

    //    no  {
    //        v
    if(scanf(" %lf , %lf , %lf }%c", &a, &b, &c, &s) != 4 && s != '\n') {
        printf("error\n");
        return 1;
    }

}

首选fgets()方式:

// Form a reasonable, yet generous buffer
#define I (50 /* rough estimate of characters use to read a double, adjust as needed */)
//                          { [ 1 ; 1 ] , [ 3 ; 1 ] , [ 2 ; 2 ] }\n\0
#define LINE_SIZE_EXPECTED (4 + I+3+I  +7  +I+3+I  +7  +I+3+I+6)
char buf[LINE_SIZE_EXPECTED * 2]; // Lets us use 2x for extra spaces, leading zeros, etc.

if (fgets(buf, sizeof buf, stdin)) {
  // Consider using "%n" to detect a complete scan and check for no trailing junk
  int n = 0;
  sscanf(buf, " { [ %lf ; %lf  ] , [ %lf ; %lf  ] , [ %lf ; %lf  ] } %n",
      &A[0], &A[1], &B[0], &B[1], &C[0], &C[1], &n);
  if (n && buf[n] == '\0') {
    // successful scan
  } else {
    n = 0;
    sscanf(" { %lf , %lf , %lf } %n", &a, &b, &c, &n);
    if (n && buf[n] == '\0') {
      // successful scan
    } else
      // both scans failed
    }
  }
}

【讨论】:

    【解决方案2】:

    你应该使用sscanf

    关注code 可以工作:

    #include <stdio.h>
    
    int main() {
        double a, b, c, A[2], B[2], C[2];
        char *s = NULL;
        size_t n = 0;
    
        getline(&s, &n, stdin);
    
        if(sscanf(s, " { [ %lf ; %lf  ] , [ %lf ; %lf  ] , [ %lf ; %lf  ] }", &A[0], &A[1], &B[0], &B[1], &C[0], &C[1]) != 6
            && sscanf(s, " { %lf , %lf , %lf }", &a, &b, &c) != 3) {
    
            printf("error\n");
            return 1;
        }
    
        // rest of the code...
    
        printf("success\n");
        return 0;
    }
    

    【讨论】:

    • 您可能需要在两个调用中捕获来自sscanf() 的返回值,以便其余代码知道要查看哪些数据。但是,如果需要,读取一行然后扫描两次是可行的方法。
    • 另外添加一些其他的返回值检查。
    • 只检查 scanf() == 6 中的返回值不会 1) 确保行以 "] }" 结尾,也不会 2) 没有其他意外的尾随文本。
    • 只是一件小事:getline 不是标准 C,它是 POSIX。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-04-23
    • 1970-01-01
    • 1970-01-01
    • 2015-12-23
    相关资源
    最近更新 更多