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;
}
$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.cin a directory
calledvigenere.
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
mainreturning1(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 withciphertext:and ending with a newline) and exiting, withmainreturning0.
With respect to the characters in k, you must treat
Aandaas 0,Bandbas 1, …, andZandzas 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
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$
add a comment |
$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.cin a directory
calledvigenere.
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
mainreturning1(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 withciphertext:and ending with a newline) and exiting, withmainreturning0.
With respect to the characters in k, you must treat
Aandaas 0,Bandbas 1, …, andZandzas 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
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$
add a comment |
$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.cin a directory
calledvigenere.
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
mainreturning1(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 withciphertext:and ending with a newline) and exiting, withmainreturning0.
With respect to the characters in k, you must treat
Aandaas 0,Bandbas 1, …, andZandzas 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
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.cin a directory
calledvigenere.
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
mainreturning1(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 withciphertext:and ending with a newline) and exiting, withmainreturning0.
With respect to the characters in k, you must treat
Aandaas 0,Bandbas 1, …, andZandzas 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
c vigenere-cipher
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.
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.
add a comment |
add a comment |
1 Answer
1
active
oldest
votes
$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);
}
$endgroup$
add a comment |
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.
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
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
$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);
}
$endgroup$
add a comment |
$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);
}
$endgroup$
add a comment |
$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);
}
$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);
}
edited 2 hours ago
answered 2 hours ago
user673679user673679
3,33911130
3,33911130
add a comment |
add a comment |
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.
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.
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
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
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
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