C++ Primer 第5版章节题 第九章

一、9.2.1 迭代器

复制代码
节练习 9.4
// chapter9_2.cpp
#include <iostream>
#include <vector>

using namespace std;
using std::vector;

vector<int> v = {2,4,63,75,34,57,234,543,678,975,4322};
bool find(vector<int>::iterator it1, vector<int>::iterator it2, int data) {
    while (it1 != it2)
    {
        if (*it1 == data) {
            cout << "find the data " << data << endl;
            return true;
        }

        it1 ++;
    }
    cout << "not find the data " << data << endl;
    return false;
}

int main(){
    find(v.begin(), v.end(), 23);
    return 0;
}

// 编译 g++ -std=c++11 -o chapter9_2  chapter9_2.cpp

节练习 9.5
// chapter9_2.cpp
#include <iostream>
#include <vector>

using namespace std;
using std::vector;

vector<int> v = {2,4,63,75,34,57,234,543,678,975,4322};
vector<int>::iterator find(vector<int>::iterator it1, vector<int>::iterator it2, int data) {
    while (it1 != it2)
    {
        if (*it1 == data) {
            cout << "find the data " << data << endl;
            return it1;
        }

        it1 ++;
    }
    cout << "not find the data " << data << endl;
    return it1;
}

int main(){
    vector<int>::iterator it = find(v.begin(), v.end(), 4322);
    if (it == v.end()) {
        cout << "not find the data "<< endl;
    } else {
        cout << "find the data " << endl;
    }
    return 0;
}
// 编译 g++ -std=c++11 -o chapter9_2  chapter9_2.cpp

// 节练习 9.14 
// chapter9_2.cpp
#include <iostream>
#include <vector>
#include <list>

using namespace std;
using std::vector;
using std::list;

int main(){
   list<char*> l = {"nihao", "hello word", "output"};
   vector<string> v;
   v.assign(l.begin(),l.end());
   cout << "ventor data is ";
   vector<string>::iterator it = v.begin();
   while(it != v.end()) {
    cout << *it << ",";
    it ++;
   }
//    for (int i = 0; i < v.size(); i ++) {
//     cout << v.at(i) << ",";
//    }
   cout << endl;
   return 0;
}

// 编译 g++ -std=c++11 -o chapter9_2  chapter9_2.cpp

// 节练习 9.15
// chapter9_2.cpp
#include <iostream>
#include <vector>

using namespace std;
using std::vector;

int main()
{
    vector<int> v1 = {1, 2, 3, 4, 5, 6, 7, 8, 9, 0};
    vector<int> v2 = {1, 2, 3, 4, 5, 6, 7, 8, 9, 0};
    // vector<int> v2 = {11, 21, 31, 41, 51, 61, 71, 81, 91, 10};
    if (v1 == v2)
    {
        cout << "vector v1 == v1" << endl;
    }
    else
    {
        cout << "vector v1 != v1" << endl;
    }
    return 0;
}
// 编译 : g++ -std=c++11 -o chapter9_2  chapter9_2.cpp

// 节练习 9.16
// chapter9_2.cpp
#include <iostream>
#include <vector>
#include <list>

using namespace std;
using std::vector;
using std::list;

int main()
{
    list<int> l = {1, 2, 3, 4, 5, 6, 7, 8, 9, 0};
    vector<int> v = {1, 2, 3, 4, 5, 16, 7, 8, 9};
    // vector<int> v2 = {11, 21, 31, 41, 51, 61, 71, 81, 91, 10};
    list<int>::iterator it1 = l.begin();
    vector<int>::iterator it2 = v.begin();
    while (it1 != l.end() && it2 != v.end())
    {
        if (*it1 == *it2) {
            cout << "the data is same " << *it1 << endl;
        } else {
            cout << "the data is not same " << *it1 << "," << *it2<< endl;
        }
        it1 ++;
        it2 ++;
    }
    
    return 0;
}
// 编译 : g++ -std=c++11 -o chapter9_2  chapter9_2.cpp

// 节练习 9.18
// chapter9_3.cpp
#include <iostream>
#include <deque>
using namespace std;
using std::deque;
int main() {
    cout << "please input some data :" ;
    string s;
    deque<string> d;
    while (cin >> s && s != "q") {
        d.push_back(s);
    }

    deque<string>::iterator it = d.begin();
    while (it != d.end())
    {
        cout << "data is : " << *it << endl;
        it ++ ;
    }
    
    return 0;
}
编译: g++ -std=c++11 -o chapter9_3  chapter9_3.cpp

