简体   繁体   English

C中的scanf()中的格式说明符?

[英]format specifiers in scanf( ) in C?

Why do we pass the format specifiers to scanf( ) in C as its parameters? 为什么我们将格式说明符传递给C中的scanf()作为其参数?

I mean, can't we just do 我的意思是,我们不能做

scanf( &var ); // Here, var is any pre-declared variable.

the type of var can be fetched from its declaration. 可以从其声明中获取var的类型。 Why is this not allowed ? 为什么不允许这样做?

I see the below code as a waste of memory. 我认为以下代码浪费了内存。

scanf( "%d" , &var );

The type cannot be "fetched from it's declaration". 该类型不能“从其声明中获取”。 There is nothing magical about scanf() , it's just a function. scanf()并不神奇,它只是一个函数。 A function in C cannot access meta information about variables. C语言中的函数无法访问有关变量的元信息。

This is why, in general, function arguments are declared including their type. 这就是为什么通常声明函数自变量包括其类型的原因。 For variable-argument functions such as scanf() , the first argument is not optional and it is used to describe the number and type of the other arguments in some fashion chosen by the function itself. 对于诸如scanf()可变参数函数,第一个参数不是可选的,它用于以函数本身选择的某种方式描述其他参数的数量和类型。

You clearly need to read some book on C programming to get better understanding of the core concepts. 您显然需要阅读一些有关C编程的书,以更好地理解核心概念。 Unlike some other languages, C doesn't have I/O mechanism baked into the language. 与其他一些语言不同,C语言没有将I / O机制引入该语言。 scanf() is just a library function and as such, this function has no way to automagically know the type of the variable it is supposed to fill. scanf()只是一个库函数,因此,该函数无法自动知道应该填充的变量的类型。

Because %d will simply specify what the type of var is, there is no memory wastage. 因为%d只会指定var的类型,所以不会浪费内存。 scanf(&var) would not work because the function is not designed to accept arguments that way. scanf(&var)无法正常工作,因为该函数并非旨在以这种方式接受参数。

You know that variables in C can be of different types: 您知道C中的变量可以具有不同的类型:

  • int: Integer int:整数
  • char: Character char:字符
  • float: Floating point number. float:浮点数。
  • ... ...

Unlike other languages, variable types cannot be implicitly inferred at compilation time in C. That is why you always declare the type of your variables ( Example: int a or char c). 与其他语言不同,在C语言中不能在编译时隐式地推断变量类型。这就是为什么总是声明变量类型的原因(示例:int a或char c)。

Because scanf is just a function in C, and because functions in C should take parameters of a specific type, people who coded C decided to use the following format: 因为scanf只是C语言中的一个函数,并且因为C语言中的函数应采用特定类型的参数,所以对C语言进行编码的人员决定使用以下格式:

     scanf("%d", &var) ; // for integers
     scanf("%c", &var); //for chars
     scanf("%f", &var); //for double and floats.

using %d or %c does not waste memory or whatsoever. 使用%d或%c不会浪费内存或其他任何资源。 you can think about it as a flag that specifies the type of the input variable. 您可以将其视为指定输入变量类型的标志。

Could the developers of C do it without %d, %c...etc? C的开发人员可以在没有%d,%c ... etc的情况下做到吗? Yes they could, but then, they have to handle all possible exceptions that might arise from sending the wrong type. 是的,他们可以,但是然后,他们必须处理由于发送错误的类型而引起的所有可能的异常。

Suppose the developers of C used just the following format 假设C的开发人员仅使用以下格式

    scanf(&var);

That is surly very concise, but then you will have to use the same syntax to send chars/int/double...etc, and then the function scanf has to figure out a way to decide about the type of the variable that was sent. 这非常简洁,但是随后您将必须使用相同的语法来发送chars / int / double ... etc,然后函数scanf必须找出一种方法来确定所发送变量的类型。 Remember what I told you before? 还记得我以前说过的话吗? variable types CANNOT be implicitly inferred at compilation time, and thus, this task will be almost impossible. 不能在编译时隐式地推断变量类型,因此,该任务几乎是不可能的。

They could however use a different scanf function for every type. 但是,他们可以为每种类型使用不同的scanf函数。 For example: 例如:

    scanfInt(&var);     //for integers.
    scanfFloat(&var);   //for floats.
    ...
    ...

That would work perfectly, but it makes less sense to replicate the same code of scanf and use different functions just because the type is different. 那会完美地工作,但是复制相同的scanf代码并使用不同的功能(因为类型不同)就没有多大意义了。

So what is the solution? 那么解决方案是什么? ==> Use the same function name ( scanf ), and then add a parameter (%d, %f, %c..) that will be used internally as a flag by C to know the parameter type. ==>使用相同的函数名称(scanf),然后添加参数(%d,%f,%c ..),C会在内部将其用作标志以了解参数类型。

I hope now you have a better understanding of the use of %d, %f.... 我希望您现在对%d,%f的用法有了更好的了解。

There are two major points you are missing here. 您在这里缺少两个要点。

First, we humans sitting at the keyboard will write something like: 首先,我们坐在键盘旁的人会写类似以下内容:

char var = '0';

And we know that the "type" of this variable is char and we probably intend to store a character there. 而且我们知道此变量的“类型”是char ,我们可能打算在其中存储一个字符。 Once the compiler gets a hold of this it removes these "human" elements all that is left is at some memory location there is 1 byte reserved, further references to places in the code where we wrote "var" will interact with this memory location. 一旦编译器掌握了这一点,它将删除这些“人为”元素,所有剩下的都是保留在某个内存位置,保留了1个字节,对我们编写“ var”的代码位置的进一步引用将与此内存位置进行交互。 That is all the compiler knows, there is no understanding of the intended variable "type". 那是编译器所知道的,对预期的变量“类型”没有任何了解。

Second, the format specificers do so much more than just indicate a simple type. 其次,格式规范者所做的不仅仅只是指示简单的类型。 Look at any page explaining scanf() and you'll see a long list, take special note of things like scan sets, negated scan sets, and expected input lengths. 查看任何解释scanf()页面,您会看到一个长长的列表,特别注意诸如扫描集,否定扫描集和预期输入长度之类的内容。

Let's say I want the user to enter just a single digit, 0-9, well I don't have to just assume they will do as I ask, I can help ensure they will by using the format specifiers in scanf(): 假设我希望用户只输入一个数字0-9,那么我不必只是假设他们会按照我的要求做,我可以通过使用scanf()中的格式说明符来帮助确保他们将:

int var = 0;
print("enter 1 digit (0-9):\n");
scanf("%1d", &var);

Now, no matter how many digits they enter, I'll only have stored the first one. 现在,无论输入多少位,我都只会存储第一个数字。

What if you have a string that you want to read from the user, and you want to read everything up until you hit a new line character (read over spaces). 如果您有一个要从用户中读取的字符串,并且想一直读取所有内容,直到遇到新的换行符(读取空格),该怎么办。 We'll there are a number of options for this, but scanf can do it too. 我们将为此提供多种选择,但是scanf也可以做到这一点。 The "standard" to read a string is: 读取字符串的“标准”是:

scanf("%s",some_string);

But that will stop at any whitespace character, so you wouldn't want scanf() to make an assumption in this case, you'd want to be able to use a specific negated scanset: 但这将停止在任何空格字符处,因此在这种情况下,您不希望scanf()做出假设,您希望能够使用特定的否定扫描集:

scanf("%[^\n]",some_string);

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM