在do-while

时间:2016-06-05 20:20:43

标签: c

如果我在C中有一段时间或做while循环,是否有一些(本机)方式我可以在第二个循环中发生某些事情?

我要求获得投入;我有这个:

int size;
do {
        printf("Size of tower (0 <= x <= 23): ");
        scanf("%i", &size);
} while (size > 23 || size < 0);

如果用户输入的值不在0到23之间,我想显示错误信息并要求另一个值。显然我可以这样做:

int size;
int error = 0;
do {
        if (error) { printf("Invalid size\n"); }
        printf("Size of tower (0 <= x <= 23): ");
        scanf("%i", &size);
        error = 1;
} while (size > 23 || size < 0);

然而,这感觉很糟糕。我正在寻找一个优雅的解决方案,我认为在第二个循环上运行某些东西会起作用。

3 个答案:

答案 0 :(得分:4)

我想你想要这样的东西:

int size = -1;
int MAX_TRIES = 10;
while (MAX_TRIES--)
{
  printf("Size of tower (0 <= x < 23): ");
  if (scanf("%i", &size) != 1)
  {
    printf("Read error!!\n");
    break;
  }

  if (size >= 0 && size < 23)
  {
    break;
  }

  printf("Error: You entered '%d' which is not in the range 0 <= x < 23\n", size);
}

通过这种方式编写,在编写代码时,您不必在心理上计算布尔条件逻辑的否定。
此外,检查scanf()的返回值很重要。感谢 Weather Vane's comment提醒您 此外,最好限制此循环的执行次数,而不是让它运行到无穷大。 (感谢Jonathan Leffler's comment

答案 1 :(得分:1)

转换和错误报告可以移动到一个函数来简化调用代码。输入由fgets获取,值由strtol在函数中解析。此函数返回成功或失败。其他值通过指针返回给调用者。

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <errno.h>
#include <limits.h>

int get_int_range ( char *line, char **next, char *delim, int *value, int min, int max);//prototype

int main( int argc, char *argv[])
{
    char line[100] = {'\0'};//input buffer
    int valid = 0;
    int size = 0;

    do {
        printf ( "Size of tower (0 <= x <= 23) or quit\n");
        fgets ( line, sizeof ( line), stdin);//read a line
        if ( strcmp ( line, "quit\n") == 0) {
            valid = 0;
            break;// if quit is entered, exit loop
        }
        valid = get_int_range ( line, NULL, "\n", &size, 0, 23);// call to parse a value
    } while ( !valid);// on failure, keep looping the above

    if ( valid) {
        printf ( "Size of tower is %d\n", size);
    }

    return 0;
}

//inputs
// char *line : pointer to text to be parsed
// char **next : pointer to pointer to allow modification of caller's pointer
// char *term : pointer to characters to be considered terminators
// int *value : pointer to int to allow modification of caller's int
// int min : minimum value of range
// int max : maximum value of range
// returns : 0 failure or 1 success
int get_int_range ( char *line, char **next, char *delim, int *value, int min, int max)
{
    long int input = 0;
    char *end = NULL;//will point to end of parsed value

    if ( line == NULL) {
        printf ( "no text to parse\n");
        return 0;
    }
    if ( value == NULL) {
        printf ( "unable to save parsed value\n");
        return 0;
    }
    errno = 0;
    input = strtol ( line, &end, 10);//get the integer from the line. end will point to the end of the parsed value
    if ( ( errno == ERANGE && ( input == LONG_MAX || input == LONG_MIN))
    || ( errno != 0 && input == 0)){// parsing error from strtol
        perror ( "input");
        return 0;
    }
    if ( end == line) {// nothing was parsed. no digits
        line[strcspn ( line, "\n")] = '\0';//remove newline
        printf ( "input [%s] MUST be a number\n", line);
        return 0;// return failure
    }
    // *end is the character that end points to
    if ( *end != '\0' && !( delim && strchr ( delim, *end))) {// is *end '\0'? is *end in the set of term characters?
        line[strcspn ( line, "\n")] = '\0';//remove newline
        printf ( "problem with input terminator: [%s] \n", line);
        return 0;
    }
    if ( input < min || input > max) {// parsed value is outside of range
        printf ( "input out of range %d to %d\n", min, max);
        return 0;
    }

    if ( next != NULL) {// if next is NULL, caller did not want pointer to end of parsed value
        *next = end;// *next allows modification to caller's pointer
    }
    *value = input;// *value allows modification to callers int
    return 1;// success
}

答案 2 :(得分:0)

我首选的技术是复制输入,但会简化你的循环:

printf("Size of tower (0 <= x <= 23): ");      // Try to get good input once.
scanf("%i", &size);

while (size < 0 || 23 < size ) {               // While the user is wrong:
    printf("Invalid size\n");           
    printf("Size of tower (0 <= x <= 23): ");  // Try, try again.
    scanf("%i", &size);
}