C: Как я могу сделать так, чтобы вход scanf () имел один из двух форматов? - PullRequest
0 голосов
/ 28 октября 2018

Мне нужно сделать эту программу, которая берет два треугольника и сравнивает их.

В основном все работает отлично, кроме той части, где пользователь вводит исходные данные.Моя главная проблема заключается в том, что одно из условий заключается в том, что пользователь может ввести либо длины трех сторон треугольников, либо координаты 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;
}

Если я поменяю местами эти два условия, то он переключится, и он будет работать, только если пользователь вводит данные с использованием вершины ...

Можно ли заставить его как-то просто работать какэто?

Ответы [ 2 ]

0 голосов
/ 28 октября 2018

Вы должны использовать 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;
}
0 голосов
/ 28 октября 2018

Гораздо лучше использовать 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
    }
  }
}
...