// 节练习 9.19
// chapter9_3.cpp
#include <iostream>
#include <list>
using namespace std;
using std::list;
int main() {
    cout << "please input some data :" ;
    string s;
    list<string> d;
    while (cin >> s && s != "q") {
        d.push_back(s);
    }

    list<string>::iterator it = d.begin();
    while (it != d.end())
    {
        cout << "list data is : " << *it << endl;
        it ++ ;
    }
    
    return 0;
}
编译: g++ -std=c++11 -o chapter9_3  chapter9_3.cpp

// 节练习 9.20
// chapter9_3.cpp
#include <iostream>
#include <list>
#include <deque>
using namespace std;
using std::list;
using std::deque;
int main()
{
    list<int> l = {1, 2, 3, 4, 5, 6, 7, 8, 9, 0};
    deque<int> d1;
    deque<int> d2;
    if (l.size() == 0)
    {
        cout << "the list is null" << endl;
        return 1;
    }
    list<int>::iterator it_l = l.begin();
    while (it_l != l.end())
    {
        if (*it_l % 2 == 0) {
            d1.push_back(*it_l);
        } else {
            d2.push_back(*it_l);
        }
        it_l ++;
    }

    deque<int>::iterator it_d1 = d1.begin();
    cout << "deque 1 data is " ;
    while (it_d1 != d1.end())
    {
        cout << *it_d1 << " ";
        it_d1 ++;
    }
    cout << endl;

    deque<int>::iterator it_d2 = d2.begin();
    cout << "deque 2 data is " ;
    while (it_d2 != d2.end())
    {
        cout << *it_d2 << " ";
        it_d2 ++;
    }
    cout << endl;

    return 0;
}
编译: g++ -std=c++11 -o chapter9_3  chapter9_3.cpp

// 节练习 9.24
// chapter9_3.cpp
#include <iostream>
#include <vector>
using namespace std;
using std::vector;
int main()
{
    vector<int> v;
    // vector<int> v = {9, 2, 3, 4, 56, 7, 8, 9, 0};
    if (v.size() == 0)
    {
        cout << "the vector is null" << endl;
        return 1;
    }
    cout << "at the first data is " << v.at(0) << endl;
    cout << " the first data is " << v[0] << endl;
    cout << " front the first data is " << v.front() << endl;
    cout << " begin the first data is " << *(v.begin()) << endl;

    return 0;
}
// 编译 g++ -std=c++11 -o chapter9_3  chapter9_3.cpp

// 节练习 9.26
// chapter9_3.cpp
#include <iostream>
#include <list>
#include <vector>
using namespace std;
using std::list;
using std::vector;
int main()
{
    int ia[] = {0, 1, 1, 2, 3, 5, 8, 13, 21, 55, 89 };

    // copy
    vector<int> v(begin(ia),end(ia));
    list<int> l(begin(ia),end(ia));
    if (v.size() == 0)
    {
        cout << "the vector is null" << endl;
        return 1;
    }
    if (l.size() == 0)
    {
        cout << "the list is null" << endl;
        return 1;
    }

    // erase
    list<int>::iterator it_l = l.begin();
    while (it_l != l.end())
    {
        if (*it_l % 2 == 1) {
            it_l = l.erase(it_l);
        } else {
            it_l ++;
        }
    }

    vector<int>::iterator it_v = v.begin();
    while (it_v != v.end())
    {
        if (*it_v % 2 == 0) {
            it_v = v.erase(it_v);
        } else {
            it_v ++;
        }
    }

    // print
    it_l= l.begin();
    cout << "list data is " ;
    while (it_l != l.end())
    {
        cout << *it_l << " ";
        it_l ++;
    }
    cout << endl;

    it_v= v.begin();
    cout << "vector data is " ;
    while (it_v != v.end())
    {
        cout << *it_v << " ";
        it_v ++;
    }
    cout << endl;

    return 0;
}
// 编译 g++ -std=c++11 -o chapter9_3  chapter9_3.cpp

// 节练习 9.27
// chapter9_3.cpp
#include <iostream>
#include <forward_list>
using namespace std;
// using std::forward_list;

int main()
{
    forward_list<int> l = {0, 1, 1, 2, 3, 5, 8, 13, 21, 55, 89 };
    if (l.empty())
    {
        cout << "the list is null" << endl;
        return 1;
    }

    // erase
    forward_list<int>::iterator pre = l.before_begin();
    forward_list<int>::iterator current = l.begin();
    while (current != l.end())
    {
        if (*current % 2 == 1) {
            current = l.erase_after(pre);
        } else {
            pre = current;
            current ++;
        }
    }

    // print
    current= l.begin();
    cout << "list data is " ;
    while (current != l.end())
    {
        cout << *current << " ";
        current ++;
    }
    cout << endl;

    return 0;
}
// 编译 g++ -std=c++11 -o chapter9_3  chapter9_3.cpp

