printf与scanf的返回值、注意点

scanf()函数注意事项

转换说明

意义

%c

把输入解释成一个字符

%d

解释成一个有符号十进制数

%e,%f,%g,%a

浮点数(%aC99的标准)

%E,%F,%G,%A

浮点数(%AC99的标准)

%i

有符号十进制数

%o

有符号八进制数

%x,%X

有符号十六进制整数

%p

一个指针

%s

一个字符串:输入内容以第一个非空白字符作为开始,并且包含直到下一个空白字符的全部字符

%u

无符号十进制整数

 

 

示例1

char name[5];

scanf("%s",name);

printf("%srn",name);

printf("sizeof(name)=%d,strlen(name)=%drn",sizeof(name),strlen(name));

1scanf把一个字符串读到一个字符数组时,不要用&(也可以加)。格式如下

char name[5];

scanf("%s",name]);  //这里name前面也可以添加&

注意,如果使用数组下标输入单个字符,则必须使用地址符号,如

char name[5];

scanf("%c",&name[1]);  //这里的&不能省略

2scanf使用空格、制表符和换行符来判断是否结束输入,而不是以数组长度来判断,例如我们输入的abcdefg,会被全部读入。

3scanf%s输入时,会自动在后面加上'',使其成为一个字符串,即使输入的字符数超过数组大小。strlen(name)是从第一个字符开始,到''结束,strlen统计字符数(不含'')。

附注:用%s读入字符串时,有两种方法停止输入:第一种就是空白符,遇到空白符,就会停止输入;第二种就是使用字段宽度,例如s,那么就最多读入10个字符,当然,如果还未够10个字符就已经遇到了空白符,那也要结束读入,10只是一个最大值。

 

示例2

char name[5];

char name2[5];

char ps;

scanf("%s",name);

//if(scanf("%c",&ps))//标记1

if(scanf("%s",name2))  //标记2

printf("Heen");

注释掉标记1,保留标记2,运行时,输入aa,按回车键,系统会显示要我们继续输入;

注释掉标记2,保留标记1,运行时,输入aa,按回车键,系统不会要我们输入,而是会打印出Hee

程序说明:

4scanf输入时,会从第一个非空白字符开始读入(唯一的例外就是%c),直到再次遇到空白字符时结束,前面的空白字符被丢弃,但后面的空白字符不会丢弃(也就是说%s实际上读入的是一个单词)。

所以,保留标记2运行时,先是对name进行输入,这时回车键会留在输入流。执行语句if(scanf("%s",name2))时,会忽略掉这个回车符,要求我们重新输入。

5scanf%c输入时,所有输入字符都是平等的,即使是空白字符,也会读入,且只读取一个,剩余的仍然留在输入流。也正是因为它什么字符都能读入,所以它的用途很多。

6scanf如果遇到错误的输入,不会将它丢弃,而是将它留在输入队列,因此,如果下次再有一个读入操作时,就会从它们开始。

 

示例3

int age1,age2;

scanf("%d",&age1);

printf("age1=%dn",age1);

scanf("%d",&age2);

printf("age2=%dn",age2);

输入-+12-3,输出

age1=2

age2=12

程序说明:

7、用%d,它会从第一个非空白字符开始读入,

1)如果是数字,直接读入即可。

2)如果是符号,则保存该符号,继续读取下一个字符:

Ø        如果下一个字符是数字,则保存该数字即可;

Ø        如果下一个字符是非数字,则将这个字符返回输入流,之前保存的符号被丢弃。

3)如果是其它字符(既不是空白,也不是数字或+-符号),将不会读入任何信息,且该字符会被返回到输入流。在本示例中,如果第一个非空白字符输入的是A,则两个scanf语句都不会读入任何信息,且A仍留在输入流中。

现在来看本示例:

1)两个变量因为是自动变量,所以不会初始化,但由于已经分配内存,所以当前值就是原先存在该内存中的值。

2)执行scanf("%d",&age1);时,首先读入的是-,系统会暂时保存这个符号,接着读取下一个符号,+,因为不是数字符号,所以-会被丢掉,+被返回输入流。

printf("age1=%dn",age1);此时打印的是一个垃圾值(上面是2)。

3)执行scanf("%d",&age2);时,首先读取的是原先留在输入流中的+,然后读取下一个字符,是12,所以age2就被赋予了12.

printf("age1=%dn",age1);打印出age2=12

