transform函数转换大小写

本文介绍如何使用C++标准库中的transform函数配合lambda表达式或自定义函数来实现字符串的大写和小写转换,避免使用被定义为宏的toupper和tolower函数带来的问题。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

新版 2018/7/3更新
直接使用transform函数,第四个参数使用lambda表达式即可
代码如下:

    transform(word.begin(),word.end(),new_word.begin(),[](char c)->char { return toupper(c);});

这样就行了。变量word是旧字符串,new_word是新字符串。


旧版

C++中没有提供对string串进行直接大小写转换的函数,只能采用toupper & tolower函数对单个字符进行转换;

可以使用STL中的algorithm头文件中函数实现;

< algorithm > : transform函数

transform参数如下:

/*////////////////////////////////
    template < class InputIterator, class OutputIterator, class UnaryOperator >
      OutputIterator transform ( InputIterator first1,  // 源容器的起始地址
                                InputIterator last1,    // 源容器的终止地址
                                OutputIterator result,  // 目标容器的起始地址
                                UnaryOperator op );     // 函数指针
    // typedef 目标容器元素类型 (*UnaryOperator)(源容器元素类型);

    template < class InputIterator1, class InputIterator2,
               class OutputIterator, class BinaryOperator >
      OutputIterator transform ( InputIterator1 first1,     // 源容器1的起始地址
                                InputIterator1 last1,       // 源容器1的终止地址
                                InputIterator2 first2,      // 源容器2的起始地址,元素个数与1相同
                                OutputIterator result,      // 目标容器的起始地址,元素个数与1相同
                                BinaryOperator binary_op ); // 函数指针
    // typedef 目标容器元素类型 (*BinaryOperator)(源容器1元素类型,源容器2元素类型);
    //*////////////////////////////////

注意:(错误演示)

#include <iostream>
#include <string>
#include <algorithm>
using namespace std;
int main()
{
    string word;
    cin>>word;
    transform(word.begin(), word.end(), word.begin(), toupper);//转换成大写
    cout<<word<<endl;
    return 0;
}

但在使用g++编译时会报错:
提示:对 transform的调用没有匹配的函数。
这里出现错误的原因是Linux将toupper实现为一个宏而不是函数:
/usr/lib/syslinux/com32/include/ctype.h:

/* Note: this is decimal, not hex, to avoid accidental promotion to unsigned */
#define _toupper(__c) ((__c) & ~32)
#define _tolower(__c) ((__c) | 32)
__ctype_inline int toupper(int __c)
{
return islower(__c) ? _toupper(__c) : __c;
}
__ctype_inline int tolower(int __c)
{
return isupper(__c) ? _tolower(__c) : __c;
}

可以看到,在Linux的g++编译器中,将tolower设置为一个宏,并不是一个函数,何谈函数指针呢,所以参数4不可以直接使用tolower和toupper;


具体实现如下:

方法一:

#include <iostream>
#include<unordered_map>
#include<set>
#include<string>
#include<algorithm>
using namespace std;

/*统计输入字符串中的特定单词的个数
    或者统计除特定单词之外的个数(忽略标点符号)
    忽略大小写(转换成小写)
*/

/** transform(word.begin(),word.end(),t_word.begin(),to_lower)
 *
 * \param 1: 源容器的起始地址
 * \param 2:源容器的终止地址
 * \param 3: 目标容器的起始地址,容器大小和源容器相同,resize()重新设置
 * \param 4:  函数指针
 * \return :none
 * \notice: 第四个参数一定要是个函数指针,不能为tolower;要自己定义函数
            这里出现错误的原因是Linux将toupper实现为一个宏而不是函数:/usr/lib/syslinux/com32/include/ctype.h:
 */

char to_lower(char c)
{
    return tolower(c);
}

char to_upper(char c)
{
    return toupper(c);
}

int main()
{
    unordered_map<string,int> m;
    set<string> s {"!",",",":"};//标点符号
    string word;
    string t_word;//转换成小写的Word
    cin>>word;
    while(word != "0")
    {
        t_word.resize(word.size());//!!!将t_word调整为和Word相同的大小;因为transform需要两个相同大小的string
        transform(word.begin(),word.end(),t_word.begin(),to_lower);

        if(s.find(t_word) == s.end())//find()返回一个迭代器,仅当Word在set中的时候,返回该元素的迭代器;否则,返回尾后迭代器。
        {
            m[t_word]++;
        }

        cin>>word;
    }
    for(auto it=m.begin(); it != m.end(); ++it)
    {
        cout<<it->first<<"  occurs  "<<it->second << ((it->second >1) ? "  times":"  time" )<< endl;
    }
    return 0;
}

方法二:

另外,看到一个博主有另一种方法,在这里也贴出来:

#include <iostream> 
#include <string>
#include <algorithm>
#include <iterator>
#include <cctype>

using namespace std;

int main() 
{
    string src = "Hello World!";
    string dst;

    transform(src.begin(), src.end(), back_inserter(dst), ::toupper);
    cout << dst << endl;

    transform(src.begin(), src.end(), dst.begin(), ::tolower);
    cout << dst << endl;

    return 0;
 }

使用了back_inserter;


本文参考了:
http://www.cnblogs.com/KeenLeung/archive/2013/03/17/2965192.html
http://blog.youkuaiyun.com/loushuai/article/details/51289345

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值