Never giving up, I found the solution.
The problem was that I didn't understand some details (immutability) of how string arrays work so I did some lame workarounds (remember the "aaaaaaaa"
assignment...).
Eventually Initializing an array of characters with a string variable, How to convert a string to character array in c (or) how to extract a single char form string?, C char array initialization plus implementing the rule that the key should contain each chracter exactly once (which I do not find necessary!) led me to the solution which passes all the tests. I post it here:
#include <stdio.h>
#include <cs50.h>
#include <string.h>
#include <ctype.h>
int main(int argc, string argv[])
{
// Remember argc before argv control; otherwise segmentation fault
if (argc < 2)
{
printf("Usage: ./substitution key.\n");
return 1;
}
if (strlen(argv[1]) != 26)
{
printf("Key must contain 26 characters.\n");
return 1;
}
string key = argv[1];
int key_length = strlen(key);
for (int i = 0; i < key_length; i++)
{
if (!isalpha(argv[1][i]))
{
printf("Key must contain 26 characters.\n");
return 1;
}
}
// Error when key contains duplicate characters
for (int i = 0; i < key_length; i++)
{
for (int j = 0; j < key_length; j++)
{
if (i == j)
{
continue;
}
if (islower(key[i]))
{
char current_key_letter = key[i];
}
else
{
char current_key_letter = key[i] + 'A' - 'a';
}
if (key[i] == key[j])
{
printf("Key must contain 26 unique characters.\n");
return 1;
}
}
}
string plaintext = get_string("plaintext: ");
int plaintext_length = strlen(plaintext);
char output_text[plaintext_length];
strcpy(output_text, plaintext);
char lowcase_key[key_length];
strcpy(lowcase_key, key);
for (int i = 0, n = strlen(lowcase_key); i < n; i++)
{
lowcase_key[i] = tolower(key[i]);
}
for (int i = 0, n = plaintext_length; i < n; i++)
{
if (islower(plaintext[i]))
{
output_text[i] = lowcase_key[plaintext[i] - 'a'];
}
if (!isalpha(plaintext[i]))
{
output_text[i] = plaintext[i];
}
if (isupper(plaintext[i]))
{
output_text[i] = lowcase_key[plaintext[i] - 'A'] + 'A' - 'a';
}
}
printf("ciphertext: %s", output_text);
printf("\n");
return 0;
}
There are more elegant solutions, although I really like the - 'A'] + 'A' - 'a'
part, but that's OK for today. Thanks all for comments!