Created
September 12, 2015 15:08
-
-
Save nocturnaltortoise/92b6fbc0eb31568d22f0 to your computer and use it in GitHub Desktop.
Program for counting similarities between two strings, in C.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <stdio.h> | |
#include <string.h> | |
#include <stdlib.h> | |
#include <errno.h> | |
void print_usage_on_error(); | |
void print_coincidences(int[], int, size_t); | |
void count_coincidences(char[], char[], int *, int); | |
void remove_spaces(char *); | |
/* | |
Program for counting similarities between two strings. Main usage being finding the key | |
length of a polyalphabetic ciphertext (such as one created by the Vigenere cipher). | |
*/ | |
int main(int argc, char *argv[]){ | |
//if the user hasn't supplied a significance level and a ciphertext, | |
//prompt them to enter both | |
if(argc < 3){ | |
print_usage_on_error(); | |
exit(EXIT_FAILURE); | |
} | |
char ciphertext[strlen(argv[1])]; | |
char ciphertext_copy[strlen(argv[1])]; | |
strcpy(ciphertext, argv[1]); | |
remove_spaces(ciphertext); | |
strcpy(ciphertext_copy, ciphertext); | |
//get significance level from user | |
char *endptr; | |
int sig_level = strtol(argv[2], &endptr, 0); | |
if(errno == ERANGE || *endptr != '\0'){ | |
print_usage_on_error(); | |
exit(EXIT_FAILURE); | |
} | |
int ciphertext_length = strlen(ciphertext); | |
int counts[ciphertext_length]; | |
//initialise the array to all 0s | |
memset(counts, 0, sizeof(counts)); | |
//count the number of coincidences and save those counts to an array | |
count_coincidences(ciphertext, ciphertext_copy, counts, ciphertext_length); | |
//we need to pass the size of the counts array because we're passing a | |
//pointer to an array so sizeof() won't work right - C can't pass arrays apparently. | |
print_coincidences(counts, sig_level, sizeof(counts)); | |
return 0; | |
} | |
void print_usage_on_error(){ | |
fprintf(stderr, "Supply a ciphertext as a command line argument between quotes, followed by a significance level (how many coincidences a shift needs before it's displayed).\n"); | |
} | |
//modifies the passed string in place | |
void remove_spaces(char *string){ | |
int str_length = strlen(string); | |
int j; | |
for(int i=0; i<str_length; i++){ | |
if(string[i] == ' '){ | |
for(j=i; j<str_length; j++){ | |
string[j] = string[j+1]; | |
} | |
} | |
} | |
string[j] = '\0'; | |
} | |
void print_coincidences(int counts[], int sig_level, size_t count_size){ | |
for(int i=0; i < count_size / sizeof(int); i++){ | |
if(counts[i] >= sig_level){ | |
printf("Shift: %d, Coincidences: %d\n",i, counts[i]); | |
} | |
} | |
} | |
void count_coincidences(char ciphertext[], char ciphertext_copy[], int *counts, int ciphertext_length){ | |
for(int shift=1; shift < ciphertext_length; shift++){ | |
for(int j=0; j < ciphertext_length - shift; j++){ | |
if(ciphertext[j + shift] == ciphertext_copy[j]){ | |
counts[shift] += 1; | |
} | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment