检查用户提供的值是否为整数,如果不要求提供正确的值

Checking if user-provided value is integer and if not asking for a correct value

我正在寻求有关扫描的用户提供的值的帮助。在我下面的代码中,我想检查每个输入的值是否为整数(ca、ta、dd、gs),如果不是,则将有关它的消息循环到它所在的位置。我看到了一些关于它的旧问题,但无论如何我都无法让它工作。我对编程很陌生,所以我不太了解。我感谢每一个答案。

int ca; // Current altitude
int ta; // Target altitude
int dd; // Distance for descent/climb
int gs; // Ground speed`

char cont; // variable to continue or close program

do
{
    printf("Type your current altitude: ");
    scanf("%i", &ca);

    printf("\nType your target altitude: ");
    scanf("%i", &ta);

    while(ca == ta) // If user entered same target altitude as current one, message will prompt him to type it again
    {
        printf("Target altitude needs to be different than your current one! Type it again: ");
        scanf("%i", &ta);
    }

    printf("\nType distance for descent/climb: ");
    scanf("%i", &dd);

    printf("\nType your ground speed: ");
    scanf("%i", &gs);

    int ad = ta - ca; // Calculates altitude difference - how much feet aircraft needs to descent or climb

    float time = dd*1.0 / gs*1.0; // v = s / t  =>  t = s / v  - Calculates how much time aircraft has to descent or climb (time in hours) | variables are multiplied by 1.0 to receive float in result

    int fpm = ad / (time*60); // Calculates FPM needed to descent in that time | time is multiplied by 60 in order to receive time in minutes

    if(fpm > 0)
    {
       printf("\nAircraft needs to climb at rate of %i FPM (doesn't include capturing altitude)\n", fpm);
    }
    else
    {
        printf("\nAircraft needs to descent at rate of %i FPM (doesn't include capturing altitude)\n", fpm);
    }

    printf("\nDo you want to run a program again? (y/n) ");
    scanf(" %c", &cont);

    while(cont != 'y' && cont != 'Y' && cont != 'n' && cont != 'N') // If user typed different character than y or n, message will prompt him to type it again
    {
        printf("\nType n or y: ");
        scanf(" %c", &cont);
    }

    printf("\n");

}
while(cont == 'Y' || cont == 'y');

return 0;

确保用户的输入确实是一个整数在 C 中是相当棘手的,scanf() 对你帮助不大(即使使用正确,它仍然不会警告你整数溢出,例如)。

一种替代方法是使用 fgets() 读取一行,然后使用 atoi() 解析它,但是当输入行长于最大长度时,fgets() 会让您头疼。此外,atoi() 不会让您知道该数字是否有效(从技术上讲,它确实会发现一些错误,但您无法将它们与 0 区分开来),因此它可能会被替换为 strtol().

因此,这是一种可行的方法:

#include <stdio.h> // printf(), fflush(), fgetc(), EOF
#include <errno.h> // errno
#include <stdlib.h> // EXIT_SUCCESS, EXIT_FAILURE, strtol()

#define MAX_LINE_SIZE 100 // this is the maximum size that a user's input line can be

// FUNCTION: int get_line_and_discard(char[], int);
// this function will help us read a line from `stdin`, and if user's line is longer than `str_size - 1`, the function will discard all user input until '\n'
// this will help us avoid some bugs around the use of `fgets()`
// RETURN VALUE: -1 in case of EOF or other fatal errors, 0 in case user's line is too long or empty, otherwise the line's length
// NOTE: `str` will not contain the newline and will always be NUL-terminated in case return value is >= 0
int get_line_and_discard(char str[], int str_size) {
  if (str_size < 1) {
    return -1;
  }

  int count = 0;

  while (1) {
    int c = fgetc(stdin);

    if (c == EOF) {
      return -1;
    }

    if (c == '\n') {
      str[count] = '[=10=]';
      return count;
    }

    if (count >= str_size - 1) {
      while (1) {
        int temp = fgetc(stdin);
        if (temp == '\n' || temp == EOF) {
          break;
        }
      }
      str[0] = '[=10=]';
      return 0;
    }

    str[count] = (char) c;

    count += 1;
  }
}

// FUNCTION: int get_number_from_user(const char*, long*);
// this function will print `ask_str` and will read a `long` integer from user
// RETURN VALUE: -1 in case of fatal errors (e.g.: EOF), 0 in case number is not valid, 1 in case of success
int get_number_from_user(const char *ask_str, long* result) {
  // print the `ask_str`
  printf("%s", ask_str);
  fflush(stdout);

  char str[MAX_LINE_SIZE];

  // read a line from `stdin`
  int slen = get_line_and_discard(str, MAX_LINE_SIZE);

  // in case of EOF or fatal errors
  if (slen < 0) {
    return -1;
  }

  // in case line is empty
  if (slen < 1) {
    return 0;
  }

  // now let's use `strtol()` to parse the number
  char *str_end;
  errno = 0;
  *result = strtol(str, &str_end, 10);

  // check that `strtol()` has not failed
  if (errno != 0 || str_end != &str[slen] || str == str_end) {
    return 0;
  }

  return 1;
}

这就是您的使用方式:

int main(void) {
  long res;

  // ask the user to input a number until the number is valid
  while (1) {
    int r = get_number_from_user("Insert number: ", &res);

    if (r < 0) {
      printf("ERROR: fatal error\n");
      return EXIT_FAILURE;
    }

    if (r == 0) {
      printf("ERROR: invalid number, please retry.\n");
      continue;
    }

    break;
  }

  printf("You have input: %ld\n", res);

  return EXIT_SUCCESS;
}

I want to check if every entered value is integer

代替printf(...); scanf("%i", ...);,形成辅助函数。

int get_int(const char *prompt) {
  int value = 0;
  for (;;) {
    fputs(prompt, stdout);
    int count = scanf("%i", &value);
    if (count == 1) {
      return value;
    } 
    if (count == EOF) { // No more input
      return 0; // or some other default value.
    } 
    // No numeric input, consume rest of the line
    puts("value is not integer");
    int ch;
    while ((ch = getchar()) != '\n' && ch != EOF) {
      ;
    }
  }
}


....
// printf("Type your current altitude: ");
// scanf("%i", &ca);
ca = get_int("Type your current altitude: ");

// printf("\nType your target altitude: ");
// scanf("%i", &ta);
ta = get_int("Type your target altitude: ");

使用 fgets(), strtol() 可以进行更精细的输入错误检查。

如果您将变量声明为字符串,则可以很容易地做到这一点,然后如果它是正确的,您可以将其更改为整数。

char user_input[100];
scanf("%s", &user_input);
while (!is_int(user_input))
{
    scanf("%s", &user_input);
}
int number = atoi(user_input);

函数:

int is_int(char* user_input)
{
    int i = 0;
    while (user_input[i])
    {
        int num = user_input[i];
        if (!(num >= '0' && num <= '9'))
        {
            return 0;
        }
        i++;
    }
    return 1;
}