I'm trying to make a columnar transposition in C. The user inputs a string and key. The length of the key determines how many columns there are.To encryp the message the key must be sorted alphabetically. Here is an example using the string as hello there and the key as 'KEY'.
I created a function to sort the key alphabetically but I have no clue how to swap the columns.
void gridStr(char *line, char *key);
char encrypt(char *key);
int main(void) {
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[--len]= '\0';
gridStr(line, key);
encrypt(key);
}
void gridStr(char *line, char *key)
{
char mat[10][10] = {0};
int columns = strlen(key)-1;
int rows = 0;
int i=0,j = 0;
while (line[i]) {
if (line[i] == ' ') {
putchar('_');
} else {
putchar(line[i]);
}
mat[rows][i % columns] = line[i];
i ;
if (i > 0 && i % columns == 0) {
putchar('\n');
rows ;
}
}
if (i % columns != 0) putchar('\n');
rows ; // from current row to number of rows
printf("\nMatrix:\n");
for (i = 0; i < rows; i ) {
for (j = 0; j < columns; j ) {
if (mat[i][j] == ' ') {
putchar('_');
} else {
putchar(mat[i][j]);
}
}
printf("\n");
}
}
char encrypt(char *key){
char temp;
int i,j;
int n = strlen(key);
for (i = 0; i < n-1; i ) {
for (j = i 1; j < n; j ) {
if (key[i] > key[j]) {
temp = key[i];
key[i] = key[j];
key[j] = temp;
}
}
}
printf("The sorted string is : %s", key);
return 0;
}
CodePudding user response:
You have a 2D array. The first axis is the list of strings. The second axis is the characters of a particular string. I assume when you mean swap column, you mean swap characters of a particular string for all strings.
In pseudo code:
for all strings i
temp = mat[i][some column]
mat[i][some column] = mat[i][someother column]
mat[i][someother column] = temp
CodePudding user response:
My take on sorting in a function and swapping columns.
You do not want to swap the columns each time a bubble moves in the sorting algorithm until it reaches its final position. Therefore, the sorting can be performed separately.
I did not impose that the input string length is a multiple of the key length but just do not swap column elements when they are outside of the input data.
Determining which columns to swap is implemented in the following way:
- Iterate over all columns from start to end
- If a column has not been swapped, find its counterpart and swap them
- Mark both swapped columns in order to not swap them again, continue iteration
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <stdbool.h>
void sort_letters(char *phrase) {
int n = strlen(phrase);
printf("The string to sort is: %s\n", phrase);
for (int i = 0; i < n-1; i ) {
for (int 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);
}
void swap_columns(char *line, char *key, int i, int j){
int columns = strlen(key);
int rows = (strlen(line) columns - 1) / columns;
printf("Rows: %d Columns: %d\n", rows, columns);
for (int row = 0; row < rows; row ) {
int index_col_i = (row * columns) i;
int index_col_j = (row * columns) j;
if (index_col_j >= strlen(line)) {
printf("Row: - No swap because j outside of input\n", row);
break;
}
printf("Row: - Swap '%c' with '%c'\n",
row, line[index_col_i], line[index_col_j]);
char tmp = line[index_col_i];
line[index_col_i] = line[index_col_j];
line[index_col_j] = tmp;
}
}
void print_matrix(char *line, int columns) {
int rows = (strlen(line) columns - 1) / columns;
for (int i = 0; i < rows; i ){
printf("Row -: ", i);
for (int j = 0; j < columns; j ) {
putchar(line[i * columns j]);
}
putchar('\n');
}
}
int main(void) {
char line[256];
char key[50];
strcpy(line, "hello_there");
strcpy(key, "KEY");
printf("string: %s \nlength: %2zu\n", line, strlen(line));
printf("key: %s \nlength: %2zu\n", key, strlen(key));
char sorted_key[strlen(key)];
strcpy(sorted_key, key);
sort_letters(sorted_key);
printf("sorted key: %s \nlength: %2zu\n", key, strlen(sorted_key));
int columns = strlen(key);
print_matrix(line, columns);
bool is_used[columns];
for (int i = 0; i < columns; i ) is_used[i]= false;
for (int 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_columns(line, key, i, j);
is_used[i] = true;
is_used[j] = true;
}
}
print_matrix(line, columns);
return EXIT_SUCCESS;
}
$ gcc -Wall transposition.c
$ ./a.out
string: hello_there
length: 11
key: KEY
length: 3
The string to sort is: KEY
The sorted string is: EKY
sorted key: KEY
length: 3
Row 0: hel
Row 1: lo_
Row 2: the
Row 3: re
Rows: 4 Columns: 3
Row: 0 Swap 'h' with 'e'
Row: 1 Swap 'l' with 'o'
Row: 2 Swap 't' with 'h'
Row: 3 Swap 'r' with 'e'
Rows: 4 Columns: 3
Row: 0 Swap 'l' with 'l'
Row: 1 Swap '_' with '_'
Row: 2 Swap 'e' with 'e'
Row: 3 No swap because j outside of input
Row 0: ehl
Row 1: ol_
Row 2: hte
Row 3: er
$