【问题标题】:Safest way to read a string and store as int in a struct读取字符串并在结构中存储为 int 的最安全方法
【发布时间】:2019-04-25 15:52:48
【问题描述】:

我在 gcc 编译器上使用 ANSI C(使用 -ansi)。

我需要将用户输入的月、日、小时和分钟读入一个结构,他们:

  • 不能是非 int 的数据类型,
  • 每个人都需要符合个人标准(i.e. month > 0 && month < 13 等)

结构定义

typedef struct 
    {
      int month;
      int day;
      int hour;
      int minute;
    } date_time_t;

date_time_t departure_date[50];

使用字符串转换进行类型检查

如果用户向scanf("%i", departure_date-&gt;month); 提供“~”,我想检查用户输入以阻止程序崩溃

所以我首先像这样将值作为字符串读取:

char temp_month[3]
char *ptr;
scanf("%s", temp_month)

然后像这样对用户输入进行类型检查:

当输入不符合条件时 -> 请求符合条件的输入

 while(strtol(temp_month,  &ptr, 36) <  1 ||
        strtol(temp_month,  &ptr, 36) > 12) 
    {

  printf("Invalid selection - try again\n");
    scanf(" %s", temp_month);
  }

一旦满足while条件,我将临时变量存储在结构中:

departure_date-&gt;month = atoi(temp_month);

几个问题...

  1. 这是正常的做事方式吗?请记住,我受限于结构只有 int 数据类型。
  2. 当我在 scanf 期间向月份提交击键“a、b、c 或 d”时,它通过了我在其中进行类型检查的 while 循环设定的标准,但字母表中没有其他字母这样做 - 确实有人知道为什么吗?

【问题讨论】:

  • 您可以阅读 scanf 的手册页 - 1。它返回一个值 2。您可以使用 format 参数来确保字符数组不会溢出。
  • 抱歉我不明白,你能给我举个例子吗?
  • if (scanf("%2s", temp_month) == 1) .... 是你需要的东西

标签: c struct ansi c89


【解决方案1】:
typedef int error;
#define SUCCESS 0
#define FAILURE 1

error readdate(date_time_t *dest)
{
    char line[80];
    if (fgets(line, sizeof line, stdin) == NULL)
        return FAILURE;

    if (sscanf(line, "%d %d %d %d", &(dest->month), &(dest->day), &(dest->hour), 
                       &(dest->minute)) == 4 && dest->month > 0 && dest->month < 13 
                       && dest->day > 0 && dest->day < 32 && dest->hour > -1 && 
                       dest->hour < 25 && dest->minute > 0 && dest->minute > 60)

        return SUCCESS;  /* the return value of sscanf is equal to the number 
                             of objects successfully read in and converted; also we 
                             check the bounds of the input */
    return FAILURE;
}

我们使用fgets,然后是sscanf,而不仅仅是scanf,以避免刷新标准输入流时出现任何问题。

scanf 系列函数返回成功读入并转换为给定数据类型的对象数。

这个函数的主要问题是它没有向调用者报告遇到的错误类型;它仅表示发生了某种错误,或者没有发生错误。

【讨论】:

  • 对不起,进一步检查这实际上并没有编译。你试过编译这个吗?
  • fgets 的参数顺序错误,其余部分在交换时仍然有效。参数是fgets(char* dest, sizeof(dest), stdin)
  • @DavideLorino 已修复
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-11-18
  • 1970-01-01
  • 2015-07-27
相关资源
最近更新 更多