验证C中的并集中的整数输入

时间:2016-10-30 16:43:32

标签: c

我正在尝试验证用户输入到union的一个部分实际上是一个整数。我一直在尝试使用isdigit函数(见下文),但我没有成功。我需要做的就是确保用户只输入日期的数字,但我遇到了很多麻烦。

我的代码:

#define STRSIZE 30
#define PROFSIZE 30
#define NBRASSI 2
#define TRUE 1
#define FALSE 0


struct assignment
{
    char name[STRSIZE];
    char prof[PROFSIZE];
    int duedate;
    float value;

};

。 。

struct assignment populate_structure(struct assignment assi[], int assi_nbr)
{
    int count;
    int date_check = FALSE;

for (count = 0; count < assi_nbr; count++)
{
    flushall();
    printf("Enter Assignment #%d name (max %d chars):\n", count + 1,
            STRSIZE);
    gets(assi[count].name);

    while (date_check == FALSE)
    {
        printf("Enter due date for Assignment #%d (YYYYMMDD):\n", 
            count + 1);
        scanf("%d", &assi[count].duedate);
        if (isdigit(assi[count].duedate))
        {
            date_check = TRUE;
        }
        else
        {
            printf("Invalid");
            date_check = FALSE;
        }
    }

    printf("Enter %% of final grade for Assignment #%d:\n", count + 1);
    scanf("%f", &assi[count].value);
    flushall();
    printf("Enter Professor's name for Assignment #%d (max %d chars):\n",
        count + 1, PROFSIZE);
    gets(assi[count].prof);
    printf("\n\n");
}
return assi[count];

}

它在Visual Studio中没有给我任何错误,但是当我运行程序时,只要为assi []输入任何值,我就会出现Abort错误.duedate

如果我删除if(isdigit(assi [count] .duedate)),程序运行正常(只要它们只为duedate输入一个整数)。非常感谢任何帮助。

2 个答案:

答案 0 :(得分:0)

正如评论者已经注意到的那样:isdigit()仅适用于单个字符。另外:您使用scanf()的方式已经确保结果为数字。

但你应该读一个字符串,它更容易测试。例如

#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>

int main(void)
{
  int c;
  int position = 0;
  int res;
  char date[9] = {'\0'};
  char input[20] = {'\0'};

  puts("try if date is in the format \"YYYYMMDD\"");
  res = scanf("%19s",input);
  if(res != 1){
    fprintf(stderr,"input was a mess, aborting\n");
    goto __FAILURE;
  }
  c = input[position];
  while(c != '\0'){
    switch(position){
       case 0:
          if( c == '2' || c == '1' ){
            date[position] = (char) c;
          } else {
            goto __FAILURE;
          }
          break;
       case 1:
          if( c == '9' || c == '0' ){
            // check valid digit by looking back here
            // (not implemented)
            date[position] = (char) c;
          } else {
            goto __FAILURE;
          }
          break;
       case 2:
          if( isdigit(c) ){
            date[position] = (char) c;
          } else {
            goto __FAILURE;
          }
          break;
       case 3:
          if( isdigit(c) ){
            date[position] = (char) c;
          } else {
            goto __FAILURE;
          }
          break;
       case 4: // month
          if( c == '0' || c == '1' ){
            date[position] = (char) c;
          } else {
            goto __FAILURE;
          }
          break;
       case 5: // month
          if( isdigit(c) ){
            // check valid digit by looking back here
            // (not implemented)
            date[position] = (char) c;
          } else {
            goto __FAILURE;
          }
          break;
       case 6: // day
          if( c == '0' || c == '1' || c == '2' || c == '3'){
            date[position] = (char) c;
          } else {
            goto __FAILURE;
          }
          break;
       case 7: // day
          if( isdigit(c)){
            // check valid digit by looking back here
            // (not implemented)
            date[position] = (char) c;
          } else {
            goto __FAILURE;
          }
          break;
       default:
          break;
    }
    c = input[++position];
  }

  printf("Date was correct and is %s\n",date);
  exit(EXIT_SUCCESS);
__FAILURE:
  printf("Date was wrong at position %d with character %c or just too short/long\n",position,c);
  exit(EXIT_FAILURE);
}

填写其余部分(检查日期是否有效并且在正确的范围内)。您还可以将日期分成单独的年/月/日部分,而不是将字符串放入另一个字符串并通过atoi将其转换为数字(您可以使用atoi`,因为您已经确定一个有效的数字)或通过在交换机内手动转换而无需额外的变量和功能。算术检查范围比比较字符串/字符更简单。

答案 1 :(得分:0)

这是我的产品 - 任何无效的条目调用exit(1),但更好的错误处理程序将是首选。数据以字符串形式输入,然后提取和验证。

#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>

typedef struct {
    int year;
    int month;
    int day;
} mydate_t;

int main(void){
    int i;
    mydate_t dat = {0};
    int dayspermon[12] = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
    char str[12];
    printf("Enter a date (YYYYMMDD): ");
    fflush(stdout);
    if(fgets(str, sizeof str, stdin) == NULL) {
        exit(1);
    }
    for(i=0; i<8; i++) {
        if(!isdigit(str[i])) {
            exit(1);                 // also fails when the string is too short
        }
    }

    // extract
    for(i=0; i<4; i++) {
        dat.year = dat.year * 10 + str[i] - '0';
    }
    for(i=4; i<6; i++) {
        dat.month = dat.month * 10 + str[i] - '0';
    }
    for(i=6; i<8; i++) {
        dat.day = dat.day * 10 + str[i] - '0';
    }

    // validate
    if(dat.year < 2000 || dat.year > 3000)    // arbitrary range
        exit(1);
    if(dat.year % 4 == 0 && (dat.year % 100 != 0 || dat.year % 400 == 0)) {
        dayspermon[1]++;                      // leap year adjustment
    }
    if(dat.month < 1 || dat.month > 12)
        exit(1);
    if(dat.day < 1 || dat.day > dayspermon[dat.month - 1])
        exit(1);

    printf("Date: %04d %02d %02d\n", dat.year, dat.month, dat.day);
}