CS50 Vigenere program The 2019 Stack Overflow Developer Survey Results Are InVigenere...

How to change the limits of integration

How long do I have to send payment?

How come people say “Would of”?

Carnot-Caratheodory metric

Does a dangling wire really electrocute me if I'm standing in water?

Geography at the pixel level

Where to refill my bottle in India?

Idiomatic way to prevent slicing?

Is three citations per paragraph excessive for undergraduate research paper?

What does "sndry explns" mean in one of the Hitchhiker's guide books?

Why is the maximum length of openwrt’s root password 8 characters?

Should I use my personal or workplace e-mail when registering to external websites for work purpose?

Is bread bad for ducks?

How to create dashed lines/arrows in Illustrator

Could JWST stay at L2 "forever"?

Is there a name of the flying bionic bird?

How are circuits which use complex ICs normally simulated?

It's possible to achieve negative score?

aging parents with no investments

I looked up a future colleague on linkedin before I started a job. I told my colleague about it and he seemed surprised. Should I apologize?

Can I write a for loop that iterates over both collections and arrays?

Why is it "Tumoren" and not "Tumore"?

Is it possible for the two major parties in the UK to form a coalition with each other instead of a much smaller party?

Evaluating number of iteration with a certain map with While



CS50 Vigenere program



The 2019 Stack Overflow Developer Survey Results Are InVigenere encryptionVigenere square cypher decryptionVigenere cipher in HaskellVigenere cipher breakerVigenere Cipher in CCS50 Vigenere CipherVigenere Cipher - Haskell ImplementationVigenere encryption assignment for CS50 C courseC Vigenere EncryptorVigenere Decypher in C++





.everyoneloves__top-leaderboard:empty,.everyoneloves__mid-leaderboard:empty,.everyoneloves__bot-mid-leaderboard:empty{ margin-bottom:0;
}







3












$begingroup$


I wrote a program for a problem in Harvard's CS50 course, Vigenere (week 2).



Here is a description of what the program needs to do:




Design and implement a program that encrypts messages using Vigenère’s cipher.




  • Implement your program in a file called vigenere.c in a directory
    called vigenere.


  • Your program must accept a single command-line argument: a keyword, k, composed entirely of alphabetical characters.


  • If your program is executed without any command-line arguments, with more than one command-line argument, or with one command-line argument that contains any non-alphabetical character, your program should print an error (of your choice) and exit immediately, with main returning 1 (thereby signifying an error).


  • Otherwise, your program must proceed to prompt the user for a string of plaintext, p, (as by a prompt for plaintext:) which it must then encrypt according to Vigenère’s cipher with k, ultimately printing the result (prepended with ciphertext: and ending with a newline) and exiting, with main returning 0.


  • With respect to the characters in k, you must treat A and a as 0, B and b as 1, …​, and Z and z as 25.


  • Your program must only apply Vigenère’s cipher to a character in p if that character is a letter. All other characters (numbers, symbols, spaces, punctuation marks, etc.) must be outputted unchanged. Moreover, if your code is about to apply the jth character of k to the ith character of p, but the latter proves to be a non-alphabetical character, you must wait to apply that jth character of k to the next alphabetical character in p; you must not yet advance to the next character in k.


  • Your program must preserve the case of each letter in p.





I received full credit for my answer, but I still want to clean up the code if possible. I am new to programming, so I enjoy seeing what changes more experienced programmers would make.



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

int check(string argv);
int shift(char c);

int main(int argc, string argv[])
{
//check for valid key and save
int valid = 0;
if (argc == 2)
{
valid = check(argv[1]);
}
else
{
printf("Usage: ./vigenere keywordn");
return 1;
}


//begin encryption
int key;
int index = -1;
int new_code;
if (valid == 1)
{
//get plaintext to encrypt
string plaintext = get_string("plaintext: ");
printf("ciphertext: ");

//iterate through each char of plaintext
for (int j = 0, l = strlen(plaintext); j < l; j++)
{
if (isalpha(plaintext[j]))
{
//iterate through the keyword only when there is an alpha in the plaintext
index++;
key = shift(tolower(argv[1][index % strlen(argv[1])]));
new_code = (int) plaintext[j] + key;
if ((int) tolower(plaintext[j]) + key > 122)
{
new_code = new_code - 26;
printf("%c", (char) new_code);
}
else
{
printf("%c", (char) new_code);
}
}
else
{
printf("%c", (char) plaintext[j]);
}
}
printf("n");
}
else
{
printf("Usage: ./vigenere keywordn");
return 1;
}
}

