三:输入与输出
一:输出
1.printf()
:
将参数文本输出到屏幕上,它名字里的 f 代表 format(格式化),表示可以定制输出文本的格式
printf()
不会在行尾自动添加换行符,待运行结束后,光标就停留在输出结束的地方,不会自动换行,而为了让光标移到下一行的开头,需在输出文本的结尾,添加一个换行符 \n
c
#include <stdio.h>
int main()
{
printf("你好\n");
return 0;
}
注意: 因为printf()
是在标准库的头文件stdio.h
中定义的,所以,在使用这个函数之前,必须在源码文件头部引入这个头文件#include <stdio.h>
想在哪里换行就在哪里添加换行符,在文本行内部也可以添加换行符
c
#include <stdio.h>
int main()
{
printf("你好呀\n乔");
return 0;
}
2.占位符:
占位符表示这个位置会被后面的值给替换掉
c
#include <stdio.h>
int main()
{
printf("你好呀%d岁的乔\n",18); //在输出的时候,%d所占的位置被后面的18给替换掉了
return 0;
}
注意: 占位符的第一个字符一律为 %
,第二个字符表示占位符的类型
printf()
的第二个参数就是替换掉占位符的值
c
#include <stdio.h>
int main()
{
printf("我想去%s\n","北京"); //%s表示的是占位的是字符串类型
return 0;
}
注意: 因为%s
表示代入的是字符串,所以printf()
的第二个参数就必须是字符串
输出文本中也可以使用多个占位符
c
#include <stdio.h>
int main()
{
printf("你好呀%d岁的乔,我想去%s\n",18,"北京");
return 0;
}
注意: 占位符和后面的值必须是一一对应的关系,不可以调换位置,占位符的个数与后面值的个数也必须是一致的
占位符的种类:
占位符 | 描述 |
---|---|
%a |
十六进制浮点数,字母输出为小写 |
%A |
十六进制浮点数,字母输出为大写 |
%c |
字符输出 |
%d |
打印十进制整数 |
%e |
使用科学计数法的浮点数,指数部分的e 为小写 |
%E |
使用科学计数法的浮点数,指数部分的E 为大写 |
%i |
整型输出,基本等同于%d |
%f |
打印float 类型的浮点数 |
%lf |
打印double 类型的浮点数 |
%g |
6个有效数字的浮点数,整数部分一旦超过6位,就会自动转为科学计数法,指数部分的e 为小写 |
%G |
等同于%g ,唯一的区别是指数部分的E 为大写 |
%hd |
十进制short int 类型 |
%ho |
八进制short int 类型 |
%hx |
十六进制short int 类型 |
$hu |
unsigned short int 类型 |
%ld |
十进制long int 类型 |
%lo |
八进制long int 类型 |
%lx |
十六进制long int 类型 |
%lu |
unsigned long int 类型 |
%lld |
十进制long long int 类型 |
%llo |
八进制long long int 类型 |
%llx |
十六进制long long int 类型 |
%llu |
unsigned long long int 类型 |
%Le |
科学计数法表示的long double 类型的浮点数 |
%Lf |
long double 类型的浮点数 |
%n |
已输出的字符串数量,该占位符本身不输出,只将值存储在指定变量之中 |
%o |
八进制整数 |
%p |
用于指针 |
%s |
用于字符串 |
%u |
unsigned int |
%x |
十六进制整数 |
%zd |
size_t 类型 |
%% |
输出一个百分号 |
3.输出格式:
(1)限定宽度
printf()
允许限定占位符的最小宽度
c
#include <stdio.h>
int main()
{
printf("%5d\n",185); //输出为 " 123"
return 0;
}
注意: %5d
表示这个占位符的宽度至少是5位,如果后面的值不满5位,那么就会自动在这个值的前面填充空格补齐位数;如果超过指定位数,则值正常输出
输出的值默认是右对齐,即在输出内容的前面填充空格;如果要改成左对齐,即在输出内容的后面填充空格,可以在占位符%的后面插入一个 -
号
c
#include <stdio.h>
int main()
{
printf("%-5d\n",123); //输出为 "123 "
return 0;
}
对于小数,限定的是所有数字的最小显示宽度
c
#include <stdio.h>
int main()
{
printf("%12f\n",123.45); //输出为 " 123.450000"
return 0;
}
注意: %12f
表示输出的浮点数最少要占12位,小数点也算一位,由于小数的默认显示精度是小数点后6位,所以编译器会自动用0把后面所欠缺的位数补齐;然后在头部把整体的12位所欠缺的位数用空格填充
(2)总是显示正负号
默认情况下,printf()
不会对正数显示 +
号,只会对负数显示 -
号,如果要让正数也输出 +
号,可以在占位符 %
的后面加一个 +
号
c
#include <stdio.h>
int main()
{
printf("%+d\n",12); //输出 +12
printf("%+d\n",-12); //输出 -12
return 0;
}
(3)限定小数位数
想要限定小数点后面的位数,可以在 % 的后面添加 .
想要限定的位数
c
#include <stdio.h>
int main()
{
printf("%.2f\n",123.457806); //限定输出小数点后两位,输出为 123.46
return 0;
}
注意: 当想要限定的位数大于小数点后面的位数时,编译器会自动用0去填充
编译器会自动进行四舍五入
这种写法还可以与限定宽度占位符一起结合使用:
c
#include <stdio.h>
int main()
{
printf("%-6.2f\n",1.5); //输出 " 1.50"
return 0;
}
注意 : %6.2f
表示输出浮点数的最小宽度为6,小数点后的位数为2,而%
后面有 -
号表示左对齐,所以,输出浮点数的尾部应补充两个空格
最小宽度和小数位数这两个限定值,都可以用
*
代替,通过printf()
的参数传入:
c
//等同于printf("%6.2f\n",0.34)
#include <stdio.h>
int main()
{
printf("%*.*f\n",6,2,0.34); // 6 和 2 传入 * 号,一一对应
return 0;
}
(4)输出部分字符串
%s
占位符用来输出字符串,默认是全部输出;如果只想输出开头的部分,限定字符串的位数,可以在 %
的后面添加 .
想要限定的位数
c
#include <stdio.h>
int main()
{
printf("%.5s\n","zheshi一个字符串");
return 0;
}
二:输入
1.scanf()
:
当我们需要给变量输入值时就可以使用
scanf()
函数,将键盘输入的值放在变量里;如果需要给变量的值输出在屏幕上的时候可以使用printf()
函数
c
#include <stdio.h>
int main()
{
int a = 0;
printf("请输入年龄:");
scanf("%d",&a); //&表示取地址,将输入的值放在a中
printf("年龄是:%d\n",a);
return 0;
}
注意: 当 VS
编译器报出错误:C4996 'scanf': This function or variable may be unsafe. Consider using scanf_s instead. To disable deprecation, use _CRT_SECURE_NO_WARNINGS. See online help for details.
提示 scanf
函数不安全需要替换成 scanf_s
时的解决办法:
方法(1)在当前程序的第一行加上:
c
#define _CRT_SECURE_NO_WARNINGS 1
注意: 为什么不把 scanf
替换成 scanf_s
?
因为:scanf_s
函数是 VS
提供的,并不是C语言标准库中的函数;也就是说,这个函数在其它的编译器上运行不了,所以不能使用 scanf_s
会使代码降低可移植性
方法(2)让每一个创建的 .c 文件自动加上 #define _CRT_SECURE_NO_WARNINGS 1
在VS安装路径下的 newc++file.cpp
文件中加上 #define _CRT_SECURE_NO_WARNINGS 1
因为所有新建的 .c / .c++
文件都是拷贝 newc++file.cpp
这个文件的
方法(3)让错误失效,此代码可以放在任何地方
c
#pragma warning(disable:4996)
//#pragma warning指的是处理警告;disable指的是失效;4996指的是这个错误的编号
scanf()
函数用于读取用户的键盘输入,当程序运行到scanf()
这个语句时,会停下来,等待用户从键盘输入,当用户输入数据,按下回车键后,scanf()
函数就会处理用户的输入,并将其存入变量,scanf()
定义在头文件<stdio.h>
中,语法与printf()
函数类似
c
scanf("占位符",&变量);
/*
scanf()函数的第一个参数为格式化字符串,里面是占位符(与printf()的占位符基本一致),用来告诉编译器需要提取的数据是什么类型,因为在C语言中数据都是有类型的,scanf()函数必须提前知道用户输入的是什么数据类型,才能够进一步去处理数据;
scanf()函数的其余参数是用来存放用户输入的变量的,格式化字符串里有多少个占位符,就有多少个变量;
&变量表示,将用户从键盘输入的数据存入变量当中。
*/
注意: 因为 scanf()
函数传递的不是值,而是一个地址,即将变量的地址指向用户输入的值,所以变量的前面必须加上 &
运算符(指针变量除外)
scanf()
后面不用加换行符
c
#define _CRT_SECURE_NO_WARNINGS 1
#include <stdio.h>
int main()
{
int a = 0;
float b = 0.0;
unsigned c = 0;
scanf("%d %f %u",&a,&b,&c);
printf("%d %f %u\n",a,b,c);
return 0;
}
注意: 当这样输写代码后,在控制台输入时,数据与数据之间一定要加空格或者回车,因为 scanf()
在处理数据时会自动过滤空白字符,包括空格;制表符;换行符等,所以在用户输入数据之间,有一个或多个空格并不影响 scanf()
解读数据
scanf()
的返回值是一个整数,表示成功读取到的变量的个数;当没有读取到任何项或者匹配失败时,则返回一个0;如果在成功读取任何数据之前,发生了读取错误或者遇到文件结尾,则返回常量EOF
c
#define _CRT_SECURE_NO_WARNINGS 1
#include <stdio.h>
int main()
{
int a;
float b;
int s = scanf("%d %f",&a,&b);
printf("a=%d b=%f\n",a,b);
printf("s=%d\n",s);
return 0;
}
注意: EOF
的本质是 -1
2.占位符:
scanf()
里面的占位符与 printf()
里的占位符基本一致
占位符 | 含义 |
---|---|
%c |
字符 |
%d |
整数 |
%f |
float 类型的浮点数 |
%lf |
double 类型的浮点数 |
%Lf |
long double 类型的浮点数 |
%s |
字符串 |
%[] |
在方括号中指定一组匹配的字符(比如 %[0-9] ),当遇到不在集合之中的字符时,匹配将会停止 |
注意:
- 上面的所有占位符,除了
%c
以外,都会自动忽略起首的空白字符;%c
不忽略空白字符,总是返回当前第一个字符,无论该字符是否为空格;如果要强制跳过字符前的空白字符,可以写成scanf(" %c",&变量)
,即在%c
前加上一个空格,表示跳过0个或多个空白字符 %s
其实并不能完全的等同于字符串,它的用法是从当前第一个非空白字符开始读起,直到遇到空白字符(即空格;制表符;换行符等)便读取结束,因为%s
不会包含空白字符,所以无法用来读取多个单词,除非多个%s
一起使用,这也表示scanf()
不适合读取可能包含空格的字符串,另外,当scanf()
遇到%s
占位符,会在字符串的变量末尾存储一个空字符\0
scanf()
函数不安全的地方:scanf()
将字符串读入字符数组时,不会检测字符串是否超过了数组长度,所以,当存储字符串时,很可能会超过数组的边界,导致出现溢出错误,而为了防止出现这种情况,在使用%s
占位符时,应当指定读入字符串的最大长度,即%所读取字符串的最大长度s
,其中所读取字符串的最大长度为整数,后面没有被读取到的字符将会被舍弃
c
#include <stdio.h>
int main()
{
char name[11]; // name为长度11的字符数组
scanf("%10s",name); // %10s表示最多读取用户输入的10个字符;数组不需要取地址
printf("%s\n",name)
return 0;
}
3.赋值忽略符:
有时,用户的输入可能不符合预定的格式。比如:
c
#include <stdio.h>
int main()
{
int year = 0;
int month = 0;
int day = 0;
scanf("%d-%d-%d",&year,&month,&day);
printf("%d %d %d\n",year,month,day)
return 0;
}
在此示例中,用户正常输入2024-01-25
,则会正确解读出年;月;日。但如果用户输入的是其它格式,比如2024/01/25
,在这种情况下,scanf()
解析数据就会发生失败。
为了避免这种情况产生,scanf()
提供了一个赋值忽略符(assignment suppression character)*
,只要把赋值忽略符*
加在任何占位符的%
后面,该占位符就不会返回值,解析后将被舍弃。
c
#include <stdio.h>
int main()
{
int year = 0;
int month = 0;
int day = 0;
scanf("%d%*c%d%*c%d",&year,&month,&day);
printf("%d %d %d\n",year,month,day)
return 0;
}
在这里,%*c
就是在占位符的%
后面,加入了赋值忽略符*
,表示这个占位符没有对应的变量,解读后不必返回