第四章字符串的格式化输入/输出
C存储字符串的方式之一是使用字符数组char a[]
注意,每一个字符占据一个比特,且在这个字符数组中,其末尾一定是\0
,\0
是一个非打印字符,C在打印到\0时会停止打印
#include<stdio.h>
int main(void)
{
char a[] = {'a','b','b','\0','v','d'};
printf("%s",a);
return 0;
}
/* outputs:
abb
*/
可以从示例中看到\0后面的字符不再被打印。
并且scanf在读取字符串的时候读到空格‘ ’,就会停止。
#include<stdio.h>
int main(void)
{
char a[20];
scanf("%s",a);
printf("%s",a);
return 0;
}
/*
input: hoiwdh nwdiw
output: hoiwdh
*/
C在limits.h 和floats.h中有一些符号常量,用于告诉用户,该整型和浮点数的大小限制(位数,字节数等)。详情见C Primer Plus 67页
C的参数传递机制:
#include<stdio.h>
int main(void)
{
float n1 = 3.0f;
double n2 = 3.0;
long n3 = 2000000000;
long n4 = 1234567890;
printf("%ld,%ld,%ld,%ld",n1,n2,n3,n4);
}
n1 | n2 | n3 | n4 |
---|---|---|---|
4 bytes | 8 bytes | 8bytes | 8bytes |
运行上面那段函数的时候,会先把n1,n2,n3,n4按照顺序存入栈中,然后再运行printf,之后按照%ld给定的方式去解析栈中的内存信息(编译器不同结果似乎也不同),我的编译器是有纠错功能的。
注意:printf()函数也是有返回值的,它的返回值时这一次输出的字符串的总长度,包括诸如\n
,\b(空格)
之类的一些特殊字符;
以及你在代码中按下的enter并不能被编译器理解为\n
#include<stdio.h>
int main(void)
{
int a = 1;
printf("%d This way is true\n",
a);
printf("%d This way is true\
yes",2);
printf("%d This way is true"
"Yes",3);
printf("%d This way is false
",a);
}
最后一个会导致编译错误:missing terminating ‘"’ character [-Winvalid-pp-token]
且在2中下一行的元素不可以带有缩进,否则会在输出中带上这个缩进
scanf()解析:
e.g1
#include<stdio.h>
int main(void) {
int b,c,d;
char a;
scanf("%c %d %d",&a,&b,&c);
printf("%d,%d,%d",a,b,c);
scanf("%d",&d);
printf("\n%d",d);
}
input{
11111 2 3}
outputs{
49,1111,2
3}
首先scanf会读取你的输入并且最开始先跳过你输入的全部的空白字符如\n,\b。然后会一旦读取到一个非字符时,按照此时%c的要求,读到这里就停止。并把值存入a所在的地址,然后把自己已经保存好的输入从缓冲区中删去。然后重复上述步骤。
注意到此时b = 1111,c = 2,因为在写入b的值的时候只写了是从上一次读到的1开始,往后读取,连续读取4个1,然后遇到空格,停止。把1111存入b,并且在缓冲区中删去1111,现在缓冲区中有:{\b2\b3\n},然后照例,跳过空格,读取2,然后遇到空格,停止读取,保存2至c,同时缓冲区把{\b2}清楚,所以此时缓冲区里面还留下3。之后进入下一轮的输入的时候,由于缓冲区中还有字符,所以程序认定你已经输入完毕,然后读取了3,传给d。
之所以a的值是49是因为,按照ansii 码,a的ascii码为49,
e.g2
#include<stdio.h>
int main(void) {
int b, c;
scanf("%d,%d", &c, &b);
printf("%d %d", c, b);
}
input: 1,2
output:1 2
input:1 2
output:1 1
按照scanf("%d,%d",&c,&b)
的要求,scanf要读取到 整数逗号整数 这样的一个格式,在第二个I/O里面,输入是{1 2},1和2之间是空格,而不是逗号,格式匹配错误,C在此时停止读取输入。并且下一步中所输出的那个b的值随机,看当时内存的情况。
e.g3
#include<stdio.h>
int main(void) {
int a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11,a12,a13,a14,a15,a16;
scanf("%d%d%d%d%d%d%d%d",&a1,&a2,&a3,&a4,&a5,&a11,&a13,&a14);
printf("%d %d %d %d %d %d %d %d\n",a1,a2,a3,a4,a5,a11,a13,a14);
fflush(stdin);
scanf("%d%d%d%d%d%d%d%d",&a6,&a7,&a8,&a9,&a10,&a12,&a15,&a16);
printf("%d %d %d %d %d %d %d %d\n",a6,a7,a8,a9,a10,a12,a15,a16);
}
input:a
output:1 71188576 1 69844412 -312147967 1 1 70844528
input:a
output:70495036 1 1807120320 1 71188576 69844412 0 0
可以看出是随机的。
以及如果是要转化为%c的时候\b(空格)也会被当成值符给,解决放啊是" %c"
在%c前面加一个空格,那么scanf就会不断的忽略这个空格,不把空格符传给对应的字符变量,但是如果把空格替换为其他的字符,那么scanf只会忽略一次。比如scanf(“12%c”,&n),然后输入123,那么你还是n会被赋值为3
修饰符*
e.g.1: 在printf()
中
#include<stdio.h>
int main(void) {
double b = 383123123129.39122332430293203902903;
printf("The b = %0*.*f",100,5,b);
return 0;
}
outputs:
The b = 0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001.39122
第一个*
被替换为100,第二个*
被替换为5,在这里%0*.*f
实际上就是%0100.5f
e.g2
#include<stdio.h>
int main(void) {
int n;
printf("Inputs: ");
scanf("%*d %*d %d",&n);
printf("Outputs: %d",n);
}
/*
Inputs: 121 343 656565
Outputs: 656565
*/
前两个符合要求的输入会被scanf一并略过,这样子可以帮助你在获取格式确定的一个文件时获取某一部分的元素(通过省略其它部分的元素)。