// 节练习 9.28
// chapter9_3.cpp
#include <iostream>
#include <forward_list>
using namespace std;
// using std::forward_list;

int find_and_add_data(forward_list<string>l, string s1, string s2) {
    forward_list<string>::iterator current = l.begin();
    bool isFind = false;

    // 查找并插入字符串
    while (current != l.end())
    {
        if (*current == s1) {
            isFind = true;
            current = l.insert_after(current,s2);
        } else {
            current ++;
        }
    }

    // 未查找到指定字符串,则在最后添加
    if (!isFind) {
        current = l.begin();
        forward_list<string>::iterator pre = l.before_begin();
        while(current != l.end()) {
            current ++;
            pre ++;
        }
        l.insert_after(pre,s2);
    }
   
   // 打印
    current = l.begin();
    cout << "list data is " ;
    while (current != l.end())
    {
        cout << *current << " ";
        current ++;
    }
    cout << endl;
    return 0;
}

int main()
{
    forward_list<string> l1 = {"0", "1", "1", "2", "3", "5", "8", "13", "21", "55", "89" };
    find_and_add_data(l1,"1","66");

    return 0;
}
// 编译 g++ -std=c++11 -o chapter9_3  chapter9_3.cpp

// 节练习 9.31 (forward_list)
// chapter9_3.cpp
#include <iostream>
#include <forward_list>
using namespace std;
// using std::forward_list;

int erase_and_add_data(forward_list<int>l) {
    cout << "erase_and_add_data..." <<endl;
    forward_list<int>::iterator pre = l.before_begin();
    forward_list<int>::iterator current = l.begin();

    // 查找并插入字符串
    while (current != l.end())
    {
        if (*current % 2 == 0) { // 偶数
            current = l.erase_after(pre); // 迭代器返回一个指向呗删元素之后元素的迭代器
        }  else { // 奇数
            current = l.insert_after(current,*current); // 迭代器返回一个指向最后一个插入元素的迭代器
            pre = current;
            current ++;
        }
    }
   
   // 打印
    current = l.begin();
    cout << "list data is " ;
    while (current != l.end())
    {
        cout << *current << " ";
        current ++;
    }
    cout << endl;
    return 0;
}

int main()
{
    forward_list<int> l1 = {5, 1, 1, 2, 3, 4, 8, 12, 21, 55, 89 };
    erase_and_add_data(l1);

    return 0;
}
// 编译 g++ -std=c++11 -o chapter9_3  chapter9_3.cpp

// 节练习 9.31 (list)
// chapter9_3.cpp
#include <iostream>
#include <list>
using namespace std;
// using std::forward_list;

int erase_and_add_data(list<int>l) {
    cout << "erase_and_add_data..." <<endl;
    list<int>::iterator current = l.begin();

    // 查找并插入字符串
    while (current != l.end())
    {
        if (*current % 2 == 0) { // 偶数
            current = l.erase(current); // 迭代器返回一个指向呗删元素之后元素的迭代器
        }  else { // 奇数
            current = l.insert(current,*current); // 迭代器返回一个指向最后一个插入元素的迭代器
            cout << "data is " << *current << endl;
            current = next(current ,2);
        }
    }
   
   // 打印
    current = l.begin();
    cout << "list data is " ;
    while (current != l.end())
    {
        cout << *current << " ";
        current ++;
    }
    cout << endl;
    return 0;
}

int main()
{
    list<int> l1 = {5, 1, 1, 2, 3, 4, 8, 12, 21, 55, 89 };
    /* list 容器next方法:current = l1.begin()对应的迭代器所指的元素是5。
    next(current, 16)返回迭代器所指元素是3;
    next(current, 10)返回迭代器所指元素是89,与l1.end()不相等;
    next(current, 10)返回迭代器所指元素是11(是容器列表中元素个数),与l1.end()相等。
    其他容器的next用法还没研究,也就是说使用next方法时,要计算迭代器的步移要小于容器当前迭代器到尾迭代器的距离。

    list<int>::iterator current = l1.begin();
    current = next(current , 11);
    if (current == l1.end()) {
        cout << "=======" << *current << endl;
    }else {
        cout << "=======!!!!!!!!!!!!!!" << *current << endl;
    }
    */
    erase_and_add_data(l1);

    return 0;
}
// 编译 g++ -std=c++11 -o chapter9_3  chapter9_3.cpp