8、使用其它数字说明符与使用%d的情况相同,主要区别就是scanf也许会把更多的字符看做数字符号。例如,使用%x,要求输入十六进制数字,那么afAF都会被当成数字符号。而浮点说明符则要求scanf识别小数点、指数计数法、新的p计数法。

scanf连续输入

示例4

char age1,age2;

scanf("%c,%c",&age1,&age2);

如果逗号(或任何非空格字符)和第一个%c之间没有间隔,则输入时,第一个字符与逗号之间也不能有间隔;如果有空格,则输入时,第一个字符和逗号之间可以有任意多个字符,也可以是0个。

如果逗号和第二个%c之间没有间隔,则逗号和第二个输入字符间也不能有间隔。如果有空格,则输入时,第二个字符和逗号之间可以有任意多个字符,也可以是0个。

 

示例5

int age1,age2;

scanf("%d,%d",&age1,&age2);

如果逗号和第一个%d之间有空格,则输入的第一个数字和逗号之间可以有任意(含0)个空格;

如果逗号和第一个%d之间没有空格,则输入的第一个数字和逗号之间不能有空格;

逗号和第二个%d之间无论是否有空格,输入时,逗号和第二个数字之间都可以有任意(含0)个空格。这点和%c不同。

 

示例6

int age1;

char pet1;

scanf("%c,%d",&pet1,&age1);

根据示例4和示例5可以推出来:

Ø        %c和逗号之间如有空格,则第一个输入的字符和逗号之间可以有任意(含0)个空格,如果没有空格,则不能含空格;

Ø        %d在逗号后面,所以他们之间不管是否有空格,输入时,逗号和整数之间都可含任意(含0)个空格。

 

示例7

int age1;

char pet1;

scanf("%d , %c",&age1,&pet1);

根据示例4和示例5可以推出来:

因为%d在逗号前面,所以,如果它们之间有空格,则输入时可含任意(含0)个空格;如果没有空格,则输入时也不能含空格;

逗号和%c之间,如有空格,则逗号和字符之间可以有任意(含0)个空格,如果没有空格,则不能含空格;

 

总结:

1)当格式符是%c时,不管逗号是在前还是在后,都遵循一条规则:如果彼此之间有空格,则输入时可含任意(含0)个空格,否则不能含空格;

2)如果是其它格式符(不限于%d),则:

Ø        若逗号在格式符前面,则不管是否有空格,输入时可含任意(含0)个空格;

Ø        若逗号在后面,则遵循%c的规则。

 

补注:

scanf("%c%d",&pet1,&age1);

不管%c%d之间是否有空格,第一个字符(注意,%c什么字符都能读入)和第一个数字之间都可以含任意(含0)个空格。

scanf("%d%c",&age1,&pet1);

如果%d%c之间有空格,则第一个数字输完之后,中间可以有任意个字符,然后再是数字;

如果没有空格,则数字输完之后必须马上输入字符,如果有空格的话,第一个空格将被作为输入赋给pet1

(注意,第一个数字之前可以有任意个空白,都不会被读入。)

 

其实%c之所以特别,就是因为%c对待所有字符都平等。所以在%c之前,如果没有空格,那么在输入时,如果输入空格,空格就会作为输入被读取;如果%c之前有空格,那就是告诉系统,我们只读取非空白字符(不限于空格),所以,所有非空白字符都被跳过丢弃。

注意,这跟%c前面有没有其它格式符或其它符号都无关,例如

scanf("%c%d",&pet1,&age1);

如果我们在%c前面留空格scanf(" %c%d",&pet1,&age1);,那在输入时,就会跳过所有空白字符。

 

对于其它格式符,因为它会自动跳过空白字符,所以,不管前面是否有空格,输入时,都可有空白字符。

 

对于这一块就要记住两点:

1%c的非%c的规则;

2、格式说明符里所有非空格的字符,如果是在格式说明符前面,遵循第一条;如果是在格式说明符后面,则,不管格式说明符是不是%c,规则都一样:如果有空格,就可以输入任意多个空白字符,否则,不能含空白字符。

补充:

scanf连续输入字符时,可能出错,因为第一个scanf需要按下回车键才能读入,但是读入后,这个回车键还在输入流里,所以,如果下一个scanf还是读入字符,就会把这个回车键读进去。

但是如果第二个scanf是读入其它类型,就不用担心,因为除了%c外,用其它格式读取输入,都会跳过前面所有空白字符,所以第一个scanf留下的回车键会被丢弃。

printf与scanf的返回值、注意点


  1. printf()的返回值为其输出字符串常量的字符数(注意字符数与字数的区别)注意计数针对所有的打印字符,包括空格和不可见的换行字符(不包括字符串的空字符)。
  2. scanf()函数返回成功读入的项目的个数。即在下面程序中scanf的返回值为1。如果没有读取任何项目(如它期望一个数字但是出入了一个非数字字符),它会返回值0。当它检测到“文件结尾”时,它返回EOF(EOF是文件stdio.h中定义的特殊值。一般,#define 指令把EOF 的值定义为 -1)。    int n;
    float  p;
    n= scanf("%f",&p);
    printf("%d,%f",n,p);
用%c读入空格和字符的问题。
如果在格式字符串中%c之前有一个空格,那么scanf()会跳到第一个非空白字符处。也就是说, 命令scanf(“%c”,&ch)读取在输入中遇到的第一个字符,而scanf(“ %c”,&ch)(%c前有个空格)则读取遇到的第一个非空白字符。
     对于同时输入几个字符,如果逗号(或任何非空格字符)和第一个%c之间没有间隔,则输入时,第一个字符与逗号之间也不能有间隔;如果有空格,则输入时,第一个字符和逗号之间可以有任意多个字符,也可以是0个。如果逗号和第二个%c之间没有间隔,则逗号和第二个输入字符间也不能有间隔。如果有空格,则输入时,第二个字符和逗号之间可以有任意多个字符,也可以是0个。

printf()函数的*修饰符(*滞后赋值,例:%*d)

 
  假定不想事先制定字段宽度,而是希望由程序来指定该值,可以在字段宽度部分使用*来代替数字来达到目的,但是也必须使用一个参数来告诉函数字段宽度应该是什么。也就是说,如果转换说明符是%*d ,那么参数列表中应该包括一个 * 值和一个 d 的值。同时这种方式也可以和浮点数一起使用来指定精度和字段宽度。
例:
        printf("What field width?\n");
        scanf("%d", &width);
        printf("The number is: %*d:\n", width, num);
        printf("Enter a width and a precision:\n");
        scanf("%d %d", &width, &precision);
        printf("Weight = %*.*f\n", width, precision, weight);
结果:
What field width?
7
The number is:     256:
Enter a width and a precision:
3 7
Weight = 123.4500000
 

  scanf()函数的*修饰符

 
   在scanf()函数中,当把 * 放在 % 和说明符字母之间时,它使函数跳过相应的输入项目。 
例:
int i,j;
    scanf("%d%*d%d",&i,&j);
    printf("%d,%d\n",i,j);
输出结果为:
2 3 5
i=2,j=5
/*
      通过while循环把上面 i 输入后的多的垃圾字符跳过
     如果没有while循环,在调试时输入 i = 123asdfg
     在Vc++6.0中的输出结果为:
     123asdfg
     i = 123
     j = -858993460

     */
    int scan1,scan2;
    char ch;
    scanf("%d", &scan1);
    printf("scan1= %d\n", scan1);
     while ( (ch=getchar()) != '\n')
        continue
;
    scanf("%d", &scan2);
    printf("scan2 = %d\n", scan2);
参数传递的原理
 
float n1 = 3.0;
double n2 = 3.0;
long n3 = 2000000000;
long n4 = 1234567890;  
printf("%ld, %ld, %ld, %ld\n", n1, n2, n3, n4);
结果为:
2000000000, 1234567890, 3, 64

  该调用告诉计算机把变量n1、n2、n3、n4的值传递给计算机,计算机把它们放置到被称为堆栈(stack)的一块内存区域中来实现。计算机根据变量的类型而非转换说明符把这些值放到堆栈中。所以,n1 在堆栈中占用8个字节(float 被转换成 double)。同样,n2 也占用8个字节,而n3 和n4 则分别占用4个字节。然后控制转移到 printf()函数。该函数从堆栈把值读出来,但是在读出时,它根据转换说明符去读。 %ld 说明符指出, printf() 应该读取4个字节,所以 printf()在堆栈中读取前4个字节作为它的第一个值。这就是n1的前半部分,它被解释成一个长整数。下一个 %ld说明符再读取4个字节,这就是n1 的后半部分,它被解释成第二个长整数。同样,%ld 的第三个和第四个实例使得 n2 的前半部分和后半部分被读出,并被解释成2个长整数。 


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值