Got stuck with Caesar.c - c

I am trying to run the program assignment caesar.c from the edx Introduction to programming. It requires a program able to encrypt a string with the Caesar encryption: therefore, the user has to enter a key (command-line); for example with a key of 2 a 'A' character needs to be encrypted in a 'C' character; the problem starts when you have to enter a key greater than 26, which is the number of alphabetical letters. For a key of 27 and an 'A' character for example, the program must return 'B' like a key of 1.
I have tried to transform the ASCII values of the characters to alphabetical values from 0 to 26 in order to use the modulus operator when the key is equal or greater than 26.
It returns me a segmentation fault. Can anyone help me with some suggestions of the causes of my error?
Here's the program:
#include <stdio.h>
#include <cs50.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
int key;
// function for an alphabetic value with non capital letters
int alpha_low( char c )
{
int alpha_value;
alpha_value = (int) c - 97;
return alpha_value + ( key % 26 );
}
// function to return to ascii valuee for non capital letters
char ascii_low( char c )
{
return (char) alpha_low( c ) + 97;
}
// function for an alphabetic value with capital letters
int alpha_up( char c )
{
int alpha_value;
alpha_value = (int) c - 65;
return alpha_value + ( key % 26 );
}
// function to return to ascii value for capital letters
char ascii_up( char c )
{
return (char) alpha_up( c ) + 65;
}
int main(int argc, string argv[])
{
int result;
string p;
key = atoi( argv[1] );
if( argc != 2 || key < 0 )
{
printf("Usage: ./caesar key(positive integer)\n");
return 1;
}
printf("Please, write a plaintext: ");
p = GetString();
for( int i = 0, n = strlen(p); i < n; i++)
{
if ( isalpha(p[i]) )
{
if ( islower(p[i]) )
{
result = alpha_low( p[i] );
printf("%c", ascii_low( p[i] ));
}
else if( islower( p[i]) )
{
result = alpha_up( p[i] );
printf("%c", ascii_up( p[i]) );
}
}
}
return 0;
}

A function to caesar an alphabetic char should be like (decomposed in elementary steps):
int caesar_lower(int c,int key) {
int v = c-'a'; // translate 'a'--'z' to 0--25
v = v+key; // translate 0--25 to key--key+25
v = v%26; // translate key--key+25 to key--25,0--key-1
v = v+'a'; // translate back 0--25 to 'a'--'z'
return v;
}

Related

Program don't encrypt the way I want (C language). From CS-50 lesson Vegenere

