基础:C语言里的printf()与scanf()

将基础理解得最透彻
服务器君一共花费了163.433 ms进行了5次数据库查询,努力地为您提供了这个页面。
试试阅读模式?希望听取您的建议

printf()函数

1. 参数传递

参数传递的机制随实现不同而不同,下面是参数传递在系统中的工作原理。函数调用如下:

printf("%ld %ld %ld %ld",n1,n2,n3,n4);
//设n1为float型 n2为double型 n3,n4为long型

该调用告诉计算机把变量n1,n2,n3,n4的值传递给计算机,计算机把它们放置到被称为对战(stack)的一块内存区域中来实现。计算机根据变量的类型而非转换说明符(%ld)把这些值放置到堆栈中。所以,n1在堆栈中占用8个字节(float被转换成了double)。同样,n2占用8个字节,而n3和n4则分别占用4个字节。让后控制转移到printf()函数。

该函数从堆栈把值都出来,但在读取时,他根据转换说明符去读取。%ld说明符指出,printf()应该读取4个字节,所以printf()在堆栈中读取前4个字节作为他的第一个值。这就是n1的前半部分,他被解释成一个长整数(long integer)。下一个%ld说明符在读取4个字节;这就是n1的前半部分,他被解释成第二个长整型(long integer)。同样,%ld的第三个和第四个实例使得n2的前半部分和后半部分被读出,并被解释成两个长整型(long integer)。所以,虽然n3和n4的说明符都正确,但是printf()仍然读取了错误的字节。

2. printf()的返回值

返回所打印的字符的数目,如果有错误输出,那么printf()会返回一个负数(printf()的一些老版会有不同的返回值)。

应用举例:

#include
main()
{
	int a=100;
	float b=123.255;
	printf("a=%d ",a);
	printf("a=d ",a);
	printf("a=%-10d ",a);
	printf("a=%+d ",a);
	printf("a=% d ",a);
	printf("a=%#o ",a);
	printf("a=%#x ",a);
	printf("b=%#f ",b);
}
/*
运行结果
a=100
a=       100
a=100
a=+100
a= 100
a=0144
a=0x64
b=123.254997  (????)
*/

输出最小宽度:用十进制整数来表示输出的最少位数。(至少要输出这么多位!)若实际位数多于定义的宽度:则按实际位数输出。若实际位数少于定义的宽度:则右对齐,左边留空。有负号,左对齐,右边留空表示宽度的数字以0开始,则右对齐,左边留空。

#include <stdio.h>
main()
{
	int a=3456;
	printf("a=%3d ",a);    //若实际位数多于定义的宽度:则按实际位数输出
	printf("a=d ",a);   //若实际位数少于定义的宽度:则右对齐,左边留空
	printf("a=%-10d ",a);  //若实际位数少于定义的宽度:有负号,左对齐,右边留空
	printf("a=0d ",a);  //若实际位数少于定义的宽度:表示宽度的数字以0开始,则右对齐,左边留空
	printf("a=%-010d ",a); //左对齐,0无意义。
}
/*
运行结果:
a=3456
a=      3456
a=3456
a=0000003456
a=3456
*/

scanf()函数

此函数可以读取各式各样的数据。它把输入的字符串转换成各种形式:整数,浮点数,字符和C的字符串。

1. 使用scanf()函数

scanf()函数使用空格(换行,制表符和空格)来决定怎样把输入分成几个字段。他一次把转换说明与字段相匹配,并跳过他们之间的空格。

例:

int age;
int assets;
scanf("%d %f",&age,&assets);

我们可以分两行进行输入。同样,也可以分一行或5行输入,只要在每个输入项目之间至少键入一个换行符,空格或者制表符。唯一例外的就是%c说明,即使下一个字符是空白字符,它也会读取那个字符。 

2. 从scanf()的角度看输入

我们在仔细地研究scanf怎样读取输入,假设您使用了一个%d说明符来读取一个整数。scanf()函数开始每次读取一个输入字符,它跳过空白字符(空格,制表符和换行符)直到遇到一个非空白字符。因为他试图读取一个整数,所以scanf()期望发现一个数字字符或者一个符号(+或者-)。

