Skip to content

Instantly share code, notes, and snippets.

@nocturnaltortoise
Created September 12, 2015 15:08
Show Gist options
  • Save nocturnaltortoise/92b6fbc0eb31568d22f0 to your computer and use it in GitHub Desktop.
Save nocturnaltortoise/92b6fbc0eb31568d22f0 to your computer and use it in GitHub Desktop.
Program for counting similarities between two strings, in C.
#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