Code:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <stdbool.h>
// use bubble sort to sort letters in a key
void sort_letters(char *phrase) {
int i,j;
int n = strlen(phrase);
//printf("The string to sort is: %s\n", phrase);
for ( i = 0; i < n-1; i++) {
for ( j = i+1; j < n; j++) {
if (phrase[i] > phrase[j]) {
char temp = phrase[i];
phrase[i] = phrase[j];
phrase[j] = temp;
}
}
}
//printf("The sorted string is: %s\n", phrase);
}
// allocate a matrix for string and fill it
char** gridStr(char *line, char *key)
{
int n = strlen(line);
int columns = strlen(key);
int rows = (n + columns - 1) / columns;
int j;
char **matrix = malloc(rows * sizeof(char *));
for ( j = 0; j < rows; j++) {
matrix[j] = malloc(columns * sizeof(char));
}
int i = 0;
int k,l;
for ( k = 0; k < rows; k++) {
for ( l = 0; l < columns; l++) {
if (i<n) {
matrix[k][l] = line[i++];
} else {
matrix[k][l] = '-'; // fill letter
}
//putchar(matrix[k][l]);
}
//putchar('\n');
}
return matrix;
}
// swap columns i and j of the given matrix, zero-based indices
void swap_matrix_columns(char **matrix, int rows, int columns, int i, int j) {
int k;
for ( k = 0; k < rows; k++) {
char tmp = matrix[k][i];
matrix[k][i] = matrix[k][j];
matrix[k][j] = tmp;
}
}
// print matrix to stdout
void print_matrix(char **matrix, int rows, int columns) {
int i,j;
for (i = 0; i < rows; i++) {
printf("Row %2d: ", i);
for (j = 0; j < columns; j++) {
if (matrix[i][j] == ' ') {
putchar('-');
} else {
putchar(matrix[i][j]);
}
}
putchar('\n');
}
}
// sort key and transpose matrox columns according new order
void encrypt(char **matrix, int rows, int columns, char *key) {
char sorted_key[strlen(key)];
strcpy(sorted_key, key);
sort_letters(sorted_key);
printf("Sorted key: %s (length: %2zu)\n", sorted_key, strlen(sorted_key));
bool is_used[columns];
int i;
for ( i = 0; i < columns; i++) is_used[i]= false;
for ( i = 0; i < columns; i++) {
if (!is_used[i]) {
// find new position, must exist
int j;
for (j = 0; j < columns; j++) {
if (key[i] == sorted_key[j] && !is_used[j]) {
break;
}
}
swap_matrix_columns(matrix, rows, columns, i, j);
is_used[i] = true;
is_used[j] = true;
}
}
}
int main(){
char key[50];
char line[256];
printf("Enter your string: ");
if (fgets(line, sizeof line, stdin) == NULL) {
fprintf(stderr, "No line read\n");
exit(EXIT_FAILURE);
}
printf("Enter your key: ");
if (fgets(key, sizeof key, stdin) == NULL) {
fprintf(stderr, "No line read\n");
exit(EXIT_FAILURE);
}
int len = strlen(line);
if (len && line[len - 1] == '\n') {
line[--len] = '\0';
}
int len1 = strlen(key);
if (len1 && key[len1 - 1] == '\n') {
key[--len1]= '\0';
}
//printf("string: |%s| (length: %2zu)\n", line, strlen(line));
//printf("key: |%s| (length: %2zu)\n", key, strlen(key));
char **matrix = gridStr(line, key);
int columns = len1;
// Use simple trick (+ len1 - 1) to determine number of rows with one integer divison
int rows = (len + columns - 1) / columns;
print_matrix(matrix, rows, columns);
encrypt(matrix, rows, columns, key);
print_matrix(matrix, rows, columns);
int i,j;
for(i=0; i<columns; i++) {
for(j=0;j<rows;j++) {
printf("%s", matrix[i][j]);
int row;
for ( row = 0; row < rows; row++) {
free(matrix[row]);
}
free(matrix);
}
}