-1

In the below code, I get different output depending on where I place the 'Printf("Ciphertext: )' statement, and I cannot understand why. Could anyone please point out what I am missing? Below you can find the code, and the output (variable piece in bold).

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


int main(int argc, string argv[]) 
{
int j = strlen(argv[1]); 
if (argc != 2) 
    {
    printf ("Usage: ./caesar key\n");
    return (1);
    }  

else 
   { 

    for (int i = 0; i < j; i++)
        { 
            if (!isdigit (argv[1][i]))
            {
                printf ("Fail\n");
                return(1);     
            }
        }  

          int convert = atoi (argv[1]) ;


          string Plaintext = get_string("Plaintext: ");
          int z = strlen(Plaintext);
          **printf("Ciphertext: ");** 

          for (int i = 0; i<z;i++)
          {
             char Ciphertext [z];
             Ciphertext [i] = (Plaintext [i] + 1);
            }


            for (int i = 0; i<z;i++)
          {
              char Ciphertext [z];
              printf("%c", Ciphertext [i]);   
            }
        printf("\n");




    }   



}  

If I run ./caesar with this code, and enter 'Hey' in the plaintext prompt, the output is Ciphertext: ifz, with which I am happy. However, when I place the printf("Ciphertext: ")Statement to a place that seems more logical to me, I don't get the same output:

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


int main(int argc, string argv[]) 
{
int j = strlen(argv[1]); 
if (argc != 2) 
    {
    printf ("Usage: ./caesar key\n");
    return (1);
    }  

else 
   { 

    for (int i = 0; i < j; i++)
        { 
            if (!isdigit (argv[1][i]))
            {
                printf ("Fail\n");
                return(1);     
            }
        }  

          int convert = atoi (argv[1]) ;


          string Plaintext = get_string("Plaintext: ");
          int z = strlen(Plaintext);


          for (int i = 0; i<z;i++)
          {
             char Ciphertext [z];
             Ciphertext [i] = (Plaintext [i] + 1);
            }

            **printf("Ciphertext: ");** 


            for (int i = 0; i<z;i++)
          {
              char Ciphertext [z];
              printf("%c", Ciphertext [i]);   
            }
        printf("\n");




    }   



}  

When I do the exact same here, I print Ciphertext: and an empty row, but it doesn't print out the ciphertext [] as above. Any ideas?

Jonathan Leffler
  • 730,956
  • 141
  • 904
  • 1,278
Zegher V
  • 117
  • 7
  • 2
    In your not-working code you create a new variable `Ciphertext`. So what value should it have? You must avoid creating important variables inside blocks; their value will be lost when the block ends. – Jongware Feb 07 '20 at 10:05

1 Answers1

0

As noted by usr2564301 in the comment, you need to declare Ciphertext once so that it doesn't go out of scope. When it goes out of scope, the old value is formally lost — you may or may not see it again (because it is undefined behaviour to access uninitialized memory, so any result is valid).

Note that although you convert argv[1] to an integer, you don't use the result. The + 1 in the encoding means that it appears as if you always supplied 1 as argv[1]. Your code does not do wraparound so that z is mapped to a. It doesn't properly handle upper-case and lower-case either. You probably shouldn't try to encode non-letters, either. However, this fairly straight-forward adaptation of your code at least produces the semblance of a result:

#include <cs50.h>
#include <ctype.h>
#include <stdio.h>
//#include <stdlib.h>    // Needed if atoi() is called
#include <string.h>

int main(int argc, string argv[])
{
    // This checking is not relevant while the encryption only adds 1
    if (argc != 2)
    {
        printf("Usage: ./caesar key\n");
        return(1);
    }
    int j = strlen(argv[1]);
    for (int i = 0; i < j; i++)
    {
        if (!isdigit(argv[1][i]))
        {
            printf("Fail\n");
            return(1);
        }
    }
    // int convert = atoi(argv[1]);

    string Plaintext = get_string("Plaintext: ");
    int z = strlen(Plaintext);
    char Ciphertext[z];

    for (int i = 0; i < z; i++)
    {
        Ciphertext[i] = (Plaintext[i] + 1);    // Should use convert, etc
    }

    printf("Ciphertext: ");

    for (int i = 0; i < z; i++)
    {
        printf("%c", Ciphertext[i]);
    }
    printf("\n");
    return 0;
}

Sample run (program cs79 created from source code cs79.c):

$ cs79 13
Plaintext: Bright vixens jump; dozy fowl quack.
Ciphertext: Csjhiu!wjyfot!kvnq<!ep{z!gpxm!rvbdl/
$
Jonathan Leffler
  • 730,956
  • 141
  • 904
  • 1,278
  • I don't see where the result of the first half of the program is used. – S.S. Anne Feb 07 '20 at 21:24
  • 1
    @S.S.Anne: It isn't used — I commented in the answer that `convert` is not used (and commented it out in the code). I didn't remove the code that checks that `argv[1]` is all numeric before conversion. That would be relevant if `convert` were used in place of the `1` in `Plaintext[i] + 1`. That whole section needs a lot of work (encode letters only; wrap around from `z` to `a`, etc). – Jonathan Leffler Feb 07 '20 at 21:27