Got Something to Work and Not sure why its working

So i made a mistake in my code, but it did what i wanted it to do. But strangely i don't see the logic of how its working, in fact i would think it should have ended a never ending loop.

So the program takes a string, in this case "PLAYFAIR" and it is supposed to get rid of any duplicate letters,so "PLAYFAIR" becomes "PLAYFIR". When i was writing the program I kept getting "PLYFAIR" which is not what i wanted. Eventually i ran the code with "j--" in the second loop by mistake and i got the result that i wanted. However i'm confused as to why this works? The test case in the loop tests if j is smaller then the length of the string, then j is negated after each loop, so this test case should always be true and go indefinitely shouldn't it?



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
#include <iostream>
using namespace std;
int main()
{
	string key = "PLAYFAIR";
	bool keep = true;
	string keep_this = "";
	for (int i = 0; i < key.length(); i++)
	{
		for (int j = i ; j < key.length(); j--)
		{
			if (key.substr(i, 1) == key.substr(j , 1) && j != i)
			{
				
				keep = false;
			}
		}
		if (keep)
		{
			keep_this = keep_this + key.substr(i, 1);
		}
		keep = true;
	}
	cout << endl << keep_this << endl;
}
Last edited on
int is a signed integer type.

key.length() gives you an unsigned integer type.

When you compare a signed type with an unsigned type that is at least as big the signed type will automatically be converted into the unsigned type. This means that the expression j < key.length() will first convert j to unsigned before comparing it to key.length(). Unsigned types can't represent negative values so when j becomes negative it will be converted to a very large positive value which is much greater than key.length() so that is why the expression returns false and the loop ends.
Compilers will often warn about mixing signed and unsigned types in comparisons because they are so error prone. If you use GCC/MinGW or Clang you should at least use the -Wall compiler flag which enables this and many other warnings (-Wextra also enables many useful warnings).
Problem solved by the look of it.
Note also that the <string> class has many powers:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
#include <iostream>
#include <string>

int main()
{
    std::string key = "ABRACADABRA";
    std::string keep_this;
    
    char ch;
    for (int i = 0; i < key.length(); i++)
    {
        ch = key[i];
        
        if( keep_this.find(ch) == std::string::npos )
            keep_this += ch;
    }
    std::cout
    << key << '\n'
    << keep_this << '\n';
}



ABRACADABRA
ABRCD
Program ended with exit code: 0

http://www.cplusplus.com/reference/string/string/find/

Topic archived. No new replies allowed.