I am just coding some classic brute force password cracking program, just to improve myself.

I've explained how my program works at the start of the code. Check some of those screenshots to understand easier.

My program works really well but it's a bit dirty and it can be faster if I solve these two problems:

1. The main code is not that long. It looks so long and dirty because I copied a code block 8 times in a switch case statement. For example, case 1 loops with one character length passwords. case 2 = two characters, case 8 = 8 characters length password. The one and only difference between those cases is the "for loop" count. case 1 has 1 for loop, case 8 has 8 nested for loops. I want to make my code prettier, so how can I get rid of this copy/pasted code and make it 1/8 size of current size? CTRL + MOUSE WHEEL DOWN, zoom-out and see the copy pasted parts.

2. It tries 1 digit first, then 2 digits, then 3 digits and so on. So it should wait for 1, 2, 3 to get the 4 digit ones. And it makes the program lose so much time at higher digits. My CPU is i7 3770k got 6 cores and the program runs only with one. I guess it's because it says 13% CPU usage. I want to make it higher, like 6 cores on the same task, or each core will take care of one part. The first core will start looping only the 8 character length ones, and second core will do the same with 7 character length ones... and when one of them finds the answer, the program will end. Can we really do it?

Here is the code

#include <iostream>
#include <ctime>
using namespace std;
long long int attempt;
clock_t start_t, end_t;

int main(){

cout << "Enter the password to crack : ";

cout << endl << endl << endl << ">\n>> CRACKED THE PASSWORD! >>\n>" << endl <<  endl <<"The password : " << crackPassword(password) << endl;
cout << "The number of attempts : " << attempt << endl;
cout << "The time duration  passed : " << (double)(end_t - start_t)/1000 << " seconds" << endl << endl;
return 0;
}

start_t = clock();

