如何使scanf选择性地忽略其转换说明符之一? [英] How to make that scanf is optionally ignoring one of its conversion specifiers?

查看:60
本文介绍了如何使scanf选择性地忽略其转换说明符之一?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

char value1[10];
int value2;
int value3 = 0;
if (!scanf("%s %d %d", &value1[0], &value2, &value3)) {
    scanf("%s %d", &value1[0], &value2);
}
;

我正在尝试使用 scanf 插入3个值,但是如果接收到2个值,它将取2个值.我找不到如何使用 scanf 的答案.我一直在尝试使用 fgets ,但stdin中的值仍然存在.

I am trying to use scanf to insert 3 values, but if received 2 it will take in 2 instead. I'm not able to find any answer how to use scanf. I've been trying to use fgets but value in stdin remains.

推荐答案

scanf("%s %d %d", &value1[0], &value2, &value3)

问题是 scanf()不能忽略第三个转换说明符.它仍然不断尝试捕获第三个参数 value3 的十进制输入.

The problem is scanf() can´t ignore the third conversion specifier. It still keeps trying to catch the decimal input for the third argument, value3.

首先捕获整个输入为字符串,然后再将该字符串的内容拆分为每个对象,可能是更好的选择.

To catching the whole input as string first and then later split the content of this string into each own object may be a better alternative.

fgets() scanf()更安全,所以我将使用 fgets()./p>

fgets() is a litte more safer than scanf() when taking user input so I´ll use fgets().

char* fgets ( char * str, int num, FILE * stream );

使用 fgets(),您需要定义要读取的字符数( num ),这是维护安全性的重要功能,但是在这种情况下,我们无需不知道用户可能会为十进制输入请求输入什么作为整数.如果我们为数字指定的字符较少,其余数字将保留在 stdin 中.

With fgets() you need to define the amount of characters to read (num), which is a great feature for maintaining security, but in this case we don´t know what a user potentially will input as integer for the decimal input requests. If we specify to less characters for the digits, the rest digits will be left in stdin.

一种解决方法是指定对 fgets()的调用中用十进制表示形式表示 int 类型整数的位数的总数.

A workaround would be to specify the total amount of digits possible for representing integers of type int in decimal notation in the call to fgets().

在64位体系结构上,总数"2,147,483,647"将为10位,在32位体系结构上则为"32,767"总数的5位.我现在使用64位的情况.

These would be 10 digits for the total number of "2,147,483,647" on 64-bit architectures or 5 digits for the total number of "32,767" on 32-bit architectures. I go with the 64-bit case for now.

所以 10 (value1)+ 10 (value2)+ 10 (value3)+ 2 空格字符在value1和value2之间以及在value2和value3之间+字符串的终止 \ 0 = 33 个字符.请注意, fgets()还会读取输入的换行符 \ n (但稍后我们会轻松地从字符串中删除该换行符),因此我们甚至还需要一个字符.总共 34 个字符:

So 10 (value1) + 10 (value2) + 10 (value3) + 2space characters between value1 and value2 and between value2 and value3 + the terminating \0 for a string = 33 characters. Note that fgets() also reads the entered newline \n (but we later discard that from the string easily) so we need even one character more; it is in total 34 characters:

char buffer[34];
fgets(buffer,sizeof(buffer),stdin);

此后,我们需要证明存储在 buffer 中的字符串中有多少内容.我们可以通过计算空格字符来隐式证明这一点:

After that we need to proof how many content we have in the string stored in buffer. We can proof it implicitly by counting the space characters:

unsigned int mark;

for(unsigned int i = 0; i < (sizeof(buffer)/sizeof(buffer[0]) - 1)); i++)
{
   if(buffer[i] == ' ')
     mark++;
}

此后,我们需要使用 sscanf() buffer 中的字符串内的各个内容片段传输/转换为适当的自己的对象.如果字符串中现在有2个空格字符,则可以在 sscanf 命令中使用3个转换说明符,否则我们有相应的 sscanf() s:

Thereafter we need to transfer/convert the individual content pieces inside the string in buffer to the appropriate own objects by using sscanf(). If we now have 2 space characters in the string, we can use 3 conversion specifiers in a sscanf command, else we have appropriate sscanf()s:

if(mark == 2)
{
    sscanf(buffer,"%s %d %d", value1, &value2, &value3);
}
   else if(mark == 1)
   {
      sscanf(buffer,"%s %d", value1, &value2);
   }
      else if(mark == 0)
      {
         sscanf(buffer,"%s", value1);
      }
         else
         {
            printf("The input entered is not valid!\n");
            printf("Please try again!\n");
         }

那么整个代码就是:

#include <stdio.h>
#include <string.h>

int main()
{
    char value1[10];
    int value2;
    int value3;
    unsigned int mark;
    char buffer[34];

    for(;;)
    {
       fgets(buffer,sizeof(buffer),stdin);
       buffer[strcspn(buffer, "\n")] = 0;

       mark = 0;

       for(unsigned int i = 0; i < ((sizeof(buffer)/sizeof(buffer[0]) - 1)); i++)
       {
          if(buffer[i] == ' ')
          mark++;
       }

       if(mark == 2)
       {
          sscanf(buffer,"%s %d %d", value1, &value2, &value3);
          break;
       }
          else if(mark == 1)
          {
             sscanf(buffer,"%s %d", value1, &value2);
             break;
          }
             else if(mark == 0)
             {
                sscanf(buffer,"%s", value1);
                break;
             }
                else
                {
                   printf("The input entered is not valid!\n");
                   printf("Please try again!\n");
                }
    }

    printf("value1 = %s\n", value1);

    if(mark == 1 || mark == 2)
    printf("value2 = %d\n", value2);

    if(mark == 2)
    printf("value3 = %d\n", value3);

    return 0;
}

这篇关于如何使scanf选择性地忽略其转换说明符之一?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