std :: replace的逻辑错误

时间:2018-04-10 14:28:20

标签: c++ string algorithm stl

今天我在学校项目上遇到了一个逻辑错误。对于此项目,需要切换chars

比如说,用户输入字母A。它切换到U,一切都很顺利。但是,当用户输入字母U时会出现此问题。角色保持不变。我已实施了两条规则,可以从A切换为UU再转换为A。字符串通过两个规则,因此不变。我怎么能阻止这个?

#include <iostream>
#include <algorithm>
#include <string>

using namespace std;

int main()
{
 string seq;
 getline(cin, seq);

 transform ( seq.begin(), seq.end(), seq.begin(), ::toupper );

 replace ( seq.begin(), seq.end(), 'A', 'U' );
 replace ( seq.begin(), seq.end(), 'U', 'A' );

 cout << seq;
 return 0;
}

2 个答案:

答案 0 :(得分:10)

根据您的实施,您将A替换为U,然后将U 替换为 A

replace ( seq.begin(), seq.end(), 'A', 'U' );
replace ( seq.begin(), seq.end(), 'U', 'A' );

您需要在一次通过中进行替换,例如使用std::transform

std::transform(begin(seq), end(seq), begin(seq), some_function_object);

你只需写下这个神秘的some_function_object。它可以是一个自由功能:

char some_function_object(char input) { /* ... */ }
std::transform(begin(seq), end(seq), begin(seq), some_function_object);

或lambda函数:

std::transform(begin(seq), end(seq), begin(seq), [](char input) { /* ... */ } );

此函数对象必须采用char并返回:

  • A如果inputU;
  • U如果inputA;
  • input否则。

如果它是一个自由函数,你应该怎么称呼?那么,为什么不是像swapAandU这样的自我描述性名称?

答案 1 :(得分:2)

似乎情况是基于范围的for循环比使用标准算法更好,更有效,例如std :: transform。

例如

#include <iostream>
#include <string>

int main() 
{
    std::string s( "AUAUA" );

    std::cout << s << std::endl;

    for ( char &c : s )
    {
        if ( c == 'A' ) c = 'U';
        else if ( c == 'U' ) c = 'A';
    }

    std::cout << s << std::endl;

    return 0;
}

程序输出

AUAUA
UAUAU

您可以编写单独的函数,例如

#include <iostream>
#include <string>

std::string & convert( std::string &s1, const std::string &s2, const std::string &s3 )
{
    for ( char &c : s1 )
    {
        auto i = s2.find( c );
        if ( i != std::string::npos ) c = s3[i]; 
    }

    return s1;
}

int main() 
{
    std::string s( "AUAUA" );

    std::cout << s << std::endl;

    std::cout << convert( s, "AU", "UA" ) << std::endl;

    return 0;
}

如果字符串s2已排序,那么您可以使用二进制搜索算法而不是线性搜索。

如果你想使用标准算法,那么在我看来,最合适的算法是std::for_each,它与基于范围的for循环相对应。例如,可以使用以下方式的算法重写第一个演示程序

#include <iostream>
#include <string>
#include <algorithm>

int main() 
{
    std::string s( "AUAUA" );

    std::cout << s << std::endl;

    std::for_each( s.begin(), s.end(), 
        []( char &c ) 
        { 
            if ( c == 'A' ) c = 'U';
            else if ( c == 'U' ) c = 'A';
        } );

    std::cout << s << std::endl;

    return 0;
}