string test,alphabet = "1337 also daktari is pro";
while(1){

case 1:
while(alphabetSet<4){
switch(alphabetSet){
case 1 : alphabet = "-0123456789";
cout << endl << endl <<"Testing only digits(0123456789) - 10 Characters, please wait";  break;
case 2 : alphabet = "-abcdefghijklmnopqrstuvwxyz";
cout << endl << endl << "Couldn't find the password, increasing the searching level."<< endl << endl << "Testing only lowercase characters(abcdefghijklmnopqrstuvwxyz) - 26 Characters, please wait";  break;
case 3 : alphabet = "-ABCDEFGHIJKLMNOPQRSTUVWXYZ";
cout << endl << endl << "Couldn't find the password, increasing the searching level."<< endl << endl << "Testing only uppercase characters(ABCDEFGHIJKLMNOPQRSTUVWXYZ) - 26 Characters, please wait";  break;
}

for(digit[0]=1;digit[0]<alphabet.length();digit[0]++){
attempt++;
if(attempt%2500000==0) cout << ".";
test=alphabet[digit[0]];
if(alphabet[digit[i]]!='-')test+=alphabet[digit[i]];
if(pass.compare(test)==0){end_t = clock(); return test;}
}
alphabetSet++;
}
break;
case 2:
alphabetSet=1;
while(alphabetSet<6){
switch(alphabetSet){
case 1 : alphabet = "-0123456789";
cout << endl << endl <<"Testing only digits(0123456789) - 10 Characters, please wait";  break;
case 2 : alphabet = "-abcdefghijklmnopqrstuvwxyz";
cout << endl << endl << "Couldn't find the password, increasing the searching level."<< endl << endl << "Testing only lowercase characters(abcdefghijklmnopqrstuvwxyz) - 26 Characters, please wait";  break;
case 3 : alphabet = "-ABCDEFGHIJKLMNOPQRSTUVWXYZ";
cout << endl << endl << "Couldn't find the password, increasing the searching level."<< endl << endl << "Testing only uppercase characters(ABCDEFGHIJKLMNOPQRSTUVWXYZ) - 26 Characters, please wait";  break;
case 4 : alphabet = "-0123456789abcdefghijklmnopqrstuvwxyz";
cout << endl << endl << "Couldn't find the password, increasing the searching level."<< endl << endl << "Testing lowercase characters and numbers(0123456789abcdefghijklmnopqrstuvwxyz) - 36 Characters, please wait";  break;
case 5 : alphabet = "-0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
}

for(digit[1]=0;digit[1]<alphabet.length();digit[1]++)
for(digit[0]=1;digit[0]<alphabet.length();digit[0]++){
attempt++;
if(attempt%2500000==0) cout << ".";
test=alphabet[digit[0]];
if(alphabet[digit[i]]!='-')test+=alphabet[digit[i]];
if(pass.compare(test)==0){end_t = clock(); return test;}
}
alphabetSet++;
}
break;
case 3:
alphabetSet=1;
while(alphabetSet<8){
switch(alphabetSet){
case 1 : alphabet = "-0123456789";
cout << endl << endl <<"Testing only digits(0123456789) - 10 Characters, please wait";  break;
case 2 : alphabet = "-abcdefghijklmnopqrstuvwxyz";
cout << endl << endl << "Couldn't find the password, increasing the searching level."<< endl << endl << "Testing only lowercase characters(abcdefghijklmnopqrstuvwxyz) - 26 Characters, please wait";  break;
case 3 : alphabet = "-ABCDEFGHIJKLMNOPQRSTUVWXYZ";
cout << endl << endl << "Couldn't find the password, increasing the searching level."<< endl << endl << "Testing only uppercase characters(ABCDEFGHIJKLMNOPQRSTUVWXYZ) - 26 Characters, please wait";  break;
case 4 : alphabet = "-0123456789abcdefghijklmnopqrstuvwxyz";
cout << endl << endl << "Couldn't find the password, increasing the searching level."<< endl << endl << "Testing lowercase characters and numbers(0123456789abcdefghijklmnopqrstuvwxyz) - 36 Characters, please wait";  break;
case 5 : alphabet = "-0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
cout << endl << endl << "Couldn't find the password, increasing the searching level."<< endl << endl << "Testing uppercase characters and numbers(0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ) - 36 Characters, please wait";  break;
case 6 : alphabet = "-abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
cout << endl << endl << "Couldn't find the password, increasing the searching level."<< endl << endl << "Testing lowercase, uppercase characters(abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ) - 52 Characters, please wait";  break;
case 7 : alphabet = "-0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
cout << endl << endl << "Couldn't find the password, increasing the searching level."<< endl << endl << "Testing lowercase, uppercase characters and numbers(0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ) - 62 Characters, please wait";  break;
}
for(digit[2]=0;digit[2]<alphabet.length();digit[2]++)
for(digit[1]=0;digit[1]<alphabet.length();digit[1]++)
for(digit[0]=1;digit[0]<alphabet.length();digit[0]++){
attempt++;
if(attempt%2500000==0) cout << ".";
test=alphabet[digit[0]];
if(alphabet[digit[i]]!='-')test+=alphabet[digit[i]];
if(pass.compare(test)==0){end_t = clock(); return test;}
}
alphabetSet++;
}
break;
case 4:
alphabetSet=1;
while(alphabetSet<8){
switch(alphabetSet){
case 1 : alphabet = "-0123456789";
cout << endl << endl <<"Testing only digits(0123456789) - 10 Characters, please wait";  break;
case 2 : alphabet = "-abcdefghijklmnopqrstuvwxyz";
cout << endl << endl << "Couldn't find the password, increasing the searching level."<< endl << endl << "Testing only lowercase characters(abcdefghijklmnopqrstuvwxyz) - 26 Characters, please wait";  break;
case 3 : alphabet = "-ABCDEFGHIJKLMNOPQRSTUVWXYZ";
cout << endl << endl << "Couldn't find the password, increasing the searching level."<< endl << endl << "Testing only uppercase characters(ABCDEFGHIJKLMNOPQRSTUVWXYZ) - 26 Characters, please wait";  break;
case 4 : alphabet = "-0123456789abcdefghijklmnopqrstuvwxyz";
cout << endl << endl << "Couldn't find the password, increasing the searching level."<< endl << endl << "Testing lowercase characters and numbers(0123456789abcdefghijklmnopqrstuvwxyz) - 36 Characters, please wait";  break;
case 5 : alphabet = "-0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
cout << endl << endl << "Couldn't find the password, increasing the searching level."<< endl << endl << "Testing uppercase characters and numbers(0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ) - 36 Characters, please wait";  break;
case 6 : alphabet = "-abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
cout << endl << endl << "Couldn't find the password, increasing the searching level."<< endl << endl << "Testing lowercase, uppercase characters(abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ) - 52 Characters, please wait";  break;
case 7 : alphabet = "-0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
cout << endl << endl << "Couldn't find the password, increasing the searching level."<< endl << endl << "Testing lowercase, uppercase characters and numbers(0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ) - 62 Characters, please wait";  break;
}

for(digit[3]=0;digit[3]<alphabet.length();digit[3]++)
for(digit[2]=0;digit[2]<alphabet.length();digit[2]++)
for(digit[1]=0;digit[1]<alphabet.length();digit[1]++)
for(digit[0]=1;digit[0]<alphabet.length();digit[0]++){
attempt++;
if(attempt%2500000==0) cout << ".";
test=alphabet[digit[0]];
if(alphabet[digit[i]]!='-')test+=alphabet[digit[i]];
if(pass.compare(test)==0){end_t = clock(); return test;}
}
alphabetSet++;
}
break;
case 5:
alphabetSet=1;
while(alphabetSet<8){
switch(alphabetSet){
case 1 : alphabet = "-0123456789";
cout << endl << endl <<"Testing only digits(0123456789) - 10 Characters, please wait";  break;
case 2 : alphabet = "-abcdefghijklmnopqrstuvwxyz";
cout << endl << endl << "Couldn't find the password, increasing the searching level."<< endl << endl << "Testing only lowercase characters(abcdefghijklmnopqrstuvwxyz) - 26 Characters, please wait";  break;
case 3 : alphabet = "-ABCDEFGHIJKLMNOPQRSTUVWXYZ";
cout << endl << endl << "Couldn't find the password, increasing the searching level."<< endl << endl << "Testing only uppercase characters(ABCDEFGHIJKLMNOPQRSTUVWXYZ) - 26 Characters, please wait";  break;
case 4 : alphabet = "-0123456789abcdefghijklmnopqrstuvwxyz";
cout << endl << endl << "Couldn't find the password, increasing the searching level."<< endl << endl << "Testing lowercase characters and numbers(0123456789abcdefghijklmnopqrstuvwxyz) - 36 Characters, please wait";  break;
case 5 : alphabet = "-0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
cout << endl << endl << "Couldn't find the password, increasing the searching level."<< endl << endl << "Testing uppercase characters and numbers(0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ) - 36 Characters, please wait";  break;
case 6 : alphabet = "-abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
cout << endl << endl << "Couldn't find the password, increasing the searching level."<< endl << endl << "Testing lowercase, uppercase characters(abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ) - 52 Characters, please wait";  break;
case 7 : alphabet = "-0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
cout << endl << endl << "Couldn't find the password, increasing the searching level."<< endl << endl << "Testing lowercase, uppercase characters and numbers(0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ) - 62 Characters, please wait";  break;
}
for(digit[4]=0;digit[4]<alphabet.length();digit[4]++)
for(digit[3]=0;digit[3]<alphabet.length();digit[3]++)
for(digit[2]=0;digit[2]<alphabet.length();digit[2]++)
for(digit[1]=0;digit[1]<alphabet.length();digit[1]++)
for(digit[0]=1;digit[0]<alphabet.length();digit[0]++){
attempt++;
if(attempt%2500000==0) cout << ".";
test=alphabet[digit[0]];
if(alphabet[digit[i]]!='-')test+=alphabet[digit[i]];
if(pass.compare(test)==0){end_t = clock(); return test;}
}
alphabetSet++;
}
break;
case 6:
alphabetSet=1;
while(alphabetSet<8){
switch(alphabetSet){
case 1 : alphabet = "-0123456789";
cout << endl << endl <<"Testing only digits(0123456789) - 10 Characters, please wait";  break;
case 2 : alphabet = "-abcdefghijklmnopqrstuvwxyz";
cout << endl << endl << "Couldn't find the password, increasing the searching level."<< endl << endl << "Testing only lowercase characters(abcdefghijklmnopqrstuvwxyz) - 26 Characters, please wait";  break;
case 3 : alphabet = "-ABCDEFGHIJKLMNOPQRSTUVWXYZ";
cout << endl << endl << "Couldn't find the password, increasing the searching level."<< endl << endl << "Testing only uppercase characters(ABCDEFGHIJKLMNOPQRSTUVWXYZ) - 26 Characters, please wait";  break;
case 4 : alphabet = "-0123456789abcdefghijklmnopqrstuvwxyz";
cout << endl << endl << "Couldn't find the password, increasing the searching level."<< endl << endl << "Testing lowercase characters and numbers(0123456789abcdefghijklmnopqrstuvwxyz) - 36 Characters, please wait";  break;
case 5 : alphabet = "-0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
cout << endl << endl << "Couldn't find the password, increasing the searching level."<< endl << endl << "Testing uppercase characters and numbers(0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ) - 36 Characters, please wait";  break;
case 6 : alphabet = "-abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
cout << endl << endl << "Couldn't find the password, increasing the searching level."<< endl << endl << "Testing lowercase, uppercase characters(abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ) - 52 Characters, please wait";  break;
case 7 : alphabet = "-0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
cout << endl << endl << "Couldn't find the password, increasing the searching level."<< endl << endl << "Testing lowercase, uppercase characters and numbers(0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ) - 62 Characters, please wait";  break;
}
for(digit[5]=0;digit[5]<alphabet.length();digit[5]++)
for(digit[4]=0;digit[4]<alphabet.length();digit[4]++)
for(digit[3]=0;digit[3]<alphabet.length();digit[3]++)
for(digit[2]=0;digit[2]<alphabet.length();digit[2]++)
for(digit[1]=0;digit[1]<alphabet.length();digit[1]++)
for(digit[0]=1;digit[0]<alphabet.length();digit[0]++){
attempt++;
if(attempt%2500000==0) cout << ".";
test=alphabet[digit[0]];
if(alphabet[digit[i]]!='-')test+=alphabet[digit[i]];
if(pass.compare(test)==0){end_t = clock(); return test;}
}
alphabetSet++;
}
break;
case 7:
alphabetSet=1;
while(alphabetSet<8){
switch(alphabetSet){
case 1 : alphabet = "-0123456789";
cout << endl << endl <<"Testing only digits(0123456789) - 10 Characters, please wait";  break;
case 2 : alphabet = "-abcdefghijklmnopqrstuvwxyz";
cout << endl << endl << "Couldn't find the password, increasing the searching level."<< endl << endl << "Testing only lowercase characters(abcdefghijklmnopqrstuvwxyz) - 26 Characters, please wait";  break;
case 3 : alphabet = "-ABCDEFGHIJKLMNOPQRSTUVWXYZ";
cout << endl << endl << "Couldn't find the password, increasing the searching level."<< endl << endl << "Testing only uppercase characters(ABCDEFGHIJKLMNOPQRSTUVWXYZ) - 26 Characters, please wait";  break;
case 4 : alphabet = "-0123456789abcdefghijklmnopqrstuvwxyz";
cout << endl << endl << "Couldn't find the password, increasing the searching level."<< endl << endl << "Testing lowercase characters and numbers(0123456789abcdefghijklmnopqrstuvwxyz) - 36 Characters, please wait";  break;
case 5 : alphabet = "-0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
cout << endl << endl << "Couldn't find the password, increasing the searching level."<< endl << endl << "Testing uppercase characters and numbers(0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ) - 36 Characters, please wait";  break;
case 6 : alphabet = "-abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
cout << endl << endl << "Couldn't find the password, increasing the searching level."<< endl << endl << "Testing lowercase, uppercase characters(abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ) - 52 Characters, please wait";  break;
case 7 : alphabet = "-0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
cout << endl << endl << "Couldn't find the password, increasing the searching level."<< endl << endl << "Testing lowercase, uppercase characters and numbers(0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ) - 62 Characters, please wait";  break;
}
for(digit[6]=0;digit[6]<alphabet.length();digit[6]++)
for(digit[5]=0;digit[5]<alphabet.length();digit[5]++)
for(digit[4]=0;digit[4]<alphabet.length();digit[4]++)
for(digit[3]=0;digit[3]<alphabet.length();digit[3]++)
for(digit[2]=0;digit[2]<alphabet.length();digit[2]++)
for(digit[1]=0;digit[1]<alphabet.length();digit[1]++)
for(digit[0]=1;digit[0]<alphabet.length();digit[0]++){
attempt++;
if(attempt%2500000==0) cout << ".";
test=alphabet[digit[0]];
if(alphabet[digit[i]]!='-')test+=alphabet[digit[i]];
if(pass.compare(test)==0){end_t = clock(); return test;}
}
alphabetSet++;
}
break;
case 8:
alphabetSet=1;
while(alphabetSet<8){
switch(alphabetSet){
case 1 : alphabet = "-0123456789";
cout << endl << endl <<"Testing only digits(0123456789) - 10 Characters, please wait";  break;
case 2 : alphabet = "-abcdefghijklmnopqrstuvwxyz";
cout << endl << endl << "Couldn't find the password, increasing the searching level."<< endl << endl << "Testing only lowercase characters(abcdefghijklmnopqrstuvwxyz) - 26 Characters, please wait";  break;
case 3 : alphabet = "-ABCDEFGHIJKLMNOPQRSTUVWXYZ";
cout << endl << endl << "Couldn't find the password, increasing the searching level."<< endl << endl << "Testing only uppercase characters(ABCDEFGHIJKLMNOPQRSTUVWXYZ) - 26 Characters, please wait";  break;
case 4 : alphabet = "-0123456789abcdefghijklmnopqrstuvwxyz";
cout << endl << endl << "Couldn't find the password, increasing the searching level."<< endl << endl << "Testing lowercase characters and numbers(0123456789abcdefghijklmnopqrstuvwxyz) - 36 Characters, please wait";  break;
case 5 : alphabet = "-0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
cout << endl << endl << "Couldn't find the password, increasing the searching level."<< endl << endl << "Testing uppercase characters and numbers(0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ) - 36 Characters, please wait";  break;
case 6 : alphabet = "-abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
cout << endl << endl << "Couldn't find the password, increasing the searching level."<< endl << endl << "Testing lowercase, uppercase characters(abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ) - 52 Characters, please wait";  break;
case 7 : alphabet = "-0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
cout << endl << endl << "Couldn't find the password, increasing the searching level."<< endl << endl << "Testing lowercase, uppercase characters and numbers(0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ) - 62 Characters, please wait";  break;
}
for(digit[7]=0;digit[7]<alphabet.length();digit[7]++)
for(digit[6]=0;digit[6]<alphabet.length();digit[6]++)
for(digit[5]=0;digit[5]<alphabet.length();digit[5]++)
for(digit[4]=0;digit[4]<alphabet.length();digit[4]++)
for(digit[3]=0;digit[3]<alphabet.length();digit[3]++)
for(digit[2]=0;digit[2]<alphabet.length();digit[2]++)
for(digit[1]=0;digit[1]<alphabet.length();digit[1]++)
for(digit[0]=1;digit[0]<alphabet.length();digit[0]++){
attempt++;
if(attempt%2500000==0) cout << ".";
test=alphabet[digit[0]];
if(alphabet[digit[i]]!='-')test+=alphabet[digit[i]];
if(pass.compare(test)==0){end_t = clock(); return test;}
}
alphabetSet++;
}
break;
}
cout  << endl << endl << endl << endl << "*" << endl;
cout  << endl << "*" << endl << endl;
}
}
• "I want to make it higher like 6 cores ... Can we really do it?" Yes that can be done. To do it, I think you need to use "multithreading". Support for multithreading is built-in to C++11 (see for example here). Commented Mar 18, 2014 at 3:17