如果遇到了一个非数字的字符,他就得出结论:已读到了整数的尾部。scanf()把这个非数字字符放回输入缓冲区。这就意味着当程序下一次开始读取输入时,它将从前面被放弃的那个非数字字符开始。最后,scanf()计算读取到的数字的相应数组,并将该值放到指定的变量中。

如果第一个非空白字符不是数字,将会发生什么呢?比如说,是A而非一个数字?这时scanf()会停在那里,并把A(或者不管什么)放回输入。没有把任何值赋给指定的变量,程序下一次读取输入时,它就在A处重新开始。如果程序中只有%d这个说明符,scanf()永远也不会越过那个A去读下一个。而且,如果您使用带有多个说明符的scanf()语句,ANSI C 要求函数在第一个出错的地方停止读入输入。

如果使用%s说明符,那么空白字符(空格,回车,制表符)以外的所有字符都是可接受的,所以scanf()跳过空白字符直到遇到第一个非空白字符,然后保存再次遇到空白字符之前的所有非空白字符。这就意味着%s 是scanf()读取一个单词,也就是说,一个不包含空白字符的字符串。如果使用字段宽度,scanf()在字段的结尾或者第一个空白字符处停止。不能通过字段宽度使得scanf()用一个%s说明符读取多于一个字的输入。最后一点:当scanf()把字符串放在一个指定的数组中,他添加终止的''使得数组内容成为一个C字符串。

如果使用%c说明符,那么所有的输入字符都是平等的。如果下一个输入字符是一个空格或者换行符,将会把这个空格或者换行符赋给指定的年龄;不会跳过空白字符。

3. scanf()的返回值

返回成功读入的项目的个数。如果他没有读取任何项目(当它期望一个数字而您却键入一个非数字字符串时就会发生这种情况),scanf()会返回值0。当他检测到“文件结尾”是,他返回EOF(EOF是在文件stdio.h中定义的特殊值。一般#define指令把EOF的值定义为-1)。

main() 
{ 
	int i; 
	char *p, str[20]; 
	scanf("%d", &i); 
	scanf("%s", p);          /*从健盘输入字符串*/ 
	scanf("%s", str); 
	printf("i=%d ",i); 
	printf("%s ", p);       /*向屏幕输出字符串*/ 
	printf("%s ", str); 
} 

本文地址:http://www.nowamagic.net/librarys/veda/detail/895,欢迎访问原出处。

不打个分吗?

转载随意,但请带上本文地址:

http://www.nowamagic.net/librarys/veda/detail/895

如果你认为这篇文章值得更多人阅读,欢迎使用下面的分享功能。
小提示:您可以按快捷键 Ctrl + D,或点此 加入收藏

阅读一百本计算机著作吧,少年

很多人觉得自己技术进步很慢,学习效率低,我觉得一个重要原因是看的书少了。多少是多呢?起码得看3、4、5、6米吧。给个具体的数量,那就100本书吧。很多人知识结构不好而且不系统,因为在特定领域有一个足够量的知识量+足够良好的知识结构,系统化以后就足以应对大量未曾遇到过的问题。

奉劝自学者:构建特定领域的知识结构体系的路径中再也没有比学习该专业的专业课程更好的了。如果我的知识结构体系足以囊括面试官的大部分甚至吞并他的知识结构体系的话,读到他言语中的一个词我们就已经知道他要表达什么,我们可以让他坐“上位”毕竟他是面试官,但是在知识结构体系以及心理上我们就居高临下。

所以,阅读一百本计算机著作吧,少年!

《深入理解计算机系统(原书第2版)》 布莱恩特(Randal E.Bryant) (作者), 奥哈拉伦(David R.O'Hallaron) (作者), 龚奕利 (译者), 雷迎春 (译者)

《深入理解计算机系统》从程序员的视角详细阐述计算机系统的本质概念,并展示这些概念如何实实在在地影响应用程序的正确性、性能和实用性。全书共12章,主要内容包括信息的表示和处理、程序的机器级表示、处理器体系结构、优化程序性能、存储器层次结构、链接、异常控制流、虚拟存储器、系统级I/O、网络编程、并发编程等。书中提供子大量的例子和练习题,并给出部分答案,有助于读者加深对正文所述概念和知识的理解。

更多计算机宝库...