? ? ? ? 做題記錄:牛客習題:單詞識別
? ? ? ? 相關題目代碼已經提交到gitee中:樓田莉子 (riko-lou-tian) - Gitee.com喜歡請點個贊謝謝
目錄
題目:
核心函數功能說明:
getline函數
仿函數
? ? ? ? 仿函數的使用
? ? ? ? 帶狀態的仿函數
? ? ? ? 多參數的仿函數
? ? ? ? 仿函數的實際應用舉例(自定義排序)
題目:
? ? ? ? 做題思路:
#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());//將單詞和出現次數存入vectorsort(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; // 輸出25return 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"; // 10std::cout << acc(20) << "\n"; // 30std::cout << acc(5) << "\n"; // 35acc.reset();std::cout << acc(100); // 100return 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"; // truestd::cout << "25 in range? " << inRange(25); // falsereturn 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 orangefor (const auto& word : words)std::cout << word << " ";return 0;
}
? ? ? ? 本篇內容就到這里了,喜歡請點個贊謝謝