第四章 字符串和输入输出
1、char数组类型和空字符:
字符串在内存中是char数组,数组是一组相邻内存单元组成。
2、空字符:
字符串在数组中存储的最后是一个空字符:\0,空字符用来标记字符串的结束,是非打印字符。也就是说实际存储的内存比字符串要多一个空字符。
3、printf(“what is your name\n”);
scanf(“%s”, name);
请注意这是很重要的:scanf()在读取了zhang wei 的名字zhang。scanf()开始读取输入以后,会在遇到的第一个空白字符空格(blank)、制表符(tab)或者换行符(newline)处停止读取。因为它在遇到一个非数字的字符,它就得出结论,已经读到了整数的结尾。所以它在遇到zhang和wei之间的空格就停止了扫描。一般情况下,使用%s的scanf()只会把一个单词而不是把整个语句作为字符串读入。
4、字符串“x”和字符‘x’的区别:
字符串“x”是由x和\0组成的字符串,而‘x’是一个字符。
5、strlen()函数和sizeof语句:
Sizeof运算符以字节为单位给出数据的大小,strlen()函数则是以字符为单位给出字符串的长度(不包括表示终止的空字符)。因为一个字符只占用一个字节。
Sizeof对于类型来说圆括号是必须的,而对于具体量则是可选的,例如:sizeof(int),sizeof(float),但是sizeof name或者sizeof 6.28都可不需要括号。最好的办法就是都带着括号。
6、C语言预处理器:
#define NAME value//#define PI 3.14159265,不用分号结尾,也不用赋值号=,而且一般像这样的常量都是大写,这是C的一个良好的传统,C预处理器是个极其有用的工具,所以在可能的时候要尽量利用它。
7、printf()和scanf()的研究和利用:
%d: Printf(“%xd\n”);
# include<stdio.h>
# define PAGES 931
int main(void)
{
printf("*%1d*\n", PAGES);
printf("*%5d*\n", PAGES);
printf("*%10d*\n", PAGES);
printf("*%-10d*\n", PAGES);
printf("*%-5d*\n", PAGES);
printf("*%-1d*\n", PAGES);
return 0;
}
上面的运行结果是:
*931*
* 931*
* 931*
*931 *
*931 *
*931*
Press any key tocontinue
其中x = 1,5,10,-10,-5,-1,对应的效果是产生一个有1、5、10、10、5、1个空格那么宽的字段,当前面没有-号时是右对齐的方式显示,当有-号时是左对齐方式显示。
8、%f:Printf(“%xf\n”); %e:Printf(“%xf\n”);
%f有两个默认项目:字段宽度和小数点右边的数字的数目,小数点右边数字的数目木人是6个数字,字段宽度就是容纳数字所有的空间。
例如:%+/-m.nf(%+/-6.4f):前面的6代表的是输出的数字总共占几个空格,如果输出的比6位要多(比如1234.567),则按最多7位输出,如果输出的比6位少(比如12.34),则按照正负号左右对齐,如果是+,则是右对齐输出,如果是-号,则是右对齐输出。后面的4代表的是浮点数精确到4位有效数字,不够4位在后面补0。
%e在小数点的左侧打印一个数字,在小数点的右侧打印6个数字。我们得到一堆数字,解决方法是指定小数点右侧小数位的数目。
9、%m.ns(%+/-24.5s)
前面的m代表的依然是空m个字符,这里是总共空出24个字符,后面的n代表的是输出打印几个字符,这里是打印5个字符,如果超出5个字符,则打印前5个字符,如果不够,当然是全输出了。如果是负号则表示输出的时候左对齐,如果是正号,则表示输出时候是右对齐。
10、为什么有时候会出现打印的不是我们想要的正数,而是负数?
在short int 中0-32767在内存中代表他们本身,而从数字32768到65535则代表负数,65536=0, 65535=-1, 65534 = -2;所以-336由65536-336得到65200来代表。所以当被解释成一个有符号整数时,65200代表-336,而被解释为无符号整数时,65200则代表65200.一定要谨慎!
11、如何将大于255的数字转换成字符的原理。
将>255的数字转换成字符时,是通过被256取余后的余数对应的ASCII码表所对应的字符,至于为什么对256取余,是因为ASCII码表的取值范围是000-255。比如数字336,就是336%256得到80余数,在ASCII码表中对应字母P。
12、参数传递中会出现的问题?
float n1;
double n2;
long n3,n4;
printf(“%ld, %ld, %ld,%ld\n”, n1, n2, n3, n4);
上面那句的运行情况:首先在内存的堆栈中开辟一块区域,区域的大小以其前面的变量声明定义为准,所以n1在堆栈中占用8个字节(float被转换成了double类型),同样n2占用8个字节,而n3和n4分别占用4个字节。
可是到printf函数输出这里却不是按照原大小输出的,而是根据转换说明符去读取的,%ld说明符指出,printf函数应该读取4个字节,所以printf在堆栈中读取前4个字节作为它的第一个值。这就是n1的前半部分,它被解释成一个长整数,下一个%ld说明符在读取4个字节,这就是n1的后半部分,它被解释成第二个长整数,然后n3和n4就按顺序阴差阳错地读错了。
13、scanf()函数使用:
如果使用scanf()来读取前面讨论过的某种基本变量类型的值,要加&;
如果使用scanf()把一个字符串读进一个字符数组中,不要加&。
14、printf和scanf中的*修饰符:
printf(“%*d\n”, width, i);中*修饰符可以提供字段的宽度,但是需要在变量之前有宽度的值。
scanf();中*提供截然不同的服务,当把它放在%和说明符字母之间时,它使函数跳过相应的输入项目。比如:scanf(“%*d %*d %d”,&n);就会跳过两个整数,把第三个整数赋值给n。