自学内容网 自学内容网

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)!