跳转至

输入输出的其他知识

控制精度

保留两位小数,前面已经讲过,两种写法都可以。

// 使用<cstdio>
printf("%.2lf", x);
// 使用<iostream>和<iomanip>
cout << fixed << setprecision(2) << x;

cout 默认通常显示 6 位有效数字,不是小数点后 6 位。数太大或太小时,可能显示成科学计数法。

fixed 配合 setprecision,才是控制小数点后的位数。

image-20250605170945471

image-20250605170815476

控制域宽

域宽,就是输出至少占几个字符。默认靠右,不足的部分补空格。

int a = 123;
printf("%8d", a);  // 占8个字符,靠右
printf("%-8d", a); // 占8个字符,靠左

如果数字本身超过 8 个字符,会完整输出,不会截断。

cout 使用 setw,需要头文件 <iomanip>。

int x = 123;
cout << setw(8) << x << setw(8) << x; // 靠右
cout << left << setw(8) << x << setw(8) << x; // 靠左

setw 是 set width 的缩写,只影响紧接着的一次输出,要用几次就写几次。

left 会持续生效,要改回靠右,用 right。

image-20240708151316128

image-20240708151401963

从文件输入输出

使用 freopen,需要头文件 <cstdio>,写在 main 里面,读写数据之前。

freopen("1.in", "r", stdin);
freopen("1.out", "w", stdout);

r 表示读文件,w 表示写文件。输出文件原来有内容,会被覆盖。

后面照常使用 cin、cout,或者 scanf、printf。

输入文件要放在程序的工作目录下。比赛时,文件名、是否使用文件输入输出,都按题目要求来。

freopen 一定要在复赛前练熟,主要是调试要熟练。

输出换行符

// 以下三种,都可以完成换行操作
cout << endl;
cout << '\n';
puts("");

puts 需要头文件 <cstdio>,输出字符串后会自动换行。

endl 除了换行,还会刷新输出缓冲区。'\n' 只表示换行。

频繁使用 endl 可能拖慢输出,做题时一般用 '\n'。

cin、cout 加速

数据量大、输入输出慢时,可以在 main 开头,读写数据之前加上:

ios::sync_with_stdio(false);
cin.tie(nullptr);

第一行,关闭 C++ 流与 C 标准输入输出的同步。

第二行,解除 cin 与 cout 的绑定,读入前不再自动刷新 cout。

开了加速,就统一用 cin、cout,不要再混用 scanf、printf。

是否需要加速,要看数据量和时限,没有超过 1e5 才需要加速的固定界线。

sscanf,从字符串里读数据

这部分用到了字符数组,学过字符串后再回来看。

scanf 从标准输入读,sscanf 从字符串里读,用法相似。

需要头文件 <cstdio>。

char s[] = "User M 19 1.85";
char name[10];
char gender;
int age;
double height;

int cnt = sscanf(s, "%9s %c %d %lf", name, &gender, &age, &height);

cnt 是成功读入并赋值的项数,这里是 4。

name 是字符数组,这里不加 &;其他几个变量要加。

%9s 最多读 9 个字符,给数组末尾的 \0 留一个位置。

%c 本身不会跳过空白。

上面格式中,%c 前的空格可以跳过空格、换行等空白字符。

2076:【21CSPJ普及组】网络连接(network)

这道题要处理 a.b.c.d:e,sscanf 可以帮忙拆数据。

但读出来,不等于格式合法。还要检查数值范围、前导零、多余字符等,不能只看读出了几个数。

sprintf,把数据写到字符串里

这部分也用到了字符数组。

printf 输出到屏幕,sprintf 写到字符数组里,需要头文件 <cstdio>。

char target[100];
char name[] = "Andrea";
char gender = 'F';
int age = 25;
double height = 1.70;

sprintf(target, "%s %c %d %.2lf", name, gender, age, height);
printf("%s", target); // 输出Andrea F 25 1.70

数组要放得下所有内容,还要给末尾的 \0 留一个位置。

sprintf 不会检查数组容量。

stringstream,字符串流

需要头文件 <sstream>,使用 string 还需要 <string>。

从字符串里读数据

string s = "123 45 6";
stringstream ss(s);

int a, b, c;
ss >> a >> b >> c;

cin 从标准输入读,ss 从字符串里读,写法一样。

把内容拼成字符串

stringstream ss;
ss << 2026 << "-" << 3 << "-" << 20;
string s = ss.str();

s 的内容是 "2026-3-20"。

>> 读数据,<< 写数据,str() 取出字符串。

清空后重新使用

ss.str(""); // 清空内容
ss.clear(); // 清除错误状态

这两行作用不同,clear() 不会清空字符串内容。