c++方法 原创

在这里插入图片描述

std::transform方法

std::transform 是 C++ 标准库算法中的一个非常有用的函数,它定义在头文件 中。这个函数用于将给定范围内的每个元素按照指定的操作进行转换,并将转换结果存储在另一个位置(可以是原始范围的另一个容器,或者完全不同的位置)。std::transform 提供了一个灵活的方式来对容器中的元素进行批量处理,而无需显式地遍历每个元素。

函数原型
std::transform 有几个重载版本,但最基本的原型如下:

cpp
template< class InputIt, class OutputIt, class UnaryOperation >
OutputIt transform( InputIt first1, InputIt last1, OutputIt d_first, UnaryOperation unary_op );

template< class InputIt1, class InputIt2, class OutputIt, class BinaryOperation >
OutputIt transform( InputIt1 first1, InputIt1 last1, InputIt2 first2,
OutputIt d_first, BinaryOperation binary_op );
Unary Operation 版本:接受一个输入范围([first1, last1)),一个输出迭代器(d_first),和一个一元操作函数(unary_op)。对于输入范围内的每个元素,unary_op 都会被应用,并且结果会被写入到由 d_first 指定的输出位置。
Binary Operation 版本:类似于一元操作版本,但它接受两个输入范围([first1, last1) 和 [first2, first2 + (last1 - first1))),这两个范围必须等长。对于每对元素(来自两个输入范围),都会应用一个二元操作函数(binary_op),并将结果写入到输出位置。
示例
一元操作示例:将 std::vector 中的每个元素乘以 2。

cpp

#include <iostream>  
#include <vector>  
#include <algorithm>  
#include <iterator>  
  
int main() {  
    std::vector<int> vec = {1, 2, 3, 4, 5};  
    std::vector<int> result(vec.size());  
  
    std::transform(vec.begin(), vec.end(), result.begin(),  
        [](int i) { return i * 2; });  
  
    for (int num : result) {  
        std::cout << num << ' ';  
    }  
    // 输出: 2 4 6 8 10  
}

二元操作示例:将两个 std::vector 中对应位置上的元素相加。

cpp

#include <iostream>  
#include <vector>  
#include <algorithm>  
#include <iterator>  
  
int main() {  
    std::vector<int> vec1 = {1, 2, 3, 4, 5};  
    std::vector<int> vec2 = {5, 4, 3, 2, 1};  
    std::vector<int> result(vec1.size());  
  
    std::transform(vec1.begin(), vec1.end(), vec2.begin(), result.begin(),  
        [](int a, int b) { return a + b; });  
  
    for (int num : result) {  
        std::cout << num << ' ';  
    }  
    // 输出: 6 6 6 6 6  
}

示例3:std::transform(fileExt.begin(), fileExt.end(),fileExt.begin(), ::toupper);

在 C++ 中,使用 std::transform 来对容器(如 std::string 或其他支持随机访问迭代器的容器)的元素进行转换时,需要注意几个关键点。首先,对于 std::string 来说,虽然它支持随机访问迭代器,但直接在其上原地(in-place)修改(即输出迭代器与输入迭代器相同)可能会导致未定义行为,因为 std::transform 在修改元素时可能会覆盖尚未处理的元素。

对于你的代码片段:

cpp
std::transform(fileExt.begin(), fileExt.end(), fileExt.begin(), ::toupper);
这里有几个问题:

原地修改:如上所述,直接在 std::string 上原地修改可能会不安全,因为 std::transform 在遍历元素时可能会覆盖当前迭代器之后的元素,而迭代器自身也可能因为容器的改变而变得无效。
::toupper 函数的适用性:::toupper 函数需要一个 int 类型的参数,并返回一个 int 类型的值。当用于字符时,它期望输入是 EOF 或无符号字符(在 unsigned char 范围内)的 int 表示。对于 std::string 中的 char 类型,如果 char 是有符号的(这在某些平台上是这样),直接传递 char 到 ::toupper 可能会导致未定义行为,因为负值的 char 会被解释为扩展的 ASCII 码或其他非预期的值。
为了安全地在 std::string 上应用 std::transform 来转换字符到大写,你可以使用以下方法之一:

