String manipulation

Dec 26, 2010 at 1:57am
How do you change a letter of a string to another and how do you invert the letters of a string?

Exemple:
Francisco -> FrXncXscX
Francisco -> ocsicnarF
Dec 26, 2010 at 2:23am
To change a letter in a string:

1
2
3
4
5
6
7
char* str="The bird called to its mate";
//change the letters
str[4]='g';
str[5]='o';
str[6]='a';
str[7]='t';
cout<<str;
The goat called to its mate

To invert a string, you would need to use the concept above in a function:
1
2
3
4
5
6
7
8
char* reverse(char* str){
    unsigned size=strlen(str);
    unsigned x;
    for(x=0;x<size;++x,--size){
        str[x]^=str[size];
        str[size]^=str[x];
        str[x]^=str[size];}
    return str;}
Last edited on Dec 26, 2010 at 2:30am
Dec 26, 2010 at 2:49am
Isn't there a string function for this problem? I'm doing the exercise of the forum 'Strings are your friends, until they betray you'. The question says that strings and string functions are requirable.
Dec 26, 2010 at 2:57am
I would use find() and replace() if you want to be generic, and reverse iterators (rbegin(), rend()) to go backwards.
Dec 26, 2010 at 4:11am
1
2
3
4
5
6
7
8
char* reverse(char* str){
    unsigned size=strlen(str);
    unsigned x;
    for(x=0;x<size;++x,--size){
        str[x]^=str[size]; //NOOO!!
        str[size]^=str[x]; //WHYY??
        str[x]^=str[size];}//AAAA!!
    return str;}

What the heck is this? I see that it must work, but why this convoluted bit logic?

Dec 26, 2010 at 4:33am
so you don't need an extra variable.
And I think that the xor operation is shorter and faster than move.

If it is encapsulated, who cares? You will need to provide the ^= operator for user types (that doesn't make sense).

you could create a replace_if with transform.
or just loop over your string with find_first_of
Last edited on Dec 26, 2010 at 4:43am
Dec 26, 2010 at 5:22am
Well, with the variable it can be optimized to a XCHG instruction with a register. Yours is too un-obvious for that.
Last edited on Dec 26, 2010 at 5:25am
Dec 26, 2010 at 5:41am
Ok. I've gprof'd it and I surrender.
given this code
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
#include <string.h> 

char* weirdstrrev(char* str){
    unsigned size=strlen(str);
    unsigned x;
    for(x=0;x<size;++x,--size){
        str[x]^=str[size]; //NOOO!!
        str[size]^=str[x]; //WHYY??
        str[x]^=str[size];}//AAAA!!
    return str;}
    
char* normalstrrev(char* str){
	unsigned size=strlen(str);
	unsigned x;
	for(x=0;x<size;++x,--size){char c=str[x];str[x]=str[size];str[size]=c;}
	return str;
}

int main(void)
{
	char x[30]="this is a test of the swap.";
	register int i=100000000;
	while(i--)weirdstrrev(x);
	i=100000000;
	while(i--)normalstrrev(x);
}

with O2 optimization,
gprof shows your code is 7% faster:
Each sample counts as 0.01 seconds.
  %   cumulative   self              self     total           
 time   seconds   seconds    calls  ns/call  ns/call  name    
 39.34      0.72     0.72 100000000     7.20     7.20  normalstrrev
 36.61      1.39     0.67 100000000     6.70     6.70  weirdstrrev
 24.04      1.83     0.44                             main
-----------------------------------------------

Last edited on Dec 26, 2010 at 5:55am
Dec 26, 2010 at 6:24am
Here is the program. It's very complicated by the fact of string be a class we can't see. Does someone known an easier way?

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
#include <iostream>
#include <conio.h>
#include <string>

using namespace std;

int main() {
    string firstname, lastname;
    size_t found;
    
    cout << "Enter your first name: ";
    cin >> firstname;
    cout <<  "Enter your last name: ";
    cin >>  lastname;
    
    cout << "\n";
    
    string::reverse_iterator rit;
    for (rit = lastname.rbegin(); rit < lastname.rend(); rit++)
        cout << *rit;
    cout << " ";
    for (rit = firstname.rbegin(); rit < firstname.rend(); rit++)
        cout << *rit;
    
    cout << "\n";
    
    cout << "\n" << firstname << " " << lastname << endl;
    
    found = firstname.find_first_of("aeiou");
          while (found != string::npos) {
                firstname[found] = 'z';
                found = firstname.find_first_of("aeiou", found + 1);
          }
    found = lastname.find_first_of("aeiou");
          while (found != string::npos) {
                lastname[found] = 'z';
                found = lastname.find_first_of("aeiou", found + 1);
          }
          
    cout << firstname << " " << lastname << endl;
    
    getch();
    return 0;
}

Dec 26, 2010 at 8:24am
seems familiar: http://www.cplusplus.com/forum/beginner/33124/#msg178184
Dunno if there is a "simpler" way, but your code will be cleaner if you create a function.
1
2
3
4
void subs( std::string &, const std::string &, char );

subs( firstname, "aeiou", 'z' );
subs( lastname, "aeiou", 'z' );
Last edited on Dec 26, 2010 at 8:26am
Topic archived. No new replies allowed.