做题记录:牛客习题:单词识别
相关题目代码已经提交到gitee中:楼田莉子 (riko-lou-tian) - Gitee.com喜欢请点个赞谢谢
目录
题目:
做题思路:
#define _CRT_SECURE_NO_WARNINGS
#include <iostream>
#include<vector>
#include<map>
#include<string>
#include<algorithm>
#include <cctype> // 添加头文件以使用 tolower 函数
using namespace std;
typedef pair<string, int> Word;
//仿函数
bool cmp(Word w1, Word w2)
{
return w1.second > w2.second;
}
int main()
{
map<string, int>mp;// 使用map存储单词及其出现次数
string s;
while (getline(cin, s))
{// std::getline (来自 <string>)
// 主要作用:从输入流中读取一行文本并存储到 std::string 对象中
for (int i = 0, j = 0; i < s.size(); i++)
{// 遇到分隔符(空格/句号)或字符串结尾时处理单词
if (s[i] == ' ' || s[i] == '.')
{
string t = s.substr(j, i - j);
if (isupper(t[0]))//将单词的首字母转为小写
t[0] = tolower(t[0]);
j = i + 1;//更新起始位置
mp[t]++;//更新出现次数
}
}
vector<Word>v(mp.begin(), mp.end());//将单词和出现次数存入vector
sort(v.begin(), v.end(), cmp);//按出现次数从多到少排序
for (int i = 0; i < v.size(); i++)
//按字典序输出单词和出现次数
cout << v[i].first << ":" << v[i].second << endl;
}
return 0;
}
扩充知识:
C++ 字符函数头文件<cctype>
在 C++ 中,isupper
和 tolower
函数都来源于 <cctype>
头文件(或 C 风格的 <ctype.h>
)。以下是详细说明:
头文件:<cctype>
(C++ 标准库)
作用:提供字符分类和转换函数,用于处理单字节字符(ASCII 字符集)
核心函数功能说明:
函数原型 | 功能描述 | 返回值 |
---|---|---|
int isupper(int ch) |
检测字符 ch 是否为大写字母(A-Z) |
非零值(true)如果是;0(false)如果不是 |
int tolower(int ch) |
若 ch 是大写字母,则返回对应小写字母;否则返回原始值 |
转换后的字符(int 类型) |
int islower(int ch) |
检测字符 ch 是否为小写字母(a-z) |
非零值(true)如果是;0(false)如果不是 |
int toupper(int ch) |
若 ch 是小写字母,则返回对应大写字母;否则返回原始值 |
转换后的字符(int 类型) |
int isalpha(int ch) |
检测字符 ch 是否为字母(A-Z 或 a-z) |
非零值如果是;0 如果不是 |
int isdigit(int ch) |
检测字符 ch 是否为数字(0-9) |
非零值如果是;0 如果不是 |
int isalnum(int ch) |
检测字符 ch 是否为字母或数字(等价于 isalpha || isdigit ) |
非零值如果是;0 如果不是 |
int isspace(int ch) |
检测字符 ch 是否为空白字符(空格、制表符 \t 、换行符 \n 等) |
非零值如果是;0 如果不是 |
int iscntrl(int ch) |
检测字符 ch 是否为控制字符(ASCII 0-31 及 127) |
非零值如果是;0 如果不是 |
int ispunct(int ch) |
检测字符 ch 是否为标点符号(非字母、数字、空白的可打印字符,如 ! , . ) |
非零值如果是;0 如果不是 |
int isprint(int ch) |
检测字符 ch 是否为可打印字符(包括空格) |
非零值如果是;0 如果不是 |
int isgraph(int ch) |
检测字符 ch 是否为图形字符(可打印字符,不包括空格) |
非零值如果是 |
参数类型:
所有函数接受
int
类型参数(实际是字符的 ASCII 值)传入的整数必须在
0~255
或EOF
(-1)范围内
返回值:
分类函数(如
isupper
)返回 非零值(通常为 1)表示真,0 表示假转换函数(如
tolower
)返回转换后的 ASCII 值(需显式转换回char
getline函数
在 C++ 中,getline
函数有两个主要版本,分别来自不同的头文件:
std::getline
(用于std::string
)
来源于:<string>
头文件istream::getline
(用于 C 风格字符串)
来源于:<iostream>
头文件(作为istream
类的成员函数)
1. std::getline
(来自 <string>
)
主要作用:从输入流中读取一行文本并存储到 std::string
对象中
核心功能:
从输入流读取字符直到遇到分隔符(默认换行符)
将读取的内容存储到
string
对象中(不包括分隔符)自动处理内存分配,无需担心缓冲区大小
分隔符会被从流中移除但不存储
2. istream::getline
(来自 <iostream>
)
主要作用:从输入流中读取一行文本并存储到 C 风格字符数组中
核心功能:
从输入流读取字符直到遇到分隔符或读取了
count-1
个字符在读取的字符串末尾添加空终止符
'\0'
分隔符会被提取但不存储到缓冲区
需要预先分配足够大的字符数组
特性 | std::getline (来自 <string> ) |
istream::getline (来自 <iostream> ) |
---|---|---|
目标类型 | std::string |
C 风格字符数组 |
内存管理 | 自动 | 手动(需预分配缓冲区) |
安全性 | 高(无缓冲区溢出风险) | 低(可能缓冲区溢出) |
最大长度 | 无限制(仅受内存限制) | 受缓冲区大小限制 |
使用便捷性 | 高 | 中 |
推荐场景 | 大多数现代 C++ 代码 | 遗留代码或特定性能需求 |
getline
是 C++ 中处理文本输入的核心函数:
<string>
版本:现代 C++ 首选,安全方便,配合std::string
使用<iostream>
版本:适用于 C 风格字符串或特定性能场景关键优势:正确处理整行输入,包括空格和特殊字符
常见应用:文件处理、用户输入、数据解析
注意要点:缓冲区管理、输入流状态处理、换行符处理
仿函数
本题中我们应用了仿函数,前面我们知道仿函数就是重载了运算符的类对象,类似于函数,因此叫仿函数
class FunctorName {
public:
// 函数调用运算符重载
return_type operator()(parameter_list) const; // 常成员函数版本
return_type operator()(parameter_list); // 非常成员函数版本
};
原型要素解析
组成部分 | 说明 |
---|---|
operator() |
必须重载的操作符 |
return_type |
仿函数的返回值类型 |
parameter_list |
参数列表(可为空) |
const 修饰符 |
声明为const成员函数,表示不修改对象状态 |
仿函数的使用
基本使用:
#include <iostream>
// 定义仿函数
class Square
{
public:
int operator()(int x) const // const版本
{
return x * x;
}
};
int main()
{
Square square; // 创建仿函数对象
int result = square(5); // 调用仿函数
std::cout << "5 squared: " << result; // 输出25
return 0;
}
带状态的仿函数
class Accumulator
{
int total = 0; // 内部状态
public:
int operator()(int value)
{
total += value;
return total;
}
void reset() { total = 0; }
};
int main()
{
Accumulator acc;
std::cout << acc(10) << "\n"; // 10
std::cout << acc(20) << "\n"; // 30
std::cout << acc(5) << "\n"; // 35
acc.reset();
std::cout << acc(100); // 100
return 0;
}
多参数的仿函数
class RangeChecker
{
int min, max;
public:
RangeChecker(int low, int high) : min(low), max(high) {}
bool operator()(int value) const
{
return value >= min && value <= max;
}
};
int main()
{
RangeChecker inRange(10, 20);
std::cout << "15 in range? " << inRange(15) << "\n"; // true
std::cout << "25 in range? " << inRange(25); // false
return 0;
}
仿函数的实际应用举例(自定义排序)
#include <algorithm>
#include <vector>
// 按字符串长度排序
class LengthComparator
{
public:
bool operator()(const std::string& a, const std::string& b) const
{
return a.size() < b.size();
}
};
int main()
{
std::vector<std::string> words = { "apple", "banana", "kiwi", "orange" };
// 使用仿函数排序
std::sort(words.begin(), words.end(), LengthComparator());
// 输出:kiwi apple banana orange
for (const auto& word : words)
std::cout << word << " ";
return 0;
}
本篇内容就到这里了,喜欢请点个赞谢谢