节练习 9.37: 为什么list或array没有capacity成员函数。

deepseek 回答:

1.链表是动态分配的:每个元素单独分配内存(节点包含数据和前后指针)

2.不需要预分配内存:每次插入只需为新节点分配内存,无需为后续元素预留空间

3.内存不连续:不需要像 vector 那样维护连续的存储空间

4.每次插入都是 O(1):不需要重新分配内存和移动现有元素

复制代码
// 节练习 9.41(来自deepseek)
// chapter9_4.cpp
#include <iostream>
#include <vector>
#include <string>
#include <algorithm>  // 用于std::copy

// 方法1:使用迭代器构造函数(最安全、最推荐)
std::string vectorToString1(const std::vector<char>& vec) {
    return std::string(vec.begin(), vec.end());
}

// 方法2:使用data()和size()(C++11,高效)
std::string vectorToString2(const std::vector<char>& vec) {
    if (vec.empty()) {
        return "";
    }
    return std::string(vec.data(), vec.size());
}

// 方法3:使用指针(兼容旧代码)
std::string vectorToString3(const std::vector<char>& vec) {
    if (vec.empty()) {
        return "";
    }
    return std::string(&vec[0], vec.size());
}

// 方法4:使用std::accumulate(函数式风格)
#include <numeric>
std::string vectorToString4(const std::vector<char>& vec) {
    return std::accumulate(vec.begin(), vec.end(), std::string());
}

// 方法5:手动构建(教育目的)
std::string vectorToString5(const std::vector<char>& vec) {
    std::string result;
    result.reserve(vec.size());  // 预分配内存提高效率
    for (char c : vec) {
        result += c;
    }
    return result;
}

// 测试函数
void testAllMethods() {
    std::vector<char> vec = {'H', 'e', 'l', 'l', 'o', ' ', 'C', '+', '+'};
    std::vector<char> empty_vec;
    std::vector<char> null_terminated = {'T', 'e', 's', 't', '\0', 'i', 'g', 'n', 'o', 'r', 'e'};
    
    std::cout << "=== 测试正常vector ===" << std::endl;
    std::cout << "方法1: \"" << vectorToString1(vec) << "\"" << std::endl;
    std::cout << "方法2: \"" << vectorToString2(vec) << "\"" << std::endl;
    std::cout << "方法3: \"" << vectorToString3(vec) << "\"" << std::endl;
    std::cout << "方法4: \"" << vectorToString4(vec) << "\"" << std::endl;
    std::cout << "方法5: \"" << vectorToString5(vec) << "\"" << std::endl;
    
    std::cout << "\n=== 测试空vector ===" << std::endl;
    std::cout << "方法1: \"" << vectorToString1(empty_vec) << "\"" << std::endl;
    std::cout << "方法2: \"" << vectorToString2(empty_vec) << "\"" << std::endl;
    std::cout << "方法3: \"" << vectorToString3(empty_vec) << "\"" << std::endl;
    
    std::cout << "\n=== 测试包含null字符的vector ===" << std::endl;
    std::cout << "注意:如果vector中包含'\\0',构造string时可能会截断" << std::endl;
    std::string str(null_terminated.data());  // 危险:会停在第一个'\0'
    std::cout << "使用data()直接构造: \"" << str << "\" (长度: " << str.length() << ")" << std::endl;
    
    // 正确处理包含null字符的vector
    std::string safe_str(null_terminated.begin(), null_terminated.end());
    std::cout << "使用迭代器安全构造: 长度 = " << safe_str.length() 
              << ", 包含 " << std::count(safe_str.begin(), safe_str.end(), '\0') 
              << " 个null字符" << std::endl;
}

// 性能测试示例
#include <chrono>

void performanceTest() {
    const int SIZE = 1000000;
    std::vector<char> large_vec(SIZE, 'x');  // 100万个'x'
    
    auto start = std::chrono::high_resolution_clock::now();
    std::string str(large_vec.begin(), large_vec.end());
    auto end = std::chrono::high_resolution_clock::now();
    
    auto duration = std::chrono::duration_cast<std::chrono::microseconds>(end - start);
    std::cout << "\n性能测试 - 构造 " << SIZE << " 个字符的字符串:" << std::endl;
    std::cout << "耗时: " << duration.count() << " 微秒" << std::endl;
    std::cout << "字符串长度: " << str.length() << std::endl;
}