• Prefer not to get into the habit of using using namespace std.

• Make sure to include <string>.

• For the <ctime> library, you should use std::clock_t instead of clock_t.

• Prefer to avoid global variables:

long long int attempt;
clock_t start_t, end_t;

As these variables can be modified anywhere in the program, you could introduce bugs, which will also hurt maintainability and testability.

You should have attempt initialized to 0 (it's being incremented) in main() and pass it to crackPassword() by reference. In this way, you'll know that only these two functions can recognize attempt (if you ever add additional functions).

start_t and end_t just need to be in main(). I'd also recommend renaming them (especially remove the _t), otherwise it may look like they're part of the library.

• There's no need to use std::endl so many times, which also flushes the buffer, needlessly slowing down the code. Just use "\n", which only gives a newline. It'll also make the code a bit shorter, especially in places where it can be put into an existing hard-coded output line.

This, for instance:

cout << endl << endl << endl << ">\n>> CRACKED THE PASSWORD! >>\n>" << endl <<  endl <<"The password : " << crackPassword(password) << endl;

would turn into this:

You could also split this into separate lines for clarity, and to keep the lines shorter:

cout << "\n\n\n>\n>> CRACKED THE PASSWORD! >>\n>\n\n;

• You don't specifically need a C-style cast here:

(double)(end_t - start_t)/1000

Cast the C++ way, with static_cast<>:

static_cast<double>(end_t - start_t)/1000

Also, in case you'll need to use this in other places, consider having it as a variable. You should also use the CLOCKS_PER_SEC macro, which is part of the library.

double timeDuration = static_cast<double>(end_t - start_t) / CLOCKS_PER_SEC;

• In crackPassword(), pass should be passed by const& instead of by value as it's not being modified inside the function. This will also save an unnecessary copy.

• Prefer to have one variable declaration/initialization per line:

int digit[7];
int alphabetSet=1;

This will allow each variable to be more visible. It will also be possible to add a comment for separate variables if needed.

• A line like this:

for(digit[0]=1;digit[0]<alphabet.length();digit[0]++){

should use appropriate whitespace for readability:

for (digit[0] = 1; digit[0] < alphabet.length(); digit[0]++) {

Generally, keep whitespace between operators, and in the case of for loop statements, separate each part as well.

If this is being avoided because the line is too long, then it should be effectively shortened in some other way. All of that will help with readability.

• Can you explain me why "using namespace std" is bad? Thank you by the way, these information are useful for me!
– user38928
Commented Mar 18, 2014 at 6:30
• @daktari: It's generally discouraged as it exposes the STL code (which is contained in the std namespace) to the global namespace. For instance, if you were to create your own string class and use some of the same names, then with using namespace std, name-clashing will occur. This will create ambiguities and could prevent compilation. For small applications, or if you put this in a local scope (such as a function), then it's not a big deal. But if it's put in global, then it's exposed to the entire program. Commented Mar 18, 2014 at 6:36

@ChrisW raises a good point, but doesn't take the concept as far as I would.

He's absolutely correct that what you're doing it basically just counting. What he doesn't point out is that it can (and probably should) be implemented as actual counting.

For example, to test all passwords up to 8 characters long, using only digits for the alphabet, we end up simply counting from 0 to 99999999. We convert each of those from a number to a string, then test the resulting string.

I would, however, advise against the strategy you suggested of testing 1 digit numbers in one thread, 2 digit numbers in a second thread, and so on. The problem is fairly simple: each digit you add multiplies the number of combinations by 10. Your first thread, testing 1-digit passwords, only has 10 possibilities. By the time you get to the last thread (8-bit passwords) it has 108 times as many possibilities as the first. Clearly the first will finish much more quickly than the last; most of the time will still be consumed by only one thread (running on only one core).

Instead, you want to split your overall range into a set of equal-sized sub-ranges. Given 100000000 combinations, you want to test approximately 100000000/8 = 12500000 possibilities on each core. To do that, you have one thread test possibilities from 0 to 12500000, the next from 12500000 to 25000000, and so on until you reach 99999999. This way, each thread does approximately equal work, so all the cores share the work about equally.

There are a couple of different ways to do that. One would be to explicitly create threads, one for each range of numbers. Another possibility would be to leave most of the code as a fairly simple loop, and use OpenMP to split that loop up into threads:

#pragma omp parallel for
for (long long i = 0; i<9999999ULL; i++) {
std::string candidate = std::to_string(i);
std::cout<<"We found it!\n"<<candidate<<"\n";
}

Doing a quick test on my laptop, this reduced the search time for a password from about 3 seconds to less than 1 second. Of course, the absolute speed will depend on how long it takes to test a password, but as long as you can test passwords concurrently from multiple threads (or testing a password is a lot faster than generating one) you can gain considerable speed from multithreading this way.

If you want to do roughly the same thing, but with (for example) a mixture of letters and digits, you can still use the same basic idea. The only difference is the base in which you convert the numbers to a string. For example, to use only letters (not digits) you could do something like this:

std::string to_string(long long val) {
std::string ret;
while (val) {
ret += ('a' + val % 26);
val /= 26;
}
}

To create a mixture of digits and letters, it's generally easiest to start with an array of the characters you want to use, then index into that array:

char digits[] = "0123456789abcdefghijklmnopqrstuvwxyz";

std::string to_string(long long val) {
std::string ret;
static const size_t size = sizeof(digits) -1;
while (val) {
ret += digits[val % size];
val /= size;
}
}

At some point, this won't work correctly any more, simply because a long long (or even an unsigned long long) is large enough to produce all the numbers in a given range. If you need/want to search that large of a range, you'll probably need to do other things to improve your search though. An unsigned long long has a range of at least 64 bits, and generating all 64-bit numbers will take longer than you're probably willing to wait (even if we ignore conversion and testing the results, just counting from 0 to 0xffffffffffffffff will take longer than most people are willing to wait.

• Here is the fix, if there are some people are having same problem with to_string and <string> : to_string Fix
– user38928
Commented Mar 18, 2014 at 10:05
• I've tried both letters only and the "mixture of digits and letters" , both are looping from 1 to 999999, I don't see any letter. std::string to_string(long long val); int main(){ std::string password; std::cin >> password; for (long long i = 0; i<9999999ULL; i++) { std::string candidate = std::to_string(i); if (password.compare(candidate)) std::cout<<"\n"<<candidate<<"\n"; } } std::string to_string(long long val) { std::string ret; while (val) { ret += ('a' + val % 26); val /= 26; } }
– user38928
Commented Mar 18, 2014 at 16:44
• @daktari This is a letter, from the alphabet of lower-case letters: ('a' + val % 26); because val % 26 is a number; when val % 26 is 0 then the letter is 'a' + 0 which is 'a'; when val % 26 is 1 then the letter is 'a' + 1 which is 'b'; etc. Alternatively, this is a letter from the dictionary which is named 'digits': digits[val % size] Commented Mar 18, 2014 at 16:53
• Yeah but as I said it loops only numbers when I print them, even if it makes a,b,c does it add them together like: zz then aaa then aab then aac etc.
– user38928
Commented Mar 18, 2014 at 21:16

The one and only difference between those cases is the "for loop" count, case 1 got 1 for loop, case 8 got 8 nested for loops. I want to make my code prettier, so how can I get rid of this copy&paste code and make it 1/8 size of current size.

Iterating through passwords is like counting numbers:

• Increment until you get to the last digit "9"
• Next increment, increment the next digit and reset this digit "10"
• Increment the first digit again: "11", "12", etc.
• Increment the next digit when you have to: "20"
• If you can't increment the next digit then increment the one after that: "99" "100"

So something like (untested code ahead):

// try up to 8 digit password
// start at last character and make it bigger by building to the left

for (;;)
{
for(int i = 0; i < alphabet.length; ++i)
{
// test for password match here
if (test.compare(pass))
return string(pass); // found!
}
// increment one or more chars to the left
// and maybe decrement pass to make it bigger
// before we run the above for loop again on the right-most char
for (int j = 6; j >= 0; --j)
{
{
// first time we've overflowed this high
--pass;
break;
}
// increment the existing character
++found;
if (found < alphabet.length)
{
break;
}
// else need to overflow to the next higher
if (j == 0)
{
// can't go higher, return failure
return string("");
}
continue; // i.e. try again with --j
}
}
• I'll test it, it looks really fine but what about using "Recursion" for "nested for loops"?
– user38928
Commented Mar 18, 2014 at 6:35
• Recursion seems to me another possible, valid way to implement it. Commented Mar 18, 2014 at 16:32
• I could not convert my nested loop to some recursion function, it is too complicated.
– user38928
Commented Mar 18, 2014 at 16:46