Looping across strings

I need to take a small string (for example: "FK3I) and convert it to "FKIII". As you can see, when a number is found (the number will always be greater than 3, thus there is no "FK2I", only "FKII") I need to take the letter after it and insert that many letters back to the string. I'm not quite sure how to "walk through" a string though. I know I need to set it up something like:
WHILE LOOP
// loop across the characters of the protein
check if the current char is not a digit 
add it to the end of the decode string
(then look at next char)

check if the current char is a digit (convert it to int)
loop for the number of occurrences
add the next char after current char to the end of the decode string

But what kind of condition is supposed to go in the while loop and how am I supposed to look at each char in the string and then add it to the end, etc. Thanks so much for the help.
The condition? That the character that you're reading isn't a digit. To check this:
http://cplusplus.com/reference/clibrary/cctype/

If it is, switch it with an I, and insert (that number-2) extra 'I's at that location.

To do that:
http://cplusplus.com/reference/string/string/

-Albatross
Last edited on
I mean what would go in the parenthesis of the while loop? I need it to terminate when there is nothing left in the string.
As Albatross noted you can check if the current character is a digit with the isdigit library function.

To iterate through the string in an effective way is somewhat more tricky...
A good idea is an infinite loop (while(true) or for(;;)), inside which you use the find_if function.
(take a look at this: http://cplusplus.com/reference/algorithm/find_if/ )

A string::iterator would be useful here. Declare one and initialize it to the beginning of your string (str.begin()). Then use find_if with your iterator, str.end() and your IsDigit function. This is important, you can't use the library's isdigit directly coz its prototype doesn't match what find_if expects. Just make a wrapper of the library's function that returns a bool. Here is an example:

1
2
3
4
bool IsDigit(char c)
{
    return isdigit(c);
}

If find_if returns str.end() we are done... It means that no digits were found. In this case use break to stop the loop. Else it will return an iterator pointing at the place of the digit. Use this info and the string reference Albatross provided to see how you can do the replacement you want.
Last edited on
Sorry guys I'm pretty new to this and I'm also pretty bad and I'm not quite sure how to implement the things you all are talking about. I wrote this code but the only problem is I need to somehow make sure the statement under the first "if" resets so that it will be "decode[loop + (whatever the number previously used in the last "if" statement was)]". Because with this code all I get is "TTSMGYYYRHRBEHYYDNJDIGGYYYYY" for the example "5TSMGYYYRHRBEH8YDNJDI3G5Y". As you can see, the only thing that's right is the last "5Y" part. I know what my problem is but I can't seem to figure out how to make the first if statement change based on whether the second one has been done yet. I know this probably isn't the easiest or best way to do it, but this is all I know and I'd prefer to leave it this 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
45
46
47
48
49
string RLEdecode (const string& protein) {
	string decode = "                                             ";
	int loop = 0, floop;
	int num;

	while (protein[loop]) {
		if (protein[loop] != '3' || '4' || '5' || '6' || '7' || '8' || '9')
		{	
			decode[loop] = protein[loop];
		}

		if (protein[loop] == '3' || '4' || '5' || '6' || '7' || '8' || '9')
		{
			num = 0;
			switch (protein[loop]) {
				case '3':
					num = 3;
					break;
				case '4':
					num = 4;
					break;
				case '5':
					num = 5;
					break;
				case '6':
					num = 6;
					break;
				case '7':
					num = 7;
					break;
				case '8':
					num = 8;
					break;
				case '9':
					num = 9;
					break;
			}

			for (floop = loop; floop < num + loop; floop++) {
				decode[floop] = protein[loop + 1];
			}

		}
		loop++;

	}
	
	return(decode);
}
Too... much... coffee......

You can do this. Think of the simplest solution possible. Take your string, and move character by character using the at() function. If isdigit(yourstring.at(i)) returns true and the digit you get from atoi() is greater than 2, replace that with the next letter, and add (the number you found, use atoi() - 2) more of that letter using insert(). There's no need for all that you have now.

http://cplusplus.com/reference/clibrary/cctype/
For isdigit(),

http://cplusplus.com/reference/string/string/
For at(), insert(), and replace(),

http://cplusplus.com/reference/clibrary/cstdlib/
For atoi().

-Albatross
This is all I could come up with from that. I'm still stumped :/ I just can't seem to put it all together. All these suggestions LOOK useful but when it comes time to try to implement them, I just get lost.
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
string RLEdecode (const string& protein) {
	char ch;
	int dig, floop;
	int loop = 0;
	string decode = "";

	while (protein[loop]) {

		if (isdigit(protein[loop]))
		{
			ch = protein.at(loop);
			dig = ch - '0';
			for (floop = 0; floop < dig; floop++){
				decode.insert(floop, protein, 1, 1);
			}
		}

		if (isalpha(protein[loop]))
			decode.insert(loop, protein, 1, 1);

		loop++;
	}
	return (decode);


}
At first glance...

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
string RLEdecode (const string& protein) {
	string decode = "                                          ";
	char ch1, ch2;
	int loop = 0;
	int dig, numLoops = 0;

	while (protein[loop]) {
		if (numLoops = 0) //This isn't right either.. = should be ==
			ch1 = protein.at(loop);

		else ch1 = protein.at(loop + 1);

		if (isalpha(ch1))
			decode[loop] = ch1;

		if (isdigit(ch1)) {
			dig = ch1 - '0';
			ch2 = protein.at(loop + 1);
			for (numLoops = 0; numLoops < dig; numLoops++) {
				decode[loop + numLoops] = ch2;
			}
			loop++; //******is this in the right place ??
		}
		return (decode); //**** or this??
	}
}
Last edited on
I have corrected that and written something else that I have gone through with pencil and paper and I see NO reason why this should not work, but lo and behold I get a message saying "debug assertion failed, string subscript out of range". This is getting frustrating, I've been working on this for hours.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
string RLEdecode (const string& protein) {
	string decode = "                                                ";
	char ch1, ch2;
	int loop = 0;
	int dig, numLoops = 0;

	while (protein[loop]) {
		ch1 = protein.at(loop);

		if (isalpha(ch1))
			decode[loop] = ch1;

		if (isdigit(ch1)) {
			dig = ch1 - '0';
			ch2 = protein.at(loop + 1);
			for (numLoops = 0; numLoops < (dig - 1); numLoops++) {
				decode[loop + numLoops] = ch2;
			}
		}
		loop++;
	}
	return (decode);
}
Just give us an example of the type of string you are passing to the function to decode, and what you expect the result to be
and let's see what we can find.
passed: 5F3AMTSO3T
decoded: FFFFFAAAMTSOOOT

I believe it might have something to do with the condition for my while loop because just out of curiosity I changed the condition to "loop < 5" and the error went away. Just sayin...
Last edited on
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
string RLEdecode (const string& protein) {
    string decode = "";
    char ch1, ch2;
    int loop = 0;
    int dig, numLoops = 0;

    while (protein[loop]) 
    {
        ch1 = protein.at(loop);

        if (isalpha(ch1))
            decode+=ch1;

        if (isdigit(ch1)) 
        {
            loop++;
            dig = ch1 - '0';
            ch2 = protein.at(loop);
            for (numLoops = 0; numLoops < (dig); numLoops++) 
            {
                decode += ch2;
            }
        }

        loop++;
    }
    return (decode);
}
Thank you that works... but may I ask what the += does?
it just tells the string to add the character onto it self. It's one of those things that the
c++ string class can do.

It can do it for strings too.

so:
std::string s1 = "Hello ";
std::string s2 = "World";

s1 += s2; //s1 is now "Hello World"

Ok, since you solved this I guess it wouldn't hurt to demonstrate a more sophisticated approach :P

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
#include <iostream>
#include <string>
#include <cstdlib>
using namespace std;

bool IsDigit(char c)
{
    return isdigit(c);
}

int  main()
{
    string str="5F3AMTSO3T";

    string::iterator it;

    int times;
    char ch;

    while(true)
    {
        it=find_if(str.begin(),str.end(),IsDigit);

        if (it==str.end()) break;

        times=*it-'0';
        ch=*(it+1);

        str.replace(it,it+2,times,ch);
    }

    cout << str << endl;
    cin.get();
}
Last edited on
Or a completely different approach:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
string RLEdecode (const string& protein) 
{
    string decode;
    int loop = 0;

    while (protein[loop]) 
    {

        isalpha(protein.at(loop))?  decode += protein.at(loop) : isdigit(protein.at(loop)) ? decode += string(protein.at(loop++) - '0', protein.at(loop) ):"";

        loop++;
    }
    return (decode);
}
Topic archived. No new replies allowed.