//create key
int shift(char c)
{
int key = (int) c - 97;
return key;
}

//decide if key is valid
int check (string argv)
{
int val = 0;
for (int i = 0, n = strlen(argv); i < n; i++)
{
if (isalpha(argv[i]))
{
val = 1;
}
else
{
val = 0;
break;
}
}
return val;
}









share|improve this question









New contributor




Snoop2001 is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.







$endgroup$



















    3












    $begingroup$


    I wrote a program for a problem in Harvard's CS50 course, Vigenere (week 2).



    Here is a description of what the program needs to do:




    Design and implement a program that encrypts messages using Vigenère’s cipher.




    • Implement your program in a file called vigenere.c in a directory
      called vigenere.


    • Your program must accept a single command-line argument: a keyword, k, composed entirely of alphabetical characters.


    • If your program is executed without any command-line arguments, with more than one command-line argument, or with one command-line argument that contains any non-alphabetical character, your program should print an error (of your choice) and exit immediately, with main returning 1 (thereby signifying an error).


    • Otherwise, your program must proceed to prompt the user for a string of plaintext, p, (as by a prompt for plaintext:) which it must then encrypt according to Vigenère’s cipher with k, ultimately printing the result (prepended with ciphertext: and ending with a newline) and exiting, with main returning 0.


    • With respect to the characters in k, you must treat A and a as 0, B and b as 1, …​, and Z and z as 25.


    • Your program must only apply Vigenère’s cipher to a character in p if that character is a letter. All other characters (numbers, symbols, spaces, punctuation marks, etc.) must be outputted unchanged. Moreover, if your code is about to apply the jth character of k to the ith character of p, but the latter proves to be a non-alphabetical character, you must wait to apply that jth character of k to the next alphabetical character in p; you must not yet advance to the next character in k.


    • Your program must preserve the case of each letter in p.





    I received full credit for my answer, but I still want to clean up the code if possible. I am new to programming, so I enjoy seeing what changes more experienced programmers would make.



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

    int check(string argv);
    int shift(char c);

    int main(int argc, string argv[])
    {
    //check for valid key and save
    int valid = 0;
    if (argc == 2)
    {
    valid = check(argv[1]);
    }
    else
    {
    printf("Usage: ./vigenere keywordn");
    return 1;
    }


    //begin encryption
    int key;
    int index = -1;
    int new_code;
    if (valid == 1)
    {
    //get plaintext to encrypt
    string plaintext = get_string("plaintext: ");
    printf("ciphertext: ");

    //iterate through each char of plaintext
    for (int j = 0, l = strlen(plaintext); j < l; j++)
    {
    if (isalpha(plaintext[j]))
    {
    //iterate through the keyword only when there is an alpha in the plaintext
    index++;
    key = shift(tolower(argv[1][index % strlen(argv[1])]));
    new_code = (int) plaintext[j] + key;
    if ((int) tolower(plaintext[j]) + key > 122)
    {
    new_code = new_code - 26;
    printf("%c", (char) new_code);
    }
    else
    {
    printf("%c", (char) new_code);
    }
    }
    else
    {
    printf("%c", (char) plaintext[j]);
    }
    }
    printf("n");
    }
    else
    {
    printf("Usage: ./vigenere keywordn");
    return 1;
    }
    }

    //create key
    int shift(char c)
    {
    int key = (int) c - 97;
    return key;
    }

    //decide if key is valid
    int check (string argv)
    {
    int val = 0;
    for (int i = 0, n = strlen(argv); i < n; i++)
    {
    if (isalpha(argv[i]))
    {
    val = 1;
    }
    else
    {
    val = 0;
    break;
    }
    }
    return val;
    }









    share|improve this question









    New contributor




    Snoop2001 is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
    Check out our Code of Conduct.







    $endgroup$















      3












      3








      3





      $begingroup$


      I wrote a program for a problem in Harvard's CS50 course, Vigenere (week 2).



      Here is a description of what the program needs to do:




      Design and implement a program that encrypts messages using Vigenère’s cipher.




      • Implement your program in a file called vigenere.c in a directory
        called vigenere.


      • Your program must accept a single command-line argument: a keyword, k, composed entirely of alphabetical characters.


      • If your program is executed without any command-line arguments, with more than one command-line argument, or with one command-line argument that contains any non-alphabetical character, your program should print an error (of your choice) and exit immediately, with main returning 1 (thereby signifying an error).


      • Otherwise, your program must proceed to prompt the user for a string of plaintext, p, (as by a prompt for plaintext:) which it must then encrypt according to Vigenère’s cipher with k, ultimately printing the result (prepended with ciphertext: and ending with a newline) and exiting, with main returning 0.


      • With respect to the characters in k, you must treat A and a as 0, B and b as 1, …​, and Z and z as 25.


      • Your program must only apply Vigenère’s cipher to a character in p if that character is a letter. All other characters (numbers, symbols, spaces, punctuation marks, etc.) must be outputted unchanged. Moreover, if your code is about to apply the jth character of k to the ith character of p, but the latter proves to be a non-alphabetical character, you must wait to apply that jth character of k to the next alphabetical character in p; you must not yet advance to the next character in k.


      • Your program must preserve the case of each letter in p.





      I received full credit for my answer, but I still want to clean up the code if possible. I am new to programming, so I enjoy seeing what changes more experienced programmers would make.



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

      int check(string argv);
      int shift(char c);

      int main(int argc, string argv[])
      {
      //check for valid key and save
      int valid = 0;
      if (argc == 2)
      {
      valid = check(argv[1]);
      }
      else
      {
      printf("Usage: ./vigenere keywordn");
      return 1;
      }


      //begin encryption
      int key;
      int index = -1;
      int new_code;
      if (valid == 1)
      {
      //get plaintext to encrypt
      string plaintext = get_string("plaintext: ");
      printf("ciphertext: ");

      //iterate through each char of plaintext
      for (int j = 0, l = strlen(plaintext); j < l; j++)
      {
      if (isalpha(plaintext[j]))
      {
      //iterate through the keyword only when there is an alpha in the plaintext
      index++;
      key = shift(tolower(argv[1][index % strlen(argv[1])]));
      new_code = (int) plaintext[j] + key;
      if ((int) tolower(plaintext[j]) + key > 122)
      {
      new_code = new_code - 26;
      printf("%c", (char) new_code);
      }
      else
      {
      printf("%c", (char) new_code);
      }
      }
      else
      {
      printf("%c", (char) plaintext[j]);
      }
      }
      printf("n");
      }
      else
      {
      printf("Usage: ./vigenere keywordn");
      return 1;
      }
      }

      //create key
      int shift(char c)
      {
      int key = (int) c - 97;
      return key;
      }

      //decide if key is valid
      int check (string argv)
      {
      int val = 0;
      for (int i = 0, n = strlen(argv); i < n; i++)
      {
      if (isalpha(argv[i]))
      {
      val = 1;
      }
      else
      {
      val = 0;
      break;
      }
      }
      return val;
      }









      share|improve this question









      New contributor




      Snoop2001 is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
      Check out our Code of Conduct.







      $endgroup$




      I wrote a program for a problem in Harvard's CS50 course, Vigenere (week 2).



      Here is a description of what the program needs to do:




      Design and implement a program that encrypts messages using Vigenère’s cipher.




      • Implement your program in a file called vigenere.c in a directory
        called vigenere.


      • Your program must accept a single command-line argument: a keyword, k, composed entirely of alphabetical characters.


      • If your program is executed without any command-line arguments, with more than one command-line argument, or with one command-line argument that contains any non-alphabetical character, your program should print an error (of your choice) and exit immediately, with main returning 1 (thereby signifying an error).


      • Otherwise, your program must proceed to prompt the user for a string of plaintext, p, (as by a prompt for plaintext:) which it must then encrypt according to Vigenère’s cipher with k, ultimately printing the result (prepended with ciphertext: and ending with a newline) and exiting, with main returning 0.


      • With respect to the characters in k, you must treat A and a as 0, B and b as 1, …​, and Z and z as 25.


      • Your program must only apply Vigenère’s cipher to a character in p if that character is a letter. All other characters (numbers, symbols, spaces, punctuation marks, etc.) must be outputted unchanged. Moreover, if your code is about to apply the jth character of k to the ith character of p, but the latter proves to be a non-alphabetical character, you must wait to apply that jth character of k to the next alphabetical character in p; you must not yet advance to the next character in k.


      • Your program must preserve the case of each letter in p.





      I received full credit for my answer, but I still want to clean up the code if possible. I am new to programming, so I enjoy seeing what changes more experienced programmers would make.



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

      int check(string argv);
      int shift(char c);

      int main(int argc, string argv[])
      {
      //check for valid key and save
      int valid = 0;
      if (argc == 2)
      {
      valid = check(argv[1]);
      }
      else
      {
      printf("Usage: ./vigenere keywordn");
      return 1;
      }


      //begin encryption
      int key;
      int index = -1;
      int new_code;
      if (valid == 1)
      {
      //get plaintext to encrypt
      string plaintext = get_string("plaintext: ");
      printf("ciphertext: ");

      //iterate through each char of plaintext
      for (int j = 0, l = strlen(plaintext); j < l; j++)
      {
      if (isalpha(plaintext[j]))
      {
      //iterate through the keyword only when there is an alpha in the plaintext
      index++;
      key = shift(tolower(argv[1][index % strlen(argv[1])]));
      new_code = (int) plaintext[j] + key;
      if ((int) tolower(plaintext[j]) + key > 122)
      {
      new_code = new_code - 26;
      printf("%c", (char) new_code);
      }
      else
      {
      printf("%c", (char) new_code);
      }
      }
      else
      {
      printf("%c", (char) plaintext[j]);
      }
      }
      printf("n");
      }
      else
      {
      printf("Usage: ./vigenere keywordn");
      return 1;
      }
      }

      //create key
      int shift(char c)
      {
      int key = (int) c - 97;
      return key;
      }

      //decide if key is valid
      int check (string argv)
      {
      int val = 0;
      for (int i = 0, n = strlen(argv); i < n; i++)
      {
      if (isalpha(argv[i]))
      {
      val = 1;
      }
      else
      {
      val = 0;
      break;
      }
      }
      return val;
      }






      c vigenere-cipher






      share|improve this question









      New contributor




      Snoop2001 is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
      Check out our Code of Conduct.











      share|improve this question









      New contributor




      Snoop2001 is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
      Check out our Code of Conduct.









      share|improve this question




      share|improve this question








      edited 5 hours ago









      200_success

      131k17157422




      131k17157422






      New contributor




      Snoop2001 is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
      Check out our Code of Conduct.









      asked 6 hours ago









      Snoop2001Snoop2001

      161




      161




      New contributor




      Snoop2001 is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
      Check out our Code of Conduct.





      New contributor





      Snoop2001 is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
      Check out our Code of Conduct.






      Snoop2001 is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
      Check out our Code of Conduct.






















          1 Answer
          1






          active

          oldest

          votes


















          0












          $begingroup$

          It's usually best to return as early as possible for invalid cases. This avoids unnecessary nesting and complexity.



          e.g. the main() function has a lot of redundant code:



          int main(int argc, string argv[])
          {
          //check for valid key and save
          int valid = 0;
          if (argc == 2)
          {
          valid = check(argv[1]);
          }
          else
          {
          printf("Usage: ./vigenere keywordn");
          return 1;
          }

          ...
          if (valid == 1)
          {
          ...
          }
          else
          {
          printf("Usage: ./vigenere keywordn");
          return 1;
          }
          }


          and could be shortened to:



          int main(int argc, string argv[])
          {
          if (argc != 2 || check(argv[1]) != 0)
          {
          printf("Usage: ./vigenere keywordn");
          return 1;
          }

          ...
          }


          The main loop of the program could be abstracted to a separate function (after checking for a valid key / printing usage on error).





          Similarly check() could be written as:



          int check (string argv)
          {
          for (int i = 0, n = strlen(argv); i < n; i++)
          {
          if (!isalpha(argv[i]))
          {
          return 1;
          }
          }

          return 0;
          }




          check() is not an informative name for a function. It should at least be check_key, or is_all_alpha or something. shift() is a similarly cryptic name.





          By using strlen, we are unnecessarily iterating the string twice (once to find the null at the end, then again to process it). We can simply run until we find a null character:



          for (int j = 0; plaintext[j]; ++j)




          Don't use magic numbers. What are 122, 26, or 97?





          Variables should be declared as close to their point of usage as possible, and initialized with real values. (key, index, new_code).





          It would be better to use another variable (e.g. keyword) as an alias, rather than using argv[1] throughout the code.



          There is no need to strlen() the keyword for every character.





          The main loop always ends up printing a char. The rest of the code just decides what the char will be. So perhaps it could be abstracted into a function. Also, since we are expected to treat both 'a' and 'A' the same, we can simplify things by only outputting letters in lowercase.



          I'd be inclined to do something like this (not tested):



          string key = argv[1];
          int key_len = strlen(key);
          int key_i = 0;
          for (int j = 0; plaintext[j]; ++j)
          {
          char p = plaintext[j];
          char c = !isalpha(p) ? p : encode_char(p, key[key_i++ % key_len]);
          printf("%c", c);
          }

          printf("n");
          ...

          char encode_char(char plaintext, char key)
          {
          assert(isalpha(plaintext)); // #include <assert.h>

          int k = shift(tolower(key));
          int p = shift(tolower(plaintext));

          return unshift((p + k) % 26);
          }





          share|improve this answer











          $endgroup$














            Your Answer





            StackExchange.ifUsing("editor", function () {
            return StackExchange.using("mathjaxEditing", function () {
            StackExchange.MarkdownEditor.creationCallbacks.add(function (editor, postfix) {
            StackExchange.mathjaxEditing.prepareWmdForMathJax(editor, postfix, [["\$", "\$"]]);
            });
            });
            }, "mathjax-editing");

            StackExchange.ifUsing("editor", function () {
            StackExchange.using("externalEditor", function () {
            StackExchange.using("snippets", function () {
            StackExchange.snippets.init();
            });
            });
            }, "code-snippets");

            StackExchange.ready(function() {
            var channelOptions = {
            tags: "".split(" "),
            id: "196"
            };
            initTagRenderer("".split(" "), "".split(" "), channelOptions);

            StackExchange.using("externalEditor", function() {
            // Have to fire editor after snippets, if snippets enabled
            if (StackExchange.settings.snippets.snippetsEnabled) {
            StackExchange.using("snippets", function() {
            createEditor();
            });
            }
            else {
            createEditor();
            }
            });

            function createEditor() {
            StackExchange.prepareEditor({
            heartbeatType: 'answer',
            autoActivateHeartbeat: false,
            convertImagesToLinks: false,
            noModals: true,
            showLowRepImageUploadWarning: true,
            reputationToPostImages: null,
            bindNavPrevention: true,
            postfix: "",
            imageUploader: {
            brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
            contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
            allowUrls: true
            },
            onDemand: true,
            discardSelector: ".discard-answer"
            ,immediatelyShowMarkdownHelp:true
            });


            }
            });






            Snoop2001 is a new contributor. Be nice, and check out our Code of Conduct.










            draft saved

            draft discarded


















            StackExchange.ready(
            function () {
            StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fcodereview.stackexchange.com%2fquestions%2f217155%2fcs50-vigenere-program%23new-answer', 'question_page');
            }
            );

            Post as a guest















            Required, but never shown

























            1 Answer
            1






            active

            oldest

            votes








            1 Answer
            1






            active

            oldest

            votes









            active

            oldest

            votes






            active

            oldest

            votes









            0












            $begingroup$

            It's usually best to return as early as possible for invalid cases. This avoids unnecessary nesting and complexity.



            e.g. the main() function has a lot of redundant code:



            int main(int argc, string argv[])
            {
            //check for valid key and save
            int valid = 0;
            if (argc == 2)
            {
            valid = check(argv[1]);
            }
            else
            {
            printf("Usage: ./vigenere keywordn");
            return 1;
            }

            ...
            if (valid == 1)
            {
            ...
            }
            else
            {
            printf("Usage: ./vigenere keywordn");
            return 1;
            }
            }


            and could be shortened to:



            int main(int argc, string argv[])
            {
            if (argc != 2 || check(argv[1]) != 0)
            {
            printf("Usage: ./vigenere keywordn");
            return 1;
            }

            ...
            }


            The main loop of the program could be abstracted to a separate function (after checking for a valid key / printing usage on error).





            Similarly check() could be written as:



            int check (string argv)
            {
            for (int i = 0, n = strlen(argv); i < n; i++)
            {
            if (!isalpha(argv[i]))
            {
            return 1;
            }
            }

            return 0;
            }




            check() is not an informative name for a function. It should at least be check_key, or is_all_alpha or something. shift() is a similarly cryptic name.





            By using strlen, we are unnecessarily iterating the string twice (once to find the null at the end, then again to process it). We can simply run until we find a null character:



            for (int j = 0; plaintext[j]; ++j)




            Don't use magic numbers. What are 122, 26, or 97?





            Variables should be declared as close to their point of usage as possible, and initialized with real values. (key, index, new_code).





            It would be better to use another variable (e.g. keyword) as an alias, rather than using argv[1] throughout the code.



            There is no need to strlen() the keyword for every character.





            The main loop always ends up printing a char. The rest of the code just decides what the char will be. So perhaps it could be abstracted into a function. Also, since we are expected to treat both 'a' and 'A' the same, we can simplify things by only outputting letters in lowercase.



            I'd be inclined to do something like this (not tested):



            string key = argv[1];
            int key_len = strlen(key);
            int key_i = 0;
            for (int j = 0; plaintext[j]; ++j)
            {
            char p = plaintext[j];
            char c = !isalpha(p) ? p : encode_char(p, key[key_i++ % key_len]);
            printf("%c", c);
            }

            printf("n");
            ...

            char encode_char(char plaintext, char key)
            {
            assert(isalpha(plaintext)); // #include <assert.h>

            int k = shift(tolower(key));
            int p = shift(tolower(plaintext));

            return unshift((p + k) % 26);
            }





            share|improve this answer











            $endgroup$


















              0












              $begingroup$

              It's usually best to return as early as possible for invalid cases. This avoids unnecessary nesting and complexity.



              e.g. the main() function has a lot of redundant code:



              int main(int argc, string argv[])
              {
              //check for valid key and save
              int valid = 0;
              if (argc == 2)
              {
              valid = check(argv[1]);
              }
              else
              {
              printf("Usage: ./vigenere keywordn");
              return 1;
              }

              ...
              if (valid == 1)
              {
              ...
              }
              else
              {
              printf("Usage: ./vigenere keywordn");
              return 1;
              }
              }


              and could be shortened to:



              int main(int argc, string argv[])
              {
              if (argc != 2 || check(argv[1]) != 0)
              {
              printf("Usage: ./vigenere keywordn");
              return 1;
              }

              ...
              }


              The main loop of the program could be abstracted to a separate function (after checking for a valid key / printing usage on error).





              Similarly check() could be written as:



              int check (string argv)
              {
              for (int i = 0, n = strlen(argv); i < n; i++)
              {
              if (!isalpha(argv[i]))
              {
              return 1;
              }
              }

              return 0;
              }




              check() is not an informative name for a function. It should at least be check_key, or is_all_alpha or something. shift() is a similarly cryptic name.





              By using strlen, we are unnecessarily iterating the string twice (once to find the null at the end, then again to process it). We can simply run until we find a null character:



              for (int j = 0; plaintext[j]; ++j)




              Don't use magic numbers. What are 122, 26, or 97?





              Variables should be declared as close to their point of usage as possible, and initialized with real values. (key, index, new_code).





              It would be better to use another variable (e.g. keyword) as an alias, rather than using argv[1] throughout the code.



              There is no need to strlen() the keyword for every character.





              The main loop always ends up printing a char. The rest of the code just decides what the char will be. So perhaps it could be abstracted into a function. Also, since we are expected to treat both 'a' and 'A' the same, we can simplify things by only outputting letters in lowercase.



              I'd be inclined to do something like this (not tested):



              string key = argv[1];
              int key_len = strlen(key);
              int key_i = 0;
              for (int j = 0; plaintext[j]; ++j)
              {
              char p = plaintext[j];
              char c = !isalpha(p) ? p : encode_char(p, key[key_i++ % key_len]);
              printf("%c", c);
              }

              printf("n");
              ...

              char encode_char(char plaintext, char key)
              {
              assert(isalpha(plaintext)); // #include <assert.h>

              int k = shift(tolower(key));
              int p = shift(tolower(plaintext));

              return unshift((p + k) % 26);
              }





              share|improve this answer











              $endgroup$
















                0












                0








                0





                $begingroup$

                It's usually best to return as early as possible for invalid cases. This avoids unnecessary nesting and complexity.



                e.g. the main() function has a lot of redundant code:



                int main(int argc, string argv[])
                {
                //check for valid key and save
                int valid = 0;
                if (argc == 2)
                {
                valid = check(argv[1]);
                }
                else
                {
                printf("Usage: ./vigenere keywordn");
                return 1;
                }

                ...
                if (valid == 1)
                {
                ...
                }
                else
                {
                printf("Usage: ./vigenere keywordn");
                return 1;
                }
                }


                and could be shortened to:



                int main(int argc, string argv[])
                {
                if (argc != 2 || check(argv[1]) != 0)
                {
                printf("Usage: ./vigenere keywordn");
                return 1;
                }

                ...
                }


                The main loop of the program could be abstracted to a separate function (after checking for a valid key / printing usage on error).





                Similarly check() could be written as:



                int check (string argv)
                {
                for (int i = 0, n = strlen(argv); i < n; i++)
                {
                if (!isalpha(argv[i]))
                {
                return 1;
                }
                }

                return 0;
                }




                check() is not an informative name for a function. It should at least be check_key, or is_all_alpha or something. shift() is a similarly cryptic name.





                By using strlen, we are unnecessarily iterating the string twice (once to find the null at the end, then again to process it). We can simply run until we find a null character:



                for (int j = 0; plaintext[j]; ++j)




                Don't use magic numbers. What are 122, 26, or 97?





                Variables should be declared as close to their point of usage as possible, and initialized with real values. (key, index, new_code).





                It would be better to use another variable (e.g. keyword) as an alias, rather than using argv[1] throughout the code.



                There is no need to strlen() the keyword for every character.





                The main loop always ends up printing a char. The rest of the code just decides what the char will be. So perhaps it could be abstracted into a function. Also, since we are expected to treat both 'a' and 'A' the same, we can simplify things by only outputting letters in lowercase.



                I'd be inclined to do something like this (not tested):



                string key = argv[1];
                int key_len = strlen(key);
                int key_i = 0;
                for (int j = 0; plaintext[j]; ++j)
                {
                char p = plaintext[j];
                char c = !isalpha(p) ? p : encode_char(p, key[key_i++ % key_len]);
                printf("%c", c);
                }

                printf("n");
                ...

                char encode_char(char plaintext, char key)
                {
                assert(isalpha(plaintext)); // #include <assert.h>

                int k = shift(tolower(key));
                int p = shift(tolower(plaintext));

                return unshift((p + k) % 26);
                }





                share|improve this answer











                $endgroup$



                It's usually best to return as early as possible for invalid cases. This avoids unnecessary nesting and complexity.



                e.g. the main() function has a lot of redundant code:



                int main(int argc, string argv[])
                {
                //check for valid key and save
                int valid = 0;
                if (argc == 2)
                {
                valid = check(argv[1]);
                }
                else
                {
                printf("Usage: ./vigenere keywordn");
                return 1;
                }

                ...
                if (valid == 1)
                {
                ...
                }
                else
                {
                printf("Usage: ./vigenere keywordn");
                return 1;
                }
                }


                and could be shortened to:



                int main(int argc, string argv[])
                {
                if (argc != 2 || check(argv[1]) != 0)
                {
                printf("Usage: ./vigenere keywordn");
                return 1;
                }

                ...
                }


                The main loop of the program could be abstracted to a separate function (after checking for a valid key / printing usage on error).





                Similarly check() could be written as:



                int check (string argv)
                {
                for (int i = 0, n = strlen(argv); i < n; i++)
                {
                if (!isalpha(argv[i]))
                {
                return 1;
                }
                }

                return 0;
                }




                check() is not an informative name for a function. It should at least be check_key, or is_all_alpha or something. shift() is a similarly cryptic name.





                By using strlen, we are unnecessarily iterating the string twice (once to find the null at the end, then again to process it). We can simply run until we find a null character:



                for (int j = 0; plaintext[j]; ++j)




                Don't use magic numbers. What are 122, 26, or 97?





                Variables should be declared as close to their point of usage as possible, and initialized with real values. (key, index, new_code).





                It would be better to use another variable (e.g. keyword) as an alias, rather than using argv[1] throughout the code.



                There is no need to strlen() the keyword for every character.





                The main loop always ends up printing a char. The rest of the code just decides what the char will be. So perhaps it could be abstracted into a function. Also, since we are expected to treat both 'a' and 'A' the same, we can simplify things by only outputting letters in lowercase.



                I'd be inclined to do something like this (not tested):



                string key = argv[1];
                int key_len = strlen(key);
                int key_i = 0;
                for (int j = 0; plaintext[j]; ++j)
                {
                char p = plaintext[j];
                char c = !isalpha(p) ? p : encode_char(p, key[key_i++ % key_len]);
                printf("%c", c);
                }

                printf("n");
                ...

                char encode_char(char plaintext, char key)
                {
                assert(isalpha(plaintext)); // #include <assert.h>

                int k = shift(tolower(key));
                int p = shift(tolower(plaintext));

                return unshift((p + k) % 26);
                }






                share|improve this answer














                share|improve this answer



                share|improve this answer








                edited 2 hours ago

























                answered 2 hours ago









                user673679user673679

                3,33911130




                3,33911130






















                    Snoop2001 is a new contributor. Be nice, and check out our Code of Conduct.










                    draft saved

                    draft discarded


















                    Snoop2001 is a new contributor. Be nice, and check out our Code of Conduct.













                    Snoop2001 is a new contributor. Be nice, and check out our Code of Conduct.












                    Snoop2001 is a new contributor. Be nice, and check out our Code of Conduct.
















                    Thanks for contributing an answer to Code Review Stack Exchange!


                    • Please be sure to answer the question. Provide details and share your research!

                    But avoid



                    • Asking for help, clarification, or responding to other answers.

                    • Making statements based on opinion; back them up with references or personal experience.


                    Use MathJax to format equations. MathJax reference.


                    To learn more, see our tips on writing great answers.




                    draft saved


                    draft discarded














                    StackExchange.ready(
                    function () {
                    StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fcodereview.stackexchange.com%2fquestions%2f217155%2fcs50-vigenere-program%23new-answer', 'question_page');
                    }
                    );

                    Post as a guest















                    Required, but never shown





















































                    Required, but never shown














                    Required, but never shown












                    Required, but never shown







                    Required, but never shown

































                    Required, but never shown














                    Required, but never shown












                    Required, but never shown







                    Required, but never shown







                    Popular posts from this blog

                    Webac Holding Inhaltsverzeichnis Geschichte | Organisationsstruktur | Tochterfirmen |...

                    What's the meaning of a knight fighting a snail in medieval book illustrations?What is the meaning of a glove...

                    Salamanca Inhaltsverzeichnis Lage und Klima | Bevölkerungsentwicklung | Geschichte | Kultur und...