int main() {
    testAllMethods();
    // performanceTest();
    
    return 0;
}
// 编译 g++ -std=c++11 -o chapter9_4  chapter9_4.cpp

// 节练习 9.42(来自deepseek)
// chapter9_4.cpp
#include <iostream>
using namespace std;
string readCharsOptimized(int min_chars) {
    string result;
    result.reserve(min_chars);  // 关键优化
    
    char ch;
    for (int i = 0; i < min_chars; ++i) {
        ch = cin.get();
        result.push_back(ch);  // 高效追加
    }
    
    return result;  // 可能启用返回值优化(RVO)
}

int main() {
    readCharsOptimized(100);
    return 0;
}
// 编译 g++ -std=c++11 -o chapter9_4  chapter9_4.cpp

// 节练习 9.43
// chapter9_4.cpp
#include <iostream>
using namespace std;

void insert_and_erase(string s, string oldVal, string newVal)
{
    string::iterator it = s.begin(); // 原字符串迭代器
    size_t o_len = oldVal.size();    // 被替换字符串长度
    size_t n_len = newVal.size();    // 新字符串长度
    string word;

    while (it != s.end() && (s.end() - it) >= o_len)
    {
        word.clear();
        word.append(it, it + o_len);
        //    cout << "2 word is " << word<< endl;
        if (word == oldVal)
        {
            it = s.erase(it, it + o_len); //  返回的迭代器指向删除的元素之后的元素(删除第一个"nihao"之后,返回迭代器在" "位置)
            it = s.insert(it, newVal.begin(), newVal.end()); // 在当前迭代器之前插入元素,返回指向第一个插入字符的迭代器(添加"hello"之后,返回迭代器在h位置)
            it = it + n_len;

            // cout << "1 it is " << *it << endl;
        }
        else
        {
            it++;
        }
    }

    cout << "result str is " << s << endl;
}

int main()
{
    string str = "nihao good apple pear string pos low hign nihao name nihao";
    string o_str = "nihao";
    string n_str = "hello";
    insert_and_erase(str, o_str, n_str);
    return 0;
}
// 编译 g++ -std=c++11 -o chapter9_4  chapter9_4.cpp

// 节练习 9.44
// chapter9_4.cpp
#include <iostream>
using namespace std;

void insert_and_erase(string s, string oldVal, string newVal)
{
    size_t pos = 0; // 下标位置
    size_t s_len = s.size(); // 原字符串长度
    size_t o_len = oldVal.size();    // 被替换字符串长度
    size_t n_len = newVal.size();    // 新字符串长度
    string word;

    while ((pos + o_len) < s_len)
    {
        word.clear();
        word.append(s,pos,o_len);
        // cout << "2 word is " << word<< endl;
        if (word == oldVal)
        {
            s.replace(pos,o_len,newVal);
            pos = pos + o_len;

            // cout << "1 it is " << *it << endl;
        }
        else
        {
            pos ++;
        }
    }

    cout << "2 result str is " << s << endl;
}

int main()
{
    string str = "nihao good apple pear string pos low hign nihao name nihao";
    string o_str = "nihao";
    string n_str = "hello";
    insert_and_erase(str, o_str, n_str);
    return 0;
}
// 编译 g++ -std=c++11 -o chapter9_4  chapter9_4.cpp

// 节练习 9.45
// chapter9_4.cpp
#include <iostream>
using namespace std;

string insert_and_append(string _name, string _pre, string _near)
{
    string::iterator name_it = _name.begin();
    name_it = _name.insert(name_it,_pre.begin(),_pre.end());
    _name.append(_near);
    return _name;
}

int main()
{
    string name = "liuRY";
    string pre = "Ms.";
    string near = ".Jr";
    cout << "result name is " << insert_and_append(name, pre, near)<< endl;
    return 0;
}
// 编译 g++ -std=c++11 -o chapter9_4  chapter9_4.cpp

// 节练习 9.46
// chapter9_4.cpp
#include <iostream>
using namespace std;

string insert_and_append(string _name, string _pre, string _near)
{
    size_t name_len = _name.size();
    size_t pre_len = _pre.size();

    _name.insert(0,_pre);
    _name.insert(name_len + pre_len,_near);
    return _name;
}

int main()
{
    string name = "liuRY";
    string pre = "Ms.";
    string near = ".Jr";
    cout << "2 result name is " << insert_and_append(name, pre, near)<< endl;
    return 0;
}
// 编译 g++ -std=c++11 -o chapter9_4  chapter9_4.cpp

// 节练习 9.47
// chapter9_4.cpp
#include <iostream>
using namespace std;

