today I've encountered a logic error while working on a school project. For this project, switching chars around is required.
Say for example, the user enters the letter A. it is switched to U, and all is well. However, the issue occurs when the user enters the letter U. The character remains untouched. I've implemented two rules to switch from A to U and U to A. The string passes through both of the rules, and therefore is unchanged. How can I prevent this?
#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;
}
With your implementation, you replace A to U then U back to A:
replace ( seq.begin(), seq.end(), 'A', 'U' );
replace ( seq.begin(), seq.end(), 'U', 'A' );
You need to make your replacements in one pass, for instance with std::transform:
std::transform(begin(seq), end(seq), begin(seq), some_function_object);
You just have to write this mysterious some_function_object. It can be a free-function:
char some_function_object(char input) { /* ... */ }
std::transform(begin(seq), end(seq), begin(seq), some_function_object);
or a lambda function:
std::transform(begin(seq), end(seq), begin(seq), [](char input) { /* ... */ } );
This function object must take a char and return:
A if input is U;U if input is A;input otherwise.And how should you call it if its a free function? Well, why not a self-descriptive name like swapAandU?
It seems it is the case when a range-based for loop is better suitable and more efficient than using a standard algorithm as for example std::transform.
For example
#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;
}
The program output is
AUAUA
UAUAU
You can write a separate function as for example
#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;
}
If the string s2 is sorted then you can use the binary search algorithm instead of the linear search.
If you want to use a standard algorithm then in my opinion the most suitable algorithm is std::for_each that correcponds to the range-based for loop. For example the first demonstrative program can be rewritten using the algorithm the following way
#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;
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With