C/C++输入输出
🕗 发布于 2025-01-19 17:11 c语言 c++
一、getchar 和 putchar
getchar()
和
putchar()
是属于 C 语言的库函数,C++是兼容 C 语言的,所以 C++ 中只要正确包
含头文件也可以正常使用这两个函数。
1.getchar
函数原型如下:
int getchar ( void );
getchar()
函数返回用户从键盘输入的一个字符,使用时不带有任何参数。程序运行到这个命令就会暂停,等待用户从键盘输入,等同于使用 cin
或
scanf() 方
法读取一个字符。它的原型定义在头⽂件 <cstdio>
。
#include <iostream>
#include <cstdio>
using namespace std;
int main()
{
int a = 0;
a = getchar();
cout << a << endl;
cout << (char)a << endl;
return 0;
}
在上面的示例代码中,当我们输入45时,输出分别是52和4,接下来分析一下原因。当我们输入45时,执行到getchar语句时会读取一个字符,所以会读取'4',因为a为整型,所以输出结果就是它的ASCII码52。当我们将它强制类型转换为字符型时,就会输出'4'。
getchar()
不会忽略起首的空白字符,总是返回当前读取的第⼀个字符,无论是否为空格。如果读取失败,返回常量 EOF
,由于
EOF
通常是
-1
,所以返回值的类型要设为
int
,而不是char 。如何让 getchar()
函数读取失败,返回
-1
呢?其实需要在输入字符之前,直接按
Ctrl+z
就可以。
getchar()
通常和
putchar()
是⼀对,配合使用的。
2.putchar()
函数原型如下:
int putchar( int character );
putchar()
函数将它的参数字符输出到屏幕,它的原型定义在头文件
<cstdio>
。
#include <iostream>
#include <cstdio>
using namespace std;
int main()
{
int a = 0;
a = getchar();
putchar(a);
return 0;
}
操作成功时,
putchar()
返回输出的字符,否则返回常量
EOF
。
二、
scanf 和 printf
scanf()
和
printf()
是属于C语言的库函数,C++是兼容 C 语言的,所以 C++ 中只要正确包含头文件也可以正常使用这两个函数。而且这两个函数在算法竞赛题目中使用的非常频繁,尤其是在输出格式控制中,所以接下来我们这里认真学习⼀下。
1.printf
printf()
函数原型如下:
int printf ( const char * format, ... );
printf()
的作用是将参数文本输出到屏幕。它名字里面的 f
代表
format
(格式化),表示可以定制输出文本的格式。
#include <cstdio>
int main()
{
printf("Hello World");
return 0;
}
上面命令会在屏幕上输出一行文字“Hello World”。
printf()
不会在行尾自动添加换行符,运行结束后,光标就停留在输出结束的地方,不会自动换行。为了让光标移到下一行的开头,可以在输出文本的结尾,添加一个换行符 \n
。
#include <cstdio>
int main()
{
printf("Hello World\n");
return 0;
}
如果文本内部有换行,也是通过插入换行符来实现,如下方代码:
#include <cstdio>
int main()
{
printf("Hello\nWorld\n");
printf("Hello\n");
printf("World\n");
return 0;
}
printf()
可以在输出文本中指定占位符。所谓 “占位符”,就是这个位置可以用其他值代入。
#include <cstdio>
// 输出 There are 3 apples
int main()
{
printf("There are %d apples\n", 3);
return 0;
}
上面示例中,
There are %d apples\n
是输出文本,里面的
%d
就是占位符,表示这个位置要用其他值来替换。占位符的第一个字符一律为百分号 %
,第二个字符表示占位符的类型,
%d
表示这里代入的值必须是一个整数。printf() 的第二个参数就是替换占位符的值,上面的例子是整数
3 替
换
%d
。执行后的输出结果就是 There are 3 apples
。
常用的占位符除了
%d
,还有
%s 表示代入的是字符串。输出文本里面还可以使用多个占位符。
#include <cstdio>
int main()
{
printf("%s says it is %d o'clock\n", "lisi", 21);
return 0;
}
上面示例中,输出文本
%s says it is %d o'clock
有两个占位符,第一个是字符串占位符 %s
,第二个是整数占位符
%d
,分别对应
printf()
的第二个参数(
lisi
)和第三个参数 ( 21
)。执行后的输出就是
lisi says it is 21 o'clock
。printf() 参数与占位符是一一对应关系,如果有
n
个占位符,
printf()
的参数就应该有
n + 1 个。如果参数个数少于对应的占位符,
printf()
可能会输出内存中的任意值。
printf()
的占位符有许多种类,与数据类型相对应。下面列出常用的占位符,方便查找。
%d :十进制整数。
%lld :十进制 long long int 类型。
%f :小数(包含float类型和double类型)。
%Lf :long double 类型浮点数。
%c :字符。
%s :字符串。
接下来说printf的格式化输出:
(1)限定宽度
printf()
允许限定占位符的最小宽度。
#include <cstdio>
int main()
{
printf("%5d\n", 123); // 输出为 " 123"
return 0;
}
上面示例中,
%5d
表示这个占位符的宽度至少为5位。如果不满5位,对应的值的前面会添加空格。输出的值默认是右对齐,即输出内容前面会有空格;如果希望改成左对齐,在输出内容后面添加空格,可以在占位符的 %
的后面插入一个
-
号。
#include <cstdio>
int main()
{
printf("%-5d\n", 123); // 输出为 "123 "
return 0;
}
上面示例中,输出内容
123
的后面添加了空格。
对于小数,这个限定符会限制所有数字的最小显示宽度。
#include <cstdio>
// 输出 " 123.450000"
int main()
{
printf("%12f\n", 123.45);
return 0;
}
上面示例中,
%12f
表示输出的浮点数最少要占据12位。由于小数的默认显示精度是小数点后6位,所以 123.45
输出结果的头部会添加2个空格。
(2)限定小数位数
输出小数时,有时希望限定小数的位数。举例来说,希望小数点后面只保留两位,占位符可以写
成
%.2f
。
#include <cstdio>
// 输出 Number is 0.50
int main()
{
printf("Number is %.2f\n", 0.5);
return 0;
}
这种写法可以与限定宽度占位符,结合使用。
#include <cstdio>
// 输出为 " 0.50"
int main()
{
printf("%6.2f\n", 0.5);
return 0;
}
上面示例中,
%6.2f
表示输出字符串最小宽度为6,小数位数为2。所以,输出字符串的头部有两个空格。最小宽度和小数位数这两个限定值,都可以用 *
代替,通过
printf()
的参数传入。
#include <cstdio>
int main()
{
printf("%*.*f\n", 6, 2, 0.5);
return 0;
}
// 等同于printf("%6.2f\n", 0.5);
上面示例中,
%*.*f
的两个星号通过
printf()
的两个参数
6
和
2
传入。
2.
scanf()
scanf()
函数原型如下:
int scanf ( const char * format, ... );
scanf()
函数用于读取用户的键盘输入。程序运行到 scanf()
这个语句时,会停下来,等待用户从键盘输入。 用户输入数据、按下回车键后, scanf()
就会处理用户的输入,将其存入变量。scanf() 的语法跟
printf()
类似。
请看下面的代码:
#include <cstdio>
int main()
{
int i = 0;
scanf("%d", &i);
printf("%d\n", i);
return 0;
}
特别注意,scanf函数的占位符后面一般不会加
\n
,
\n
是换行,一般在输出的时候才使用。
它的第一个参数是一个格式字符串,里面会放置占位符(与
printf()
的占位符基本一致),告诉编
译器如何解读用户的输入,需要提取的数据是什么类型。这是因为 C 语言的数据都是有类型的,
scanf()
必须提前知道用户输入的数据类型,才能处理数据。
它的其余参数就是存放用户输入的变量,格式字符串里面有多少个占位符,就有多少个变量。
上面示例中,
scanf()
的第一个参数
%d
,表示用户输入的应该是一个整数。
%d
就是一个占位
符,
%
是占位符的标志,
d
表示整数。第二个参数
&i
表示将用户从键盘输入的整数存入变量 i 。
scanf函数中存储数据的变量前面必须加上
&
运算符(指针变量除外),因为
scanf()
需要的是地址,必须将变量 i
的地址取出来传给scanf函数。如果这里的变量 i
是数组,那就不用加
&
运算符,因为数组名其实就是首元素的地址。
下面是一次从键盘读取多个变量的例子:
#include <cstdio>
int main()
{
int a, b, c, d;
scanf("%d%d%d%d", &a, &b, &c, &d);
printf("%d %d %d %d\n", a, b, c, d);
return 0;
}
scanf()
处理数值占位符时,会自动过滤空白字符,包括空格、制表符、换行符等。所以用户输入的数据之间,有一个或多个空格不影响 scanf()
解读数据。另外,用户使用回车键,将输入分成几行,也不会影响解读。
scanf()
处理用户输入的原理是:
用户的输入先放入缓存,等到按下回车键后,按照占位符对缓存进行解读。解读用户输入时,会从上一次解读遗留的第一个字符开始,直到读完缓存,或者遇到第一个不符合条件的字符为止。
再来看一下是scanf()的占位符:
scanf()
常用的占位符如下,与
printf()
的占位符基本一致。
%c :字符。
%d :整数。
%f :float类型浮点数。
%lf :double类型浮点数。
%Lf :long double类型浮点数。
%s :字符串。
上面所有占位符之中,除了
%c
以外,都会自动忽略起首的空白字符。
%c
不忽略空白字符,总是返回当前第一个字符,无论该字符是否为空格,因为空格也是一个字符。如果要强制跳过字符前的空白字符,可以写成 scanf(" %c", &ch)
,即
%c
前加上一个空格,表示跳过零个或多个空白字符。
了解这一点后,当
%c
和
%d
等占位符连续使用的时候,也要注意,
%c
默认不会跳过空白字符的,所以在输入的时候,要非常小心,比如:
#include <cstdio>
int main()
{
int a;
char ch;
scanf("%d%c", &a, &ch);
printf("%d %c\n", a, ch);
return 0;
}
如果在输入的时候,就是想在整数和字符之间加上空格,那么scanf中的格式串中%c的前面就要加上空格。
再来看看scanf()的返回值:
scanf()
的返回值是一个整数,表示成功读取的变量个数。
如果没有读取任何项,或者匹配失败,则返回
0
。如果在成功读取任何数据之前,发生了读取错误或者遇到读取到文件结尾,则返回常量 EOF(-1)。
三、
cin 和 cout
前面我们已经提到过在C++中提供了:
cin
和
cout
两个流对象。
cin
是 C++ 中提供的标准输入流对象,一般针对的是键盘,也就是从键盘上输入的字符流,使用cin 来进行数据的提取,
cin 一
般是和
>>
(流提取运算符)配合使用的。
cin
的功能和
scanf 是类似的。
cout
是C++中提供的标准输出流对象,一般针对的控制台的窗口,也就是将数据以字符流的形式输
出到控制台窗口上显示。
cout
⼀般是和
<<
(流插入运算符)配合使用。
cout
的功能和 printf 是类似的。
我们在写程序的时候,经常需要处理数据,不管什么
类型的数据都是以字符流的形
式输入和输出的,也就是不管在键盘上输入什么类型的数据,还是将程序中的各种类型的数据输出显示到控制台屏幕上,都是以字符流的形式处理的。cin 和
cout 的输入输出非常的方便,不需要手动控制格式,能够自动识别变量类型。
当我们在键盘输入数据的时候,输入的数据不能被
cin
解读为对应类型的数据,那么读取也就结束
了。
cin 的好处:当输入若干个变量(也就是数据量很少)的时候,我们就可以通过 >> 把所有的数据用一行代码完成接收,而且无需关心数据的类型,和 scanf 函数比起来代码的书写非常简洁明了。
cout
的好处: cout 也可以用来连续输出多个数值,而且无需考虑数值的类型,因为它本身会做类型处理,和 printf 比
起来比较方便。
1.cin
使用细节:
cin
在读取的时候是根据用户的输入,从前往后,从上往下依次扫描。
cin
在读取的过程中遇到空格,自动会跳过,所以不要担心在想要的字符前输入空白字符。
当一行读取结束的时候,会自动换行,读取下一行的内容。
cin
后面不可以跟换行
endl
2.连续输入输出:
如果我们一次要输入/输出多个数据,那
cin
和
cout
能做到吗?当然是可以的。
使用
cout
进行变量的输出,实质上是将变量插入到
cout
对象里,并以
cout 对象作为返回值返回,因此我们还可以用 <<
在后面连续输出多个内容,通过连续输入输出的方式对代码进行编写。
示例如下:
#include <iostream>
using namespace std;
int main()
{
int a,b,c;
cin >> a >> b >> c;
cout << a << " " << b << " " << c << endl;
return 0;
}
接下来我们来看一道oj题
#include <iostream>
using namespace std;
int a, b;
int main()
{
while (cin >> a >> b)
{
cout << a + b << endl;
}
return 0;
}
为什么可以这样写呢?我们来分析一下。cin >> a;
会返回一个流对象的引用,即
cin
本身。在 C++ 中,流对象
cin
可以被用作布尔值来检查流的状态。如果流的状态良好(即没有发生错误),流对象的布尔值为 true 。如果发生错误(如遇到输入结束符或类型不匹配),布尔值为
false
。 在 while (cin >> a >> b)
语句中,循环的条件部分检查
cin
流的状态。如果流成功读取到2个值, cin >> a >> b
返回的流对象
cin
将被转换为
true
,循环将继续。如果读取失败(例如遇到输入结束符或无法读取到2个值), cin >> a >> b
返回的流对象 cin
将被转换为
false
,循环将停止。
3.
cout 的格式输出
printf
函数在输出数据的时候,可以指定格式来输出,比如指定宽度,比如指定小数点后的位数,对齐方式等等。
cout
结合 <iomanip> (IO manipulators)头文件中的操纵符,也可以灵活控制输出格式,从而满足各种格式化需求。
(1)控制宽度和填充
setw
:设置字段宽度(只对紧接着的输出项有效)。
setfill
:设置填充字符。
#include <iostream>
using namespace std;
#include <iomanip>
int main() {
int a = 123;
cout << "默认宽度: " << a << endl;
cout << "宽度设置为10: " << setw(10) << a << endl;
cout << "宽度为10,不够时填充*: " << setw(10) << setfill('*') << a << endl;
return 0;
}
(2)控制数值格式
fixed
:以固定小数点表示浮点数,设置后就不会以科学计数法展示了。
scientific
:以科学计数法表示浮点数。
setprecision
:设置浮点数的精度,以控制小数点后的数字位数,一般先固定小数点,再设置精度。
#include <iostream>
using namespace std;
#include <iomanip>
int main()
{
double pi = 3.141592653589793;
cout << "默认: " << pi << endl;
cout << "固定⼩时点⽅式: " << fixed << pi << endl;
cout << "科学计数法⽅式: " << scientific << pi << endl;
cout << "固定⼩数点,⼩数点后2位有效数字: " << fixed << setprecision(2) << pi << endl;
return 0;
}
cout
结合其他操作符还能完成一些其他的格式输出,但是毕竟
cout
在完成格式化输出的时候,其
实不如
printf 方
便,所以在竞赛中,涉及格式化输出的时候,我们⼀般会使用
printf
来完成。
3.控制整数格式
dec
:以十进制格式显示整数(默认)。
hex
:以十六进制格式显示整数。
oct
:以八进制格式显示整数。
#include <iostream>
using namespace std;
#include <iomanip>
int main() {
int n = 255;
cout << "⼗进制 : " << dec << n << endl;
cout << "⼗六进制: " << hex << n << endl;
cout << "⼋进制 : " << oct << n << endl;
return 0;
}
4.
控制对齐方式
left
:左对齐。
right
:右对齐(默认)。
#include <iostream>
using namespace std;
#include <iomanip>
int main() {
int n = 123;
cout << "右对⻬: " << setw(10) << right << n << endl;
cout << "左对⻬: " << setw(10) << left << n << endl;
return 0;
}
四、scanf/printf 和 cin/cout的对比
scanf
和
printf
是 C 语言中的标准输入输出函数,而
cin
和
cout
是 C++ 语言中的标准输入输出流对象。它们各自有优缺点,整体上来说 cin
和
cout
会更加方便,但有时候我们也不得不使用 scanf
和
printf
。
1.格式控制差异
scanf
和
printf
不能自动识别输入数据的类型,需要手动指定格式字符串,容易出现格式错误。开发者需要确保格式字符串与变量类型匹配,否则会导致未定义行为。
cin 和
cout
会根据变量类型自动处理输入输出,避免格式化错误。相对
scanf
和
printf ,C++的 cin
和
cout
更加易用。
格式化输出更精确直观,特别适合复杂格式的输入输出,比如:在要求指定格式输出的时候, printf 函数就比
cout
更加方便和灵活。
2.性能差异
scanf
和
printf
通常比
cin
和
cout
快。
原因:
cin
和
cout
由于要考虑兼容C语言的输入和输出,封装实现的更加复杂,通常比
scanf 和 printf
稍慢,但这种差异在大多数应用场景中可以忽略不计。
但是在竞赛的题目中,尤其是当输入、输出数据量较大时,使用
cin
和
cout
完成输入输出,经常
会出现
Time Limit Exceeded
的情况。而
scanf
和
printf
就不存在类似的问题。
总结一下其实就是2个点:
(1)C++中为了支持混合使用yong cin/cout
和
scanf/printf
,C++ 标准库默认会将
cin
、
cout 等 C++ 流对象与 stdin
、
stdout
等 C 标准库的流对象同步在一起。这种同步操作意味着每次使用 cin
或
cout
时,都会自动刷新 C 标准库的缓冲区,以确保 C++ 和 C 的 I/O 是一致的。这就导致了性能的下降。
(2)在默认情况下, cin
和
cout
之间存在一种绑定关系。这种绑定意味着,每当从
cin
读取数据时,任何之前通过 cout
输出的内容都会被强制刷新到屏幕上。这种绑定也可能导致性能问题,特别是在需要频繁读取大量数据的情况下。
所以未来我们在使用
scanf
/
printf
和
cin
/
cout
抉择的时候,如果要追求性能那就使用 scanf /
printf
,如果不追求性能,直接使用
cin
/
cout
就行。
小提示:
如果输入的数据量比较小(
10^6
以内)的话,用
cin
和
cout
或
scanf
和 printf 都行;但是输入的数据量比较大( 10^9 左右)的话,更推荐使用
scanf
和
printf
,避免因为输入输出的开销,导致代码超时;
在大多数场景下 printf / scanf
和
cin / cout
的使用根据个人习惯进行选择即可。
原文地址:https://blog.csdn.net/shdbdndj/article/details/144547622
免责声明:本站文章内容转载自网络资源,如侵犯了原著者的合法权益,可联系本站删除。更多内容请关注自学内容网(zxcms.com)!