文章目录
-
- 准备工作:先记住两个概念
- [第一个:`%*s` 中的 `*` 是什么意思?](#第一个:
%*s中的*是什么意思?) -
- [先看不带 `*` 的普通写法(你肯定见过):](#先看不带
*的普通写法(你肯定见过):) - [再看带 `*` 的写法:](#再看带
*的写法:) - 完整运行代码:
- [先看不带 `*` 的普通写法(你肯定见过):](#先看不带
- [第二个:`%.*s` 中的 `.*` 是什么意思?](#第二个:
%.*s中的.*是什么意思?) -
- [先看不带 `*` 的普通写法:](#先看不带
*的普通写法:) - [再看带 `.*` 的写法:](#再看带
.*的写法:) - 完整运行代码:
- [先看不带 `*` 的普通写法:](#先看不带
- [第三个:两个一起用 `%*.*s`](#第三个:两个一起用
%*.*s) - [第四个:`scanf` 中的 `%*s`(完全不同!)](#第四个:
scanf中的%*s(完全不同!)) - 总结(初学者记住这些就够了)
- 最简单的记忆方法
- [一、最传统的方法:`cout <<`(最常用,但功能有限)](#一、最传统的方法:
cout <<(最常用,但功能有限)) - [二、控制宽度和对齐:`iomanip` 库](#二、控制宽度和对齐:
iomanip库) -
- [1. 控制宽度:`setw()`](#1. 控制宽度:
setw()) - [2. 左对齐和右对齐:`left` 和 `right`](#2. 左对齐和右对齐:
left和right) - [3. 填充字符:`setfill()`](#3. 填充字符:
setfill())
- [1. 控制宽度:`setw()`](#1. 控制宽度:
- [三、截取字符串(相当于 C 的 `%.*s`)](#三、截取字符串(相当于 C 的
%.*s)) - [四、现代 C++ 方法:`std::format`(C++20,推荐!)](#四、现代 C++ 方法:
std::format(C++20,推荐!)) -
- [如果你用不了 C++20(编译器太老)](#如果你用不了 C++20(编译器太老))
- [五、C 和 C++ 对比(初学者友好版)](#五、C 和 C++ 对比(初学者友好版))
- 六、实际例子对比
- 总结:初学者怎么选?
准备工作:先记住两个概念
- 宽度:一共占多少个字符的位置
- 精度:最多取多少个字符
第一个:%*s 中的 * 是什么意思?
* 的作用是:宽度不写死,用一个变量来决定。
先看不带 * 的普通写法(你肯定见过):
c
printf("%10s", "hello");
输出:
" hello"(一共10个位置,前面补5个空格)
再看带 * 的写法:
c
int w = 10;
printf("%*s", w, "hello");
输出:
" hello"(和上面完全一样)
解释:
%*s中的*会被w替换成 10- 相当于
printf("%10s", "hello")
完整运行代码:
c
#include <stdio.h>
int main() {
int width = 15;
printf("【%*s】\n", width, "hi");
return 0;
}
输出:
【 hi】
hi占了15个位置,前面补了13个空格(因为hi本身2个字符,15-2=13)
第二个:%.*s 中的 .* 是什么意思?
.* 的作用是:最多取几个字符,用一个变量来决定。
先看不带 * 的普通写法:
c
printf("%.3s", "hello");
输出:
"hel"(只取前3个字符)
再看带 .* 的写法:
c
int n = 3;
printf("%.*s", n, "hello");
输出:
"hel"(和上面一样)
解释:
%.*s中的.*会被n替换成 3- 相当于
printf("%.3s", "hello")
完整运行代码:
c
#include <stdio.h>
int main() {
int len = 4;
printf("【%.*s】\n", len, "abcdef");
return 0;
}
输出:
【abcd】
只取了前4个字符 "abcd"
第三个:两个一起用 %*.*s
同时控制宽度 和取几个字符。
c
#include <stdio.h>
int main() {
int width = 10; // 一共占10个位置
int len = 4; // 最多取4个字符
printf("【%*.*s】\n", width, len, "hello world");
return 0;
}
输出:
【 hell】
分解步骤:
- 先取前4个字符 →
"hell" - 再占10个宽度 → 前面补6个空格
- 结果:
" hell"
第四个:scanf 中的 %*s(完全不同!)
重要 :scanf 里的 %*s 和 printf 里的 %*s 是两回事!
在 scanf 中,* 表示跳过这个数据,不保存。
c
#include <stdio.h>
int main() {
char word[100];
// 输入字符串:"apple banana"
sscanf("apple banana", "%*s %s", word);
// ↑ 跳过第一个字符串 "apple"
// ↑ 把第二个 "banana" 存到 word 中
printf("%s\n", word); // 输出 "banana"
return 0;
}
再举个例子:
c
sscanf("100 200 300", "%*d %d %*d", &a);
// 跳过100,读取200到a,跳过300
总结(初学者记住这些就够了)
| 写法 | 用在 | 意思 | 例子 |
|---|---|---|---|
%*s |
printf | 宽度由变量决定 | printf("%*s", w, s) |
%.*s |
printf | 取几个字符由变量决定 | printf("%.*s", n, s) |
%*.*s |
printf | 宽度和取字符数都由变量决定 | printf("%*.*s", w, n, s) |
%*s |
scanf | 跳过这个字符串 | scanf("%*s %s", s) |
最简单的记忆方法
- printf 里的
*= 数字不写死,用变量代替 - scanf 里的
*= 跳过不要了
这样是不是清楚多了?
好的,C++ 的格式化比 C 安全很多,也更好理解。我从最简单到最现代,逐个给你介绍。
一、最传统的方法:cout <<(最常用,但功能有限)
cpp
#include <iostream>
#include <string>
int main() {
int age = 18;
std::string name = "小明";
// 直接拼接输出
std::cout << "我叫" << name << ",今年" << age << "岁" << std::endl;
// 输出:我叫小明,今年18岁
return 0;
}
特点:
- 自然、好理解
- 不需要记
%d、%s这些格式 - 但控制对齐、宽度比较麻烦
二、控制宽度和对齐:iomanip 库
需要 #include <iomanip>
1. 控制宽度:setw()
cpp
#include <iostream>
#include <iomanip>
int main() {
std::cout << std::setw(10) << "hello" << std::endl;
// 输出:" hello"(一共10个位置,右对齐,前面补5个空格)
return 0;
}
2. 左对齐和右对齐:left 和 right
cpp
#include <iostream>
#include <iomanip>
int main() {
// 右对齐(默认)
std::cout << std::setw(10) << "hello" << std::endl;
// 输出:" hello"
// 左对齐
std::cout << std::left << std::setw(10) << "hello" << std::endl;
// 输出:"hello "
// 中间的换回右对齐
std::cout << std::right << std::setw(10) << "world" << std::endl;
// 输出:" world"
return 0;
}
3. 填充字符:setfill()
cpp
#include <iostream>
#include <iomanip>
int main() {
// 用 * 号填充
std::cout << std::setfill('*') << std::setw(10) << "hello" << std::endl;
// 输出:"*****hello"
// 用 0 填充
std::cout << std::setfill('0') << std::setw(8) << 123 << std::endl;
// 输出:"00000123"
return 0;
}
三、截取字符串(相当于 C 的 %.*s)
C++ 用 substr() 来截取,比 C 简单多了:
cpp
#include <iostream>
#include <string>
int main() {
std::string s = "hello world";
// 取前5个字符
std::cout << s.substr(0, 5) << std::endl;
// 输出:"hello"
// 结合宽度控制
std::cout << std::setw(10) << s.substr(0, 5) << std::endl;
// 输出:" hello"(先取5个字符,再占10个宽度)
return 0;
}
四、现代 C++ 方法:std::format(C++20,推荐!)
最像 Python 的 f-string,非常好用!
cpp
#include <iostream>
#include <format> // C++20
int main() {
std::string name = "小明";
int age = 18;
double score = 95.5;
// 基本用法
std::cout << std::format("我叫{},今年{}岁", name, age) << std::endl;
// 输出:我叫小明,今年18岁
// 控制宽度和位置
std::cout << std::format("{:10}", "hello") << std::endl;
// 输出:"hello "(左对齐,宽度10)
std::cout << std::format("{:>10}", "hello") << std::endl;
// 输出:" hello"(右对齐)
std::cout << std::format("{:*<10}", "hello") << std::endl;
// 输出:"hello*****"(左对齐,用*填充)
// 截取字符串
std::cout << std::format("{:.5}", "hello world") << std::endl;
// 输出:"hello"(只取前5个字符)
// 组合使用
std::cout << std::format("{:>10.5}", "hello world") << std::endl;
// 输出:" hello"(取前5个字符,右对齐宽度10)
return 0;
}
如果你用不了 C++20(编译器太老)
可以装 {fmt} 库,用法和 std::format 一模一样:
cpp
#include <fmt/core.h> // 第三方库
int main() {
fmt::print("我叫{},今年{}岁\n", "小明", 18);
return 0;
}
五、C 和 C++ 对比(初学者友好版)
| 需求 | C 写法 | C++ 传统写法 | C++ 现代写法(C++20) |
|---|---|---|---|
| 输出变量 | printf("%d", age) |
cout << age |
format("{}", age) |
| 固定宽度 | printf("%10s", s) |
cout << setw(10) << s |
format("{:10}", s) |
| 左对齐 | printf("%-10s", s) |
cout << left << setw(10) << s |
format("{:<10}", s) |
| 右对齐 | printf("%10s", s) |
cout << right << setw(10) << s |
format("{:>10}", s) |
| 补0 | printf("%08d", n) |
cout << setfill('0') << setw(8) << n |
format("{:08}", n) |
| 截取字符串 | printf("%.5s", s) |
s.substr(0,5) |
format("{:.5}", s) |
| 跳过输入 | scanf("%*s %s", s) |
cin >> skip >> s(不常用) |
用 cin 逐个读取 |
六、实际例子对比
同样功能,三种写法:
C 语言(麻烦、容易错):
c
printf("%10s\n", "hello");
printf("%.3s\n", "hello world");
printf("%*.*s\n", 10, 5, "hello world");
C++ 传统(有点啰嗦):
cpp
cout << setw(10) << "hello" << endl;
cout << string("hello world").substr(0, 3) << endl;
cout << setw(10) << string("hello world").substr(0, 5) << endl;
C++20 现代(最简洁):
cpp
cout << format("{:10}\n", "hello");
cout << format("{:.3}\n", "hello world");
cout << format("{:>10.5}\n", "hello world");
总结:初学者怎么选?
- 刚入门 :用
cout <<直接输出,简单够用 - 需要对齐表格 :用
setw()和left/right - 编译器支持 C++20 :直接学
std::format,最好用 - 工作项目 :看项目用什么,一般是
cout或std::format
一句话 :如果你用的编译器比较新(VS2022、gcc13+),学 std::format 就行,它最像 Python,最容易用!