int main()
{
    string numbers("0123456789");
    string str("ab3c3d7R4E60a");
    size_t len = str.size();
    size_t pos = 0;
    while(pos < len) {
        pos = str.find_first_of(numbers,pos); // pos = str.find_first_not_of(numbers,pos);
        // cout << "pos_t = " << pos<< endl;
        if (pos < len) {
            cout << "data = " << str[pos]<< endl;
            pos ++;
        } else {
            break;
        }
    }
    
    return 0;
}
// 编译 g++ -std=c++11 -o chapter9_4  chapter9_4.cpp

// 节练习 9.49
// chapter9_4.cpp
#include <iostream>
#include <sstream>
using namespace std;

int main()
{ 
    // string z1("acemnorsuvwxz");
    string z2("bdfghijklpqty");
    string str("transform  proceed  accc accelerate diminish fluctuate aa ambitious compassionate determined enthusiastic resilientalgorithm acc algorithm accccccccc blockchain cybersecurity database encryption");
    string word;
    string word_t;
    size_t len = 0;;
    size_t len_t = 0;
    size_t pos = 0;
    istringstream is(str);
    while (is >> word_t)
    {
        len_t = word_t.size();
        pos = word_t.find_first_of(z2);
        if (pos >= len_t && len_t > len) { // 单词中不包含z2中的字符
            len = len_t;
            word.clear();
            word.append(word_t);
        }
    }

    cout << "word is " << word << ",len is " << len << endl;
    return 0;
}
// 编译 g++ -std=c++11 -o chapter9_4  chapter9_4.cpp

// 节练习 9.50(1)
// chapter9_4.cpp
#include <iostream>
#include <vector>
using namespace std;

int main()
{ 
    // string z1("acemnorsuvwxz");
   vector<string> v({"1","2","3","4","5","6","7","8","9","10","11","12","13","14","15","16","17","18","19","20"});
   vector<string>::iterator it = v.begin();
   int sum = 0;
    while (it != v.end())
    {
        int num = stoi(*it);
        sum += num;
        it ++;
    }

    cout << "sum is " << sum  << endl;
    return 0;
}
// 编译 g++ -std=c++11 -o chapter9_4  chapter9_4.cpp

// 节练习 9.50(2)
// chapter9_4.cpp
#include <iostream>
#include <vector>
using namespace std;

int main()
{ 
    // string z1("acemnorsuvwxz");
   vector<string> v({"1.1","2.2","3.3","4.4","5.5","6.6","7.7","8.8","9.9","10.1","11.2","12.3","13.4","14.5","15.6","16.7","17.8","18.9","19.1","20.2"});
   vector<string>::iterator it = v.begin();
   float sum = 0;
    while (it != v.end())
    {
        float num = stof(*it);
        sum += num;
        it ++;
    }

    cout << "sum is " << sum  << endl;
    return 0;
}
// 编译 g++ -std=c++11 -o chapter9_4  chapter9_4.cpp

// 节练习 9.51(deepseek 生成)
// chapter9_4.h
#include <iostream>
#include <string>
#include <vector>
#include <map>
#include <sstream>
#include <cctype>
#include <stdexcept>
#include <algorithm>

class Date {
private:
    unsigned year;
    unsigned month;
    unsigned day;
    
    // 月份名称映射
    static std::map<std::string, unsigned> monthMap;
    static bool mapsInitialized;
    
    // 初始化月份映射
    static void initializeMaps() {
        if (mapsInitialized) return;
        
        // 完整月份名
        monthMap["january"] = 1;
        monthMap["february"] = 2;
        monthMap["march"] = 3;
        monthMap["april"] = 4;
        monthMap["may"] = 5;
        monthMap["june"] = 6;
        monthMap["july"] = 7;
        monthMap["august"] = 8;
        monthMap["september"] = 9;
        monthMap["october"] = 10;
        monthMap["november"] = 11;
        monthMap["december"] = 12;
        
        // 缩写月份名
        monthMap["jan"] = 1;
        monthMap["feb"] = 2;
        monthMap["mar"] = 3;
        monthMap["apr"] = 4;
        monthMap["may"] = 5;
        monthMap["jun"] = 6;
        monthMap["jul"] = 7;
        monthMap["aug"] = 8;
        monthMap["sep"] = 9;
        monthMap["oct"] = 10;
        monthMap["nov"] = 11;
        monthMap["dec"] = 12;
        
        mapsInitialized = true;
    }
    
    // 辅助函数:转换为小写
    static std::string toLower(const std::string& str) {
        std::string result = str;
        std::transform(result.begin(), result.end(), result.begin(), 
                      [](unsigned char c) { return std::tolower(c); });
        return result;
    }
    
