为什么我们将格式说明符传递给C中的scanf()作为参数?
我的意思是,我们不能只做
scanf( &var ); // Here, var is any pre-declared variable.
可以从其声明中获取var的类型。为什么不允许这样做?
我认为以下代码浪费了内存。
scanf( "%d" , &var );
答案 0 :(得分:3)
该类型不能从其声明"中获取。 scanf()
没有什么神奇的东西,它只是一个功能。 C中的函数无法访问有关变量的元信息。
这就是为什么一般来说,声明函数参数包括它们的类型。对于scanf()
之类的变量参数函数,第一个参数不是可选的,它用于以函数本身选择的某种方式描述其他参数的数量和类型。
答案 1 :(得分:2)
您显然需要阅读一些关于C编程的书籍,以便更好地理解核心概念。与其他一些语言不同,C并没有将I / O机制融入语言。 scanf()
只是一个库函数,因此,这个函数无法自动知道它应该填充的变量的类型。
答案 2 :(得分:2)
因为%d
只会指定var
的类型,所以没有内存浪费。 scanf(&var)
不起作用,因为该函数不是设计为以这种方式接受参数。
答案 3 :(得分:2)
你知道C中的变量可以是不同的类型:
与其他语言不同,C语言编译时无法隐式推断变量类型。这就是为什么总是声明变量的类型(例如:int a或char c)。
因为scanf只是C中的一个函数,并且因为C中的函数应该采用特定类型的参数,所以编码C的人决定使用以下格式:
scanf("%d", &var) ; // for integers
scanf("%c", &var); //for chars
scanf("%f", &var); //for double and floats.
使用%d或%c不会浪费内存或任何内容。您可以将其视为指定输入变量类型的标志。
C的开发人员可以在没有%d,%c等的情况下做到这一点吗?是的,他们可以,但是,他们必须处理发送错误类型可能引起的所有可能的异常。
假设C的开发人员使用以下格式
scanf(&var);
这非常简洁,但是你必须使用相同的语法来发送chars / int / double ...等等,然后函数scanf必须找出一种方法来决定变量的类型那是发送的。还记得我之前告诉过你的吗?变量类型不能在编译时隐式推断,因此,这项任务几乎是不可能的。
然而,他们可以为每种类型使用不同的scanf函数。例如: scanfInt(&var); //for integers.
scanfFloat(&var); //for floats.
...
...
这样可以完美地工作,但是复制相同的scanf代码并使用不同的函数没有意义,因为类型不同。
那么解决方案是什么? ==>使用相同的函数名称(scanf),然后添加一个参数(%d,%f,%c ..),该参数将在内部用作C的标志以了解参数类型。
我希望你现在对%d,%f ....
的使用有了更好的理解答案 4 :(得分:2)
这里有两个主要观点。
首先,我们坐在键盘上的人会写出类似的东西:
char var = '0';
我们知道这个变量的“类型”是char
,我们可能打算在那里存储一个字符。一旦编译器获得了这一点,就会删除这些“人”元素,剩下的就是在某个内存位置保留1个字节,对代码中我们编写“var”的地方的进一步引用将与此内存位置进行交互。这就是所有编译器都知道的,没有理解预期的变量“type”。
其次,格式指定者不仅仅指示一个简单的类型。查看解释scanf()
的任何页面,您将看到一个长列表,特别注意扫描集,否定扫描集和预期输入长度等内容。
假设我希望用户只输入一个数字,0-9,我不必只是假设他们将按照我的要求进行操作,我可以帮助确保他们将通过使用scanf()中的格式说明符:
int var = 0;
print("enter 1 digit (0-9):\n");
scanf("%1d", &var);
现在,无论他们输入多少位数,我都只会存储第一个数字。
如果您想要从用户那里读取一个字符串,并且想要阅读所有内容,直到您点击一个新行字符(读取空格),该怎么办?我们有很多选择,但scanf也可以这样做。读取字符串的“标准”是:
scanf("%s",some_string);
但是这会停留在任何空白字符上,所以你不希望scanf()
在这种情况下做出假设,你希望能够使用特定的否定扫描集:
scanf("%[^\n]",some_string);