Program must encrypt plaintext by the key from command-line.
If p is some plaintext and k is a keyword (i.e., an alphabetical string, whereby A (or a) represents 0, B (or b) represents 1, C (or c) represents 2, …, and Z (or z) represents 25), then each letter, ci, in the ciphertext, c, is computed as:
ci = (pi + kj) % 26
Note this cipher’s use of kj as opposed to just k. And if k is shorter than p, then the letters in k must be reused cyclically as many times as it takes to encrypt p.
In other words, if Vigenère himself wanted to say HELLO to someone confidentially, using a keyword of, say, ABC, he would encrypt the H with a key of 0 (i.e., A), the E with a key of 1 (i.e., B), and the first L with a key of 2 (i.e., C), at which point he’d be out of letters in the keyword, and so he’d reuse (part of) it to encrypt the second L with a key of 0 (i.e., A) again, and the O with a key of 1 (i.e., B) again. And so he’d write HELLO as HFNLP, per the below:
In that way:
plaintext H E L L O
+key A B C A B
(shift value) 0 1 2 0 1
= ciphertext H F N L P
For example:
$ ./vigenere bacon
plaintext: Meet me at the park at eleven am
ciphertext: Negh zf av huf pcfx bt gzrwep oz
My case:
key: baz
plaintext: barfoo
expected: caqgon
my result: caqfgv
My code:
#include <cs50.h>
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#include <string.h>
// Functions:
bool check_arguments(int argc);
bool is_key_alpha(string key);
int shift(char c);
int main(int argc, string argv[])
{
if (check_arguments(argc) == false)
{
return 1;
}
// Declaring key string variable:
string key = argv[1];
// Check containing any character that is not an alphabetic character
if (is_key_alpha(key) == false)
{
return 1;
}
// Prompting user for plaintext:
string plaintext = get_string("plaintext: ");
// Ecipher:
printf("ciphertext: ");
for (int i = 0; i < strlen(plaintext); i++)
{
if (islower(plaintext[i]))
{
printf("%c", ((plaintext[i]) - 97 + shift(key[i])) % 26 + 97);
}
else if (isupper(plaintext[i]))
{
printf("%c", ((plaintext[i]) - 65 + shift(key[i])) % 26 + 65);
}
else
{
printf("%c", plaintext[i]);
}
}
printf("\n");
return 0;
}
// FUNCTIONS :
// Checking if there's more than one command-line argument
// Checking if the command-line argument exists:
bool check_arguments(int argc)
{
// Checking if there's more than one command-line argument
if (argc > 2)
{
printf("Usage: ./vigenere keyword\n\n");
return false;
}
// Checking if the command-line argument exists:
else if (argc < 2)
{
printf("Usage: ./vigenere keyword\n");
return false;
}
// If okey:
else
{
return true;
}
}
// containing any character that is not an alphabetic character
bool is_key_alpha(string key)
{
for (int i = 0; i < strlen(key); i++)
{
if (isalpha(key[i]) == false)
{
printf("Key contains non-alphabetical chars");
return false;
}
}
return true;
}
// convert character into the correct shift value
int shift(char c)
{ // for ex. char = a == 97 ascii
if (isalpha(c))
{
if (isupper(c))
// The ASCII value of A is 65
{
c = c - 65;
}
else if (islower(c))
// The ASCII value of a is 97
{
c = c - 97;
}
}
else
{
return c;
}
return c;
}
Barry is on the right track. It is UB. On my system, I got: caqflr
If i hits the length of key, then key[i] goes beyond the end of key
Change:
shift(key[i])
Into:
shift(key[i % strlen(key)])
That fixes the bug.
But, the code is more complicated than it needs to be. That may be one reason why the issue was difficult to spot.
Also, the code runs slowly.
Using strlen when looping on a string changes the running time from O(n) to O(n^2). That's because strlen rescans the string on every loop iteration.
So, to fix this, change (e.g.):
for (int i = 0; i < strlen(plaintext); ++i)
Into:
for (int i = 0; plaintext[i] != 0; ++i)
Also, in such loops there is a lot of replicated code using plaintext[i].
Although the optimizer will understand this and produce fast code (i.e. cache the value and not refetch plaintext[i]), it can be simplified if we use an extra variable to contain the current value:
for (int i = 0, chr = plaintext[i]; chr != 0; chr = plaintext[++i])
Now, instead of using plaintext[i] in many places within the loop we can use chr
This is usually easier to read. And, ironically, is close/similar to the code the optimizer will generate.
The length of the key is invariant. So, we can precompute the value and just use it rather than recalculating it on every iteration of the plaintext loop.
Avoid using "magic numbers":
When you want 'A' use it instead of 65
When you want 'a' use it instead of 97
Also, shift can be improved / eliminated:
Because is_key_alpha checks with isalpha, key is guaranteed to be only alpha chars. So, no need for shift to use isalpha
We don't need to keep the original key value, only the modified one. That is, we can replace every value in key with the result of shift
In other words, we only need to do the shift operation for each key once, during initialization. We can have is_key_alpha do this.
Here is the refactored code:
#include <cs50.h>
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#include <string.h>
// Functions:
bool check_arguments(int argc);
bool is_key_alpha(string key);
int shift(char c);
int
main(int argc, string argv[])
{
if (check_arguments(argc) == false) {
return 1;
}
// Declaring key string variable:
string key = argv[1];
// get the length of the key
// (1) cache it so we don't need to call strlen(key) in the loop (it's
// invariant)
// (2) because is_key_alpha transforms the key, calling strlen on key
// will no longer be valid
int klen = strlen(key);
// Check containing any character that is not an alphabetic character
if (is_key_alpha(key) == false)
return 1;
// Prompting user for plaintext:
string plaintext = get_string("plaintext: ");
// Ecipher:
printf("ciphertext: ");
for (int i = 0, chr = plaintext[i]; chr != 0; chr = plaintext[++i]) {
int k = key[i % klen];
if (islower(chr)) {
chr = ((chr - 'a') + k) % 26 + 'a';
}
else if (isupper(chr)) {
chr = ((chr - 'A') + k) % 26 + 'A';
}
printf("%c", chr);
}
printf("\n");
return 0;
}
// FUNCTIONS :
// Checking if there's more than one command-line argument
// Checking if the command-line argument exists:
bool
check_arguments(int argc)
{
// Checking if there's more than one command-line argument
if (argc > 2) {
printf("Usage: ./vigenere keyword\n\n");
return false;
}
// Checking if the command-line argument exists:
else if (argc < 2) {
printf("Usage: ./vigenere keyword\n");
return false;
}
// If okey:
else {
return true;
}
}
// containing any character that is not an alphabetic character
bool
is_key_alpha(string key)
{
// do what shift does and convert the key into offsets
for (int i = 0, chr = key[i]; chr != 0; chr = key[++i]) {
if (isupper(chr)) {
key[i] = chr - 'A';
continue;
}
if (islower(chr)) {
key[i] = chr - 'a';
continue;
}
printf("Key contains non-alphabetical chars");
return false;
}
return true;
}
// convert character into the correct shift value
int
shift(char c)
{ // for ex. char = a == 97 ascii
// The ASCII value of A is 65
// The ASCII value of a is 97
// NOTES:
// (1) is_key_alpha guarantees that the key value is an alpha
// (2) now that is_key_alpha computes the offset, this function is obsolete
if (isupper(c))
c -= 'A';
else if (islower(c))
c -= 'a';
return c;
}
We can tighten this up a bit further. shift is no longer needed. And, we can have is_key_alpha return the key length (-1 is error). Now, that it changes the key, we could rename it to be more descriptive of its function
#include <cs50.h>
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#include <string.h>
// Functions:
bool check_arguments(int argc);
int key_transform(string key);
int
main(int argc, string argv[])
{
if (check_arguments(argc) == false) {
return 1;
}
// Declaring key string variable:
string key = argv[1];
// check and transform the key
int klen = key_transform(key);
if (klen < 0)
return 1;
// Prompting user for plaintext:
string plaintext = get_string("plaintext: ");
// Ecipher:
printf("ciphertext: ");
for (int i = 0, chr = plaintext[i]; chr != 0; chr = plaintext[++i]) {
int k = key[i % klen];
if (islower(chr)) {
chr = ((chr - 'a') + k) % 26 + 'a';
}
else if (isupper(chr)) {
chr = ((chr - 'A') + k) % 26 + 'A';
}
printf("%c", chr);
}
printf("\n");
return 0;
}
// FUNCTIONS :
// Checking if there's more than one command-line argument
// Checking if the command-line argument exists:
bool
check_arguments(int argc)
{
// Checking if there's more than one command-line argument
if (argc > 2) {
printf("Usage: ./vigenere keyword\n\n");
return false;
}
// Checking if the command-line argument exists:
else if (argc < 2) {
printf("Usage: ./vigenere keyword\n");
return false;
}
// If okey:
else {
return true;
}
}
// check and transform the key
// RETURNS: key length (-1=error)
int
key_transform(string key)
{
// do what shift does and convert the key into offsets
int i = 0;
for (int chr = key[i]; chr != 0; chr = key[++i]) {
if (isupper(chr)) {
key[i] = chr - 'A';
continue;
}
if (islower(chr)) {
key[i] = chr - 'a';
continue;
}
printf("Key contains non-alphabetical chars");
return -1;
}
return i;
}

Digit Frequency Program (HackerRank)

I'm trying to compare each character of the given string with numbers 0 to 9, and on successful comparison, increment the count variable. Finally, printing the value of count variable for each of the numbers.
But these method isn't working out. Can't figure out why.
int main() {
char *s;
s = malloc(1024 * sizeof(char));
scanf("%[^\n]", s);
int i,j,count=0;
for(i=0;i<=9;i++)
{
for(j=0;j<strlen(s);j++)
{
if(s[j]==i)
{
count++;
}
}
printf("%d ",count);
}
return 0;
}
Finally, printing the value of count variable for each of the numbers.
So you need an array to store counters for each digit. It is strange that zero is excluded from counted digits.
In this if statement
if(s[j]==i)
you have to write at least
if( s[j] - '0' == i )
And moreover this loop
for(i=0;i<=9;i++)
also tries to count zeroes though you wrote that to count only digits 1-9 inclusively.
Your approach is inefficient because you are traversing the same character array several times.
And there is no sense to allocate a character array dynamically.
The program can look the following way
#include <stdio.h>
int main(void)
{
enum { M = 9, N = 1024 };
char s[N];
s[0] = '\0';
size_t counter[M] = { 0 };
fgets( s, N, stdin );
for ( const char *p = s; *p; ++p )
{
if ( '0' < *p && *p <= '9' )
{
++counter[*p - '0' - 1];
}
}
for ( size_t i = 0; i < M; i++ )
{
printf( "%zu ", counter[i] );
}
putchar( '\n' );
return 0;
}
If to enter for example a string like
12345678987654321246897531
then the output will be
3 3 3 3 3 3 3 3 2
In fact the character array is redundant for this task. Moreover it restricts the length of the entered sequence of digits. You could write the program without using a character array. For example
#include <stdio.h>
int main(void)
{
enum { M = 9, N = 1024 };
size_t counter[M] = { 0 };
for ( int c; ( c = getchar() ) != EOF && c != '\n'; )
{
if ( '0' < c && c <= '9' )
{
++counter[c - '0' - 1];
}
}
for ( size_t i = 0; i < M; i++ )
{
printf( "%zu ", counter[i] );
}
putchar( '\n' );
return 0;
}
if(s[j]==i) <<<<<<<<<
{
count++;
}
You are comparing the ordinal value of the character to an integer in the range 0 to 9. Which is not what you want.
You can convert a digit to int with this method:
char c = '5';
int x = c - '0';
So in your case it would be:
if(s[j] -'0' ==i)
{
count++;
}
In C a character value is a number, but it is not the number you are expecting here. When we have the character '2' and we check what it is equal to as a number we are really asking what the ASCII code of '2' is which in this case would be 50. You need to adjust your code so it converts the ASCII code into a numeric representation so 50 becomes 2. It is quite simple simply change your code so it looks like this
if((s[j] - '0') == i){
This works because the ASCII code of 0 is 48, the ASCII code of 1 is 49, etc etc.
TL;DR In C a character value is not equal to it's numeric value. You need to convert '5' to 5. To do this you adjust your code so you subtract the '0' character from your numeric character.

Wanted to do caesar's cipher but couldn't change the last two characters

I wrote a code for caesar's cipher and the code works except I can't cipher more than 8 letters and I also can't handle spaces. It shows ">>" this symbol instead of spaces. Also, I wanted to do binary search in the second function of my code but I don't know whether I have done that or not.
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
char caesar (char x, char alphabets[]);
int j;
int main()
{
char* plain_text = malloc (10 * sizeof(char) + 1);
int key, num;
char* cipher_text = malloc (10 * sizeof(char) + 1);
printf("Plain text: ");
gets(plain_text);
printf("\nThe plain text is: ");
puts(plain_text);
printf("\nKey: ");
scanf("%d", &key);
num = (int)key;
if (key != num)
{
return 1;
}
int i;
char alphabets[] = {'a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v','w','x','y','z'};
for (i=0;i<=strlen(plain_text);i++)
{
char x = plain_text[i];
caesar(x, alphabets);
cipher_text[i] = alphabets[j+key];
printf("%c", cipher_text[i]);
}
free(plain_text);
}
char caesar (char x, char alphabets[])
{
if(x == alphabets[13])
{
return 13;
}
for(j = 1; j <= 13; j++)
{
if(x == alphabets[j])
{
return j;
}
}
for(j = 13; j <= strlen (alphabets); j++)
{
if(x == alphabets[j])
{
return j;
}
}
}
caesar() appears to simply return the position of characters b to z in the array in a remarkably over complex manner and omits a altogether! Moreover since alphabets is not a null terminated string strlen() is not a valid operation in any case. The "encryption" is done (incorrectly) by alphabets[j+key] in main() making caesar() particularly poorly named - since that is not what it does at all.
The following function will return the the cipher of any character in alphabet, and leave any other character unmodified:
char caesar( char x, int key )
{
const char alphabet[] = {'a','b','c','d','e','f','g','h',
'i','j','k','l','m','n','o','p',
'q','r','s','t','u','v','w','x',
'y','z'};
char cipher = x ;
for( int i = 0;
cipher == x && i < sizeof( alphabet );
i++ )
{
if( alphabet[i] == x )
{
cipher = alphabet[(i + key) % sizeof( alphabet )] ;
}
}
return cipher ;
}
It makes far more sense to pass key to ceasar() that to pass the constant alphabet, and to do the encryption where is alphabet is "known". Splitting the cipher steps between caesar() and main() as you had done is a poor design and lacks cohesion and has unnecessary coupling.
If the character x appears in alphabet it is modified by alphabet[(i + key) % sizeof( alphabet )] ;. This adds the key as you had, but also "wraps-around" (the % modulo operation), so that for example for key = 1, z wraps around to a rather then referencing a byte beyond the end of the alphabet array as your code had. Critically, if it does not appear in alphabet, it is unmodified - that is why cipher is initialised with x. The loop exits when cipher is modified (cipher != x), or when the end of alphabet is reached.
Then in the iteration of plain_text:
for (i = 0; i <= strlen(plain_text); i++ )
{
cipher_text[i] = caesar( plain_text[i], key ) ;
}
The <= strlen() here is unusual, but here it ensures the nul terminator is copied to cipher_text - it will not be modified by caesar().
Note that the the above solution only encrypts lower case text (as does your original code). There are other issues and ill-advised practices in your code, discussed in the comments but not perhaps directly relevant to your question, but using the above function, the following complete implementation addresses most of the issues:
#include <stdio.h>
#include <string.h>
char caesar( char x, int key ) ;
#define MAX_TEXT 128
int main()
{
char plain_text[MAX_TEXT] = "" ;
char cipher_text[MAX_TEXT] = "" ;
printf( "Plain text: " );
fgets( plain_text, MAX_TEXT, stdin ) ;
printf( "\nThe plain text is: %s\n", plain_text ) ;
printf( "Key: " ) ;
int key = 0 ;
scanf( "%d", &key );
for( size_t i = 0; i <= strlen( plain_text ); i++ )
{
cipher_text[i] = caesar( plain_text[i], key ) ;
}
printf( "\nThe cipher text is: %s\n", cipher_text ) ;
return 0 ;
}
Example:
Plain text: abc, xyz
The plain text is: abc, xyz
Key: 1
The cipher text is: bcd, yza
Modification to allow capital letters:
#include <ctype.h>
char caesar( char x, int key )
{
const char alphabet[] = {'a','b','c','d','e','f','g','h',
'i','j','k','l','m','n','o','p',
'q','r','s','t','u','v','w','x',
'y','z'};
char cipher = x ;
for( int i = 0;
cipher == x && i < sizeof( alphabet );
i++ )
{
if( alphabet[i] == tolower( x ) )
{
cipher = alphabet[(i + key) % sizeof( alphabet )] ;
if( isupper( x ) )
{
cipher = toupper( cipher ) ;
}
}
}
return cipher ;
}
Here the test alphabet[i] == tolower( x ) ignores the case, and then when a match is fount the application of cipher = toupper( cipher ) if x is upper case, yields the upper case cipher.
Example output:
Plain text: aBc, XyZ 123
The plain text is: aBc, XyZ 123
Key: 1
The cipher text is: bCd, YzA 123
Note that instead of testing cipher = x in the for loop, you could break after cipher is assigned in the loop - reducing the number of tests - but that arguably breaks structured programming "rules" - I would not criticise its use by others, but it is not my preference. You might also use isalpha(x) in this case to skip the loop altogether, but that has implementation defined behaviours for accented characters for example, so if you were to extend the supported "alphabet", it might fail to work as intended.
If you only ever use the characters a to z in the alphabet as you have, then a further simplification is possible where the cipher can be determined arithmetically using character code values:
char caesar( char x, int key )
{
char cipher = tolower( x ) ;
if( isalpha( x ) )
{
cipher = ((cipher - 'a') + key) % ('z' - 'a' + 1) + 'a' ;
if( isupper( x ) )
{
cipher = toupper( cipher ) ;
}
}
return cipher ;
}
Strictly this assumes that the characters a to z are contiguous in the target character set, but that is universally true for any system you are likely to run this code on (i.e. not an IBM Z series mainframe or various antique mainframe/mini computers), and if not the alphabet array solution remains valid. I point this out only because otherwise someone will place a comment about it as if it is really an issue.
To explain the expression: cipher = ((cipher - 'a') + key) % ('z' - 'a' + 1) + 'a' :
(cipher - 'a') - subtract the code for 'a' to get a value 0 to 25 for characters a to z.
... + key - add the key "shift"
... % ('z' - 'a' + 1) - this constant expression resolves to % 26 in practice, to "wrap-around".
... +a- transform the range 0 to 25 back into character codesatoz`.

Caesar’s cipher encryption program in C

I am using this code for Caesar’s cipher encryption program. c = (alpha + k) % 26; //c = cipher text ASCII code, "alpha" alphabet ASCII code, "k" key for cipher text; this equation gives me zero(0) on all the 26 alphabets.
Thank You!
#include <stdio.h>
#include <stdlib.h>
#include <cs50.h>
#include <string.h>
#include <ctype.h>
int main (int argc, string argv[]) {
// took key from user and converted it to int
int k = atoi (argv[1]);
// get plaintext from user
string p = GetString ();
int c = 0, alpha = 0;
for (int i = 0, n = strlen(p); i < n; i++)
{
// if it is alphabet else if not alphabet
if (isalpha (p[i]) == true) {
// if it is capital case else lower case
if (isupper(p[i]) == true) {
alpha = p[i] - 65;
// add key to plaintext then take modulas
c = (alpha + k) % 26;
alpha = c + 65;
} else {
alpha = p[i] - 97;
// add key to plaintext then take modulas
c = (alpha + k) % 26;
alpha = c + 97;
}
} else {
alpha = p[i];
}
printf("%c \n", alpha);
}
}
From documentation of isalpha
Each of these routines returns nonzero if c is a particular
representation of an alphabetic character
So when you say if (isalpha (p[i]) == true) you are comparing what ever non-zero value returned by isalpha()(which may not be 1) with 1(true) which may not hold true and that if block will not be executed. The same goes for isupper(). So basically i don't think the equation is giving you zero, its just the if block the equation is in is not being executed.
You may want to do:
if (isalpha(p[i])
{
if (isupper(p[i])
{
//your code
}
...//your code
}

Using a returned value from a function in C

My goal is to make a Vigenere cipher. I am attempting to do this by getting the key from argv, getting the string from the user, then passing the message and key though a function I made which combined them and returns the new value before printing it. For some reason it is just printing the key. I think it has something to do with the new function and how I am trying to use the returned value. Here is the code:
#include <stdio.h>
#include <stdlib.h>
#include <cs50.h>
#include <string.h>
#include <stdbool.h>
#include <ctype.h>
int new_crypt;
int encrypt(string , int );
int main(int argc, string argv[])
{
if( argc != 2)
{
printf("Plese enter only one key");
return 1;
}
string message = GetString();
for(int i=0; i < strlen(message); i++)
{
int klen = strlen(argv[1]);
//repeats the key until the message is over
int key= argv[1][i%klen];
bool kupper = isupper(key);
bool klower = islower(key);
bool kalpha = isalpha(key);
if(kupper == true){
//ASCII value of A is 65. 'A' = 0 shifts
int k = key-65;
int new_crypt = encrypt(message, k);
printf("%c", new_crypt);
}
if(klower == true){
//ASCII value of 'a' is 97. 'a' = 0 shifts
int k = key- 97;
int new_crypt = encrypt(message, k);
printf("%c", new_crypt);
}
if(kalpha == false){
int k = 0;
int i = i-1;
int new_crypt = encrypt(message, k);
printf("%c", new_crypt);
}
}
printf("\n");
return 0;
}
int encrypt(string message, int k)
{
for(int i=0; i < strlen(message); i++)
{
bool upper = isupper(message[i]);
if(upper == true)
{ //Makes sure the message doesnt go past 'Z'.. If it does it mod 90 it / // and adds 65 ('A')
int crypt = (message[i]+ k) % 90;
if(crypt < 65)
{
int new_crypt = (crypt + 65);
return new_crypt;
}
else{
int new_crypt = crypt;
return new_crypt;
}
}
bool lower = islower(message[i]);
if(lower == true)
{
int crypt = (message[i]+ k) % 123;
if(crypt < 97)
{
int new_crypt = crypt + 97;
return new_crypt;
}
else{
int new_crypt = crypt;
return new_crypt;
}
}
bool alpha = isalpha(message[i]);
if(alpha == false)
{
int new_crypt = message[i];
return new_crypt;
}
}
return 0;
}
The loop in the encrypt function is completely useless, because there is no path through the loop-body without a return statement causing the loop to be terminated and control returned to the caller of encrypt. This makes that the program as a whole repeatedly encrypts the first character of the message with successive elements from the key.
The easiest way around this is to make the following changes
Remove the loop from the encrypt function
Pass, as an additional argument, the element from the message that you want to encrypt, making the signature
int encrypt(string message, int k, int i)
Some miscellaneous remarks:
The global variable new_crypt is not used anywhere. You can safely remove it. (You should avoid the use of global variables as much as reasonably possible).
Instead of using the magic number 65, you can also use the character literal 'A'. This has the advantage that you don't need a comment to explain the number 65 and that it is always the correct value for the capital A, even if you end up not using ASCII. (But see also the next bullet)
Your code assumes the letters A to Z (and a to z) have contiguous values (such that Z == A+26). This may happen to be the case for the English alphabet in the ASCII encoding, but it is not guaranteed for other language alphabets or encodings.

Resources