    // 辅助函数:去除字符串两端的空白字符
    static std::string trim(const std::string& str) {
        size_t first = str.find_first_not_of(" \t\n\r");
        if (first == std::string::npos) return "";
        size_t last = str.find_last_not_of(" \t\n\r");
        return str.substr(first, last - first + 1);
    }
    
    // 辅助函数:分割字符串
    static std::vector<std::string> split(const std::string& str, char delimiter) {
        std::vector<std::string> tokens;
        std::string token;
        std::istringstream tokenStream(str);
        while (std::getline(tokenStream, token, delimiter)) {
            token = trim(token);
            if (!token.empty()) {
                tokens.push_back(token);
            }
        }
        return tokens;
    }
    
    // 验证日期是否有效
    bool isValidDate(unsigned y, unsigned m, unsigned d) {
        if (m < 1 || m > 12) return false;
        if (d < 1 || d > 31) return false;
        
        // 检查月份天数
        int daysInMonth[] = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
        
        // 闰年处理
        if (m == 2) {
            bool isLeapYear = (y % 400 == 0) || (y % 4 == 0 && y % 100 != 0);
            if (isLeapYear) daysInMonth[1] = 29;
        }
        
        return d <= daysInMonth[m - 1];
    }
    
    // 设置日期
    void setDate(unsigned y, unsigned m, unsigned d) {
        if (!isValidDate(y, m, d)) {
            throw std::invalid_argument("Invalid date");
        }
        year = y;
        month = m;
        day = d;
    }
    
    // 解析数字格式的日期 (MM/DD/YYYY 或 YYYY-MM-DD 等)
    bool parseNumericFormat(const std::string& dateStr) {
        std::string cleaned = dateStr;
        
        // 替换可能的日期分隔符为空格
        std::replace_if(cleaned.begin(), cleaned.end(), 
                       [](char c) { return c == '/' || c == '-' || c == '.' || c == ','; }, ' ');
        
        auto tokens = split(cleaned, ' ');
        if (tokens.size() != 3) return false;
        
        unsigned m, d, y;
        
        try {
            // 尝试格式 MM/DD/YYYY 或 DD/MM/YYYY
            m = std::stoul(tokens[0]);
            d = std::stoul(tokens[1]);
            y = std::stoul(tokens[2]);
            
            // 检查年份是否为2位数(假设是1900-1999)
            if (y < 100) {
                y += 1900; // 可以根据需求调整这个逻辑
            }
            
            // 尝试两种可能的顺序
            if (isValidDate(y, m, d)) {
                setDate(y, m, d);
                return true;
            }
            
            // 尝试交换月和日
            if (isValidDate(y, d, m)) {
                setDate(y, d, m);
                return true;
            }
            
        } catch (const std::exception&) {
            return false;
        }
        
        return false;
    }
    
    // 解析月份名称格式的日期
    bool parseMonthNameFormat(const std::string& dateStr) {
        auto tokens = split(dateStr, ' ');
        if (tokens.size() < 3) return false;
        
        std::string monthStr = toLower(tokens[0]);
        std::string dayStr = tokens[1];
        std::string yearStr = tokens[2];
        
        // 处理日期中的逗号 (如 "January 1, 1900")
        if (dayStr.back() == ',') {
            dayStr = dayStr.substr(0, dayStr.length() - 1);
        }
        
        // 如果第二部分是逗号,调整token索引
        if (tokens.size() > 3 && tokens[1] == ",") {
            monthStr = toLower(tokens[0]);
            dayStr = tokens[2];
            yearStr = tokens[3];
        }
        
        // 查找月份
        auto it = monthMap.find(monthStr);
        if (it == monthMap.end()) return false;
        
        try {
            unsigned m = it->second;
            unsigned d = std::stoul(dayStr);
            unsigned y = std::stoul(yearStr);
            
            // 处理2位数年份
            if (y < 100) {
                y += 1900;
            }
            
            if (isValidDate(y, m, d)) {
                setDate(y, m, d);
                return true;
            }
        } catch (const std::exception&) {
            return false;
        }
        
        return false;
    }

public:
    // 默认构造函数
    Date() : year(1900), month(1), day(1) {
        initializeMaps();
    }
    
