C++ 字符处理基础与二进制位统计实战
问题背景描述
在算法竞赛中,经常需要处理定长的字符序列。本题设定场景为:接收一个固定长度为 8 位的二进制编码(仅包含 '0' 和 '1'),目标是计算该编码中有效位 '1' 的数量。
输入规范:单一行数据,包含一个由字符 '0' 或 '1' 组成的字符串。
输出规范:打印一个整数,表示 '1' 出现的总频次。
- 示例情况 A:输入 `00010100`,结果为 `2`。
- 示例情况 B:输入 `11111111`,结果为 `8`。
核心语法与数据存储机制
1. 字符单元 (char)
计算机中最小的文本存储单位是字符,在 C/C++ 中对应 char 类型。它占用 1 个字节的内存空间。字符本质上是一个整数值,对应于 ASCII 码表中的编码。
char val1 = 'A'; // 显式字符
char val2 = 65; // 隐式转换,65 对应 'A'
2. 字符数组 (Character Array)
C 语言中没有内置的字符串类型,通常使用字符数组来模拟。需要注意的是,只有以空字符 '\0' 结尾的字符数组才能被标准库函数识别为"字符串"。
// 初始化方式差异
char bufferA[5] = {'H', 'e', 'l', 'l', 'o'}; // 未包含结束符,视为纯数组
char bufferB[6] = {'H', 'e', 'l', 'l', 'o', '\0'}; // 包含结束符,视为字符串
若直接输出指针指向的 char 数组且含有 '\0',会打印完整内容;否则可能输出乱码或只到首个非有效区域。
3. C++ 标准字符串类 (std::string)
引入 `std::string 类管理动态长度的文本。它封装了内存管理和常用操作(如长度获取、拼接、子串截取)。
#include <string>
using namespace std;
// 构造函数重载示例
string text1 = "Init"; // 字面量赋值
string text2(3, '*'); // 重复填充 3 个 '*'
string text3("Prefix-Suffix", 7, 6); // 从下标 7 开始取 6 个字符
数据输入机制分析
流式输入 (cin)
cin 遇到空白符(空格、换行、制表符)会自动停止读取。适用于读取不含空格的单词或数字。
string token;
cin >> token; // 若输入 "Hello World",token 仅获取 "Hello"
行级输入 (getline)
当需要读取包含空格的整行文本时,应使用 getline(cin, str)。它会一直读取直到遇到换行符。\n
注意:若在 cin >> n; 之后立即使用 getline,需先处理缓冲区遗留的换行符。
解题策略与代码实现
针对上述统计任务,以下展示四种不同的技术实现路径,涵盖从底层字符操作到高层数学技巧。
策略一:逐字符流处理
不一次性存储整个字符串,而是循环 8 次,每次读取一个字符并即时判断。
#include <iostream>
using namespace std;
int main() {
int bitCounter = 0;
char currentCh;
for (int i = 0; i < 8; ++i) {
cin >> currentCh;
if (currentCh == '1') {
bitCounter++;
}
}
cout << bitCounter << endl;
return 0;
}
策略二:定长数组遍历
利用静态字符数组存储输入,通过索引访问每个元素。这是 C 风格字符串处理的典型方式。
#include <iostream>
using namespace std;
int main() {
char sequence[10]; // 预留额外空间存放潜在的空字符
int onesTotal = 0;
cin >> sequence; // 自动以空格/回车结束
for (int i = 0; i < 8; ++i) {
if (sequence[i] == '1') {
onesTotal++;
}
}
cout << onesTotal << endl;
return 0;
}
策略三:STL 容器迭代
使用现代 C++ 的 string 对象,结合范围基循环(Range-based for loop)简化逻辑,增强可读性。
#include <iostream>
#include <string>
using namespace std;
int main() {
string rawData;
getline(cin, rawData); // 读取整行
int countVal = 0;
for (auto ch : rawData) { // 自动类型推导
if (ch == '1') {
countVal++;
}
}
cout << countVal << endl;
return 0;
}
策略四:数论同余特性
基于十进制数模 9 的特性:一个数除以 9 的余数,等于其各位数字之和除以 9 的余数。
由于输入仅由 '0' 和 '1' 组成,将输入的 8 位串视作一个十进制整数,对该整数取模 9,结果即为 '1' 的个数。此方法假设 '1' 的总数小于 9(题目限制长度为 8,满足条件)。
#include <cstdio>
int main() {
long long numValue;
// 以整数格式读取二进制形式的字符序列
scanf("%lld", &numValue);
// 利用数位和性质直接计算
printf("%lld\n", numValue % 9);
return 0;
}