方法 1:使用临时字符串
创建一个新的 std::string 来存储结果,然后可以将结果赋值回原字符串(如果需要)。

cpp

std::string fileExt = "example.txt";  
std::string upperExt(fileExt.size(), '\0'); // 初始化大小,用 '\0' 填充  
std::transform(fileExt.begin(), fileExt.end(), upperExt.begin(),  
    [](unsigned char c) { return std::toupper(static_cast<unsigned char>(c)); });  
fileExt = upperExt; // 如果需要,将结果赋值回原字符串

注意这里使用了 unsigned char 来确保传递给 std::toupper 的是无符号值。

方法 2:使用标准库中的其他函数(如果适用)
对于 std::string,如果你只是想将所有字符转换为大写,可以使用 std::for_each 配合 std::toupper(但要注意类型转换问题),但更简单的方法是使用 C++17 引入的 std::string 的成员函数 std::transform(注意这不是算法 std::transform):

cpp

#include <algorithm>  
#include <cctype> // 对于 std::toupper  
#include <string>  
  
std::string fileExt = "example.txt";  
std::transform(fileExt.begin(), fileExt.end(), fileExt.begin(),  
    [](unsigned char c) { return std::toupper(static_cast<unsigned char>(c)); });

这里直接在原字符串上操作是安全的,因为 std::string::transform 成员函数是为这种场景设计的。然而,注意这里仍然需要确保传递给 std::toupper 的是无符号值。

注意
确保你的编译器和 C++ 标准库支持你正在使用的特性(如 C++17 的 std::string::transform)。如果你使用的是较旧的编译器或标准库,你可能需要坚持使用第一种方法或寻找其他替代方案。

string方法

unsigned int found = fileI.find_last_of(“.”);

查找最后一个“.”所在的位置

std::string fileExt = fileI.substr(found+1);

截取到found+1位置

c++ string判断是否为空 如果只有空格 也判断为空

在C++中,std::string类并没有直接提供一个成员函数来判断字符串是否仅包含空格(包括空格、制表符、换行符等空白字符)或者为空。但是,你可以通过结合使用std::string的成员函数和一些标准库算法来实现这个功能。

以下是一个简单的函数示例,用于判断一个std::string是否为空或仅包含空白字符:

cpp

#include <iostream>  
#include <string>  
#include <cctype> // std::isspace  
#include <algorithm> // std::find_if_not  
  
bool isStringEmptyOrWhitespace(const std::string& str) {  
    // 使用 std::find_if_not 来查找第一个非空白字符  
    // 如果找不到(即迭代器等于 str.end()),则字符串为空或仅包含空白字符  
    return str.empty() || std::find_if_not(str.begin(), str.end(), ::isspace) == str.end();  
}  
  
int main() {  
    std::string test1 = "";  
    std::string test2 = " ";  
    std::string test3 = "   ";  
    std::string test4 = "Hello";  
    std::string test5 = " \t\n";  
  
    std::cout << std::boolalpha; // 使bool值输出为true/false  
    std::cout << "test1 is empty or whitespace: " << isStringEmptyOrWhitespace(test1) << std::endl;  
    std::cout << "test2 is empty or whitespace: " << isStringEmptyOrWhitespace(test2) << std::endl;  
    std::cout << "test3 is empty or whitespace: " << isStringEmptyOrWhitespace(test3) << std::endl;  
    std::cout << "test4 is empty or whitespace: " << isStringEmptyOrWhitespace(test4) << std::endl;  
    std::cout << "test5 is empty or whitespace: " << isStringEmptyOrWhitespace(test5) << std::endl;  
  
    return 0;  
}

这个函数isStringEmptyOrWhitespace首先检查字符串是否为空(str.empty()),如果不是,则使用std::find_if_not结合std::isspace来查找字符串中第一个不是空白字符的字符。如果找不到这样的字符(即std::find_if_not返回的迭代器等于str.end()),则说明字符串仅包含空白字符或为空。

这种方法简洁且有效,能够处理包括空格、制表符、换行符等在内的多种空白字符。

posted @ 2024-07-11 14:23  一点灯  阅读(0)  评论(0编辑  收藏  举报  来源