1

I'm a newbie, so apologies if I don't explain myself well. If it helps, I'm doing this for the Caesar problem set as part of the Harvard CS50x OpenCourseWare. I'm trying to convert user generated plain text to cipher text using a simple key. To accomplish this I'm attempting to use a wraparound counting formula in my last function. However, sometimes I get blanks that print out instead of the new characters... Help!

EDIT: I'm using a key of 5 and the plaintext "Helloz!" to test. Expect to see Mjqqte! instead am seeing blank spaces.

#include <stdio.h>
#include <cs50.h>
#include <string.h>
#include <math.h>
#include <ctype.h>
#include <stdlib.h>

int convert(string n);
string k, text;
char text;
int r, c, t,x;
bool validate(string n);
//int encrypted(string n);

int main(int argc, string argv[])
{
    //accept single command-line argument, non negative integer, k with appropriate error
    k = argv[1];
    
    if (argc > 1 && argc <= 2)
    {
        //printf("Success\n%s\n", argv[1]);
        // print individual characters of argv[i]
        validate(k);
    }
    
    else //if wrong input then print error message and main should return 1
    {
        printf("Usage: ./caesar key\n");
        return 1;
    }
    
    text = get_string("plaintext:");
    t = atoi(k);
    printf("%i\n", t);
    
    convert (text);
    printf("\n");
}
    //output "ciphertext:" without a newline, with the characters roated by k positions
    //after output, print a newline and exit by returning 0 from main


bool validate(string n)
{
   for (int i = 0; k[i] != '\0'; i++)
   {
        if (48 <= k[i] && k[i] <= 57)
        {
            //printf("%c\n", k[i]);
        }
        else
        {
            printf("./caesar key\n");
            return 1;
        // save for later: printf("%s \n", k);
        }
    }
    return r;
}

int convert(string n) 
{
    //if fits within a range, Reads individual characters
    for (int i = 0; i < text[i]; i++)
    {
        if (isalpha(text[i]))
        {
            x = text[i];
            //printf("%i\n", x);
      
            c = (x+t) % 26;
            // printf("%i\n",c);
      
            printf("%c", c);
        }
        else
        {
            printf("%i", text[i]);
        }
    }
    
    return 0;
}
Jonathan Leffler
  • 730,956
  • 141
  • 904
  • 1,278
irlupe
  • 11
  • 3
  • 1
    What are you doing with that for loop condition `i < text[i]`? I'm guessing that happens to work for short strings (shorter than about 65 chars long, depending on the content), but is not the right way to loop through a text string. – lxop Nov 18 '20 at 21:55
  • 1
    Your `c = (x+t) % 26;` is incorrect, you lose the prefix ascii value of the letter, it should be `c = 'a' + ((x - 'a' + t) % 26);`. Try it. – Uriya Harpeness Nov 18 '20 at 21:56
  • Please try to show a minimal self-contained program that reproduces the problem. Currently I don't know what input you gave, what output you got, or what you expected instead. – Useless Nov 18 '20 at 21:58
  • Note that the formula from @UriyaHarpeness will only work for lowercase letters - you may want to do further processing to handle both lowercase and capitals – lxop Nov 18 '20 at 21:58
  • 1
    Yes of course, the convension is lowercase for the decoded text, and uppercase to ciphertext, you can use `tolower` and `toupper` to achieve this. – Uriya Harpeness Nov 18 '20 at 22:03
  • Also, is this a cpp code? Because there's bool and string in there. – Uriya Harpeness Nov 18 '20 at 22:06
  • @lxop it worked for me so far, but would it have been more correct to use strlen? Also, my apologies. I'll edit my question to include this information. – irlupe Nov 18 '20 at 22:51
  • @UriyaHarpeness it seems I need to do some research on "prefix ascii values" as I didn't quite understand why it would be lost. Would you be able to provide any pointers on where I can learn more about this topic? Thank you for your answer- now I just need to get it to process the capitals. Working on it now. The bool and string bit are left over from when I was just trying to get it to work. As I mentioned, I'm very very new so my work is quite messy! – irlupe Nov 18 '20 at 22:54
  • You'll need to understand how ASCII encoding works to understand what @UriyaHarpeness is telling you. Read through a basic description of ASCII for that – lxop Nov 19 '20 at 01:29

1 Answers1

0

Here's an implementation that could work for you:

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <ctype.h>

void convert(char *text, unsigned char k) {
    for (unsigned int i = 0; i < strlen(text); i++) {
        if (isalpha(text[i])) {
            // Contains the 3 leftmost bits, containing the uppercase/lowercase part.
            char c = (text[i] / 32) * 32;
            // Perform the shifting with modulo on the alphabetic index of the letter.
            text[i] = c + ((text[i] % 32) + k) % 26;
        }
    }
}

int main(int argc, char *argv[]) {
    unsigned char k = strtol(argv[1], NULL, 10);
    char text[64];

    printf("Using key %d.\n", (int) k);
    printf("Plaintext: ");
    fgets(text, 64, stdin);
    // Remove newline.
    text[strlen(text) - 1] = 0;

    convert(text, k);
    printf("Ciphertext: %s.\n", text);

    return 0;
}

Test run:

>>> cipher 4
Using key 4.
Plaintext: Test mE Right Away!!1
Ciphertext: Xiwx qI Vmklx Eaec!!1.
Uriya Harpeness
  • 628
  • 1
  • 6
  • 21