    // 主要构造函数
    Date(const std::string& dateStr) {
        initializeMaps();
        
        if (dateStr.empty()) {
            throw std::invalid_argument("Date string cannot be empty");
        }
        
        std::string trimmed = trim(dateStr);
        
        // 尝试月份名称格式
        if (parseMonthNameFormat(trimmed)) {
            return;
        }
        
        // 尝试数字格式
        if (parseNumericFormat(trimmed)) {
            return;
        }
        
        throw std::invalid_argument("Unable to parse date string: " + dateStr);
    }
    
    // 带参数的构造函数
    Date(unsigned y, unsigned m, unsigned d) {
        setDate(y, m, d);
    }
    
    // 获取器
    unsigned getYear() const { return year; }
    unsigned getMonth() const { return month; }
    unsigned getDay() const { return day; }
    
    // 格式化输出
    std::string toString() const {
        std::ostringstream oss;
        oss << year << "-" 
            << (month < 10 ? "0" : "") << month << "-"
            << (day < 10 ? "0" : "") << day;
        return oss.str();
    }
    
    // 友元输出操作符
    friend std::ostream& operator<<(std::ostream& os, const Date& date) {
        os << date.toString();
        return os;
    }
};

// chapter9_4.cpp
#include "chapter9_4.h"
// 静态成员初始化
std::map<std::string, unsigned> Date::monthMap;
bool Date::mapsInitialized = false;

// 测试函数
int main() {
    try {
        // 测试不同的日期格式
        std::vector<std::string> testDates = {
            "January 1, 1900",
            "1/1/1990",
            "Jan 1 1900",
            "1990-01-01",
            "12/25/2023",
            "December 25, 2023",
            "25.12.2023",
            "Feb 28, 2020",  // 闰年
            "March 15, 2000",
            "7/4/1776"
        };
        
        std::cout << "Testing Date class with various formats:\n";
        std::cout << "=========================================\n";
        
        for (const auto& dateStr : testDates) {
            try {
                Date date(dateStr);
                std::cout << "Original: \"" << dateStr << "\"\n";
                std::cout << "Parsed:   " << date.toString() << "\n";
                std::cout << "Components: Year=" << date.getYear() 
                          << ", Month=" << date.getMonth() 
                          << ", Day=" << date.getDay() << "\n";
                std::cout << "---\n";
            } catch (const std::exception& e) {
                std::cout << "Error parsing \"" << dateStr << "\": " 
                          << e.what() << "\n";
                std::cout << "---\n";
            }
        }
        
        // 测试无效日期
        std::cout << "\nTesting invalid dates:\n";
        std::cout << "======================\n";
        
        std::vector<std::string> invalidDates = {
            "February 30, 2023",  // 无效日期
            "13/1/2023",          // 无效月份
            "January 32, 2023",   // 无效日期
            "Not a date",         // 无效格式
            "Jan/1/2023"          // 混合格式
        };
        
        for (const auto& dateStr : invalidDates) {
            try {
                Date date(dateStr);
                std::cout << "Unexpectedly parsed: \"" << dateStr << "\" as " 
                          << date.toString() << "\n";
            } catch (const std::exception& e) {
                std::cout << "Correctly rejected \"" << dateStr << "\": " 
                          << e.what() << "\n";
            }
        }
        
    } catch (const std::exception& e) {
        std::cerr << "Error: " << e.what() << std::endl;
        return 1;
    }
    
    return 0;
}

编译: g++ -std=c++11 -o chapter9_4  chapter9_4.cpp

// 节练习 9.52
没看明白题。
相关推荐
特立独行的猫a2 小时前
c++弱引用指针std::weak_ptr作用详解
开发语言·c++·智能指针·弱指针·weak_ptr
小菱形_2 小时前
【C#】IEnumerable
开发语言·c#
爱敲点代码的小哥2 小时前
Directoy文件夹操作对象 、StreamReader和StreamWriter 和BufferedStream
开发语言·c#
这是程序猿2 小时前
基于java的ssm框架经典电影推荐网站
java·开发语言·spring boot·spring·经典电影推荐网站
Nan_Shu_6142 小时前
学习:Java (1)
java·开发语言·学习
李慕婉学姐2 小时前
【开题答辩过程】以《基于PHP的饮食健康管理系统设计与实现》为例,不知道这个选题怎么做的,不知道这个选题怎么开题答辩的可以进来看看
开发语言·php
李慕婉学姐2 小时前
【开题答辩过程】以《基于PHP的养老中心管理系统的设计与实现》为例,不知道这个选题怎么做的,不知道这个选题怎么开题答辩的可以进来看看
开发语言·php
曹牧2 小时前
Java:String.startsWith 方法
java·开发语言
秃然想通2 小时前
Java多态完全指南:深入理解“一个接口,多种实现”
java·开发语言