Check whether a list of words make a Pangram - arrays

I need to create a 2D string array and input to hi, up to 10 words, than to check if those words are pangram or not.
The program needs to stop receiving words if the words are pangram.
for example:
the
five
boxing
wizards
jump
quickly
It's a pangram?
Yes
but instead of stopping it's just keeps asking for words until it gets to 10. Also says that non-pangram sentences are pangram.
#include<stdio.h>
#include <string.h>
#define ROWS 10
#define COL 50
#define NUM_OF_LETTERS 26
int main()
{
char words[ROWS][COL] = {0};
char used []['z' - 'a' + 1] = {0};
int i = 0;
int j=0;
int count = 0;
printf("Enter up to 10 words try to make a pangram\n");
while(i<ROW&& count < NUM_OF_LETTERS)
{
fgets(words[i], ROW, stdin);
words[i][strcspn(words[i], "\n")] = 0;
int len = strlen(words[i]);
for(j=0;j<COL;j++)
{
if(strcmp(words[j] ,used[j]) == 0)
{
count++;
}
}
i++;
}
printf("It's a pangram?\n");
if (count >= NUM_OF_LETTERS)
{
printf("Yes!\n");
}
else
{
printf("No\n");
}
return 0;
}
And I can't use pointers.

Pangram :
A pangram or holoalphabetic sentence is a sentence using every letter of a given alphabet at least once. Pangram - wiki
2. Count only unique appearance of letters in the input words. Words can have both upper & lower case letters.
#include <stdio.h>
#include <string.h>
#include <ctype.h>
#define MAX_INPUT_WORDS 10
#define MAX_WORD_SIZE 50
#define UNIQUE_LETTERS 26
int main()
{
char* uniq_chars = "abcdefghijklmnopqrstuvwxyz";
//create a look-up table for characters in an alphabet set
char alpha_lt[256] = {0};
for (int ai = 0; '\0' != uniq_chars[ai]; ++ai)
alpha_lt[ (unsigned) uniq_chars[ai]] = 1;
char words [MAX_INPUT_WORDS][MAX_WORD_SIZE];
printf ("\nEnter up to 10 words, try to make a Pangram:\n");
int uniq_count = 0; // tracks count of unique characters so far
int wcount = 0;
for (int wi = 0 ; wi < MAX_INPUT_WORDS; ++wi) {
while (1 != scanf ("%49s", words[wi]));
++wcount;
//count the unique characters from alphabet-set
for (int ci = 0; '\0' != words[wi][ci]; ++ci) {
//Pangram can have letter from different cases.
int ichar = tolower (words[wi][ci]); // to homogenise upper/lower cases
if (alpha_lt[ichar]) { // uniq character not yet counted
++uniq_count;
alpha_lt[ichar] = 0; // remove from LT; to skip
// counting during next occurance
}
}
if (UNIQUE_LETTERS == uniq_count)
break;
}
printf ("\nIs it a Pangram?\n");
printf ((UNIQUE_LETTERS == uniq_count) ? "Yes!\n" : "No\n");
for (int wi = 0; wi < wcount;)
printf ("%s ", words[wi++]);
printf ("\n");
return 0;
}
Sample Pangrams for standard English:
"Waltz, bad nymph, for quick jigs vex." (28 letters)
"Glib jocks quiz nymph to vex dwarf." (28 letters)
"Sphinx of black quartz, judge my vow." (29 letters)
"How vexingly quick daft zebras jump!" (30 letters)
"The five boxing wizards jump quickly." (31 letters)
"Jackdaws love my big sphinx of quartz." (31 letters)
"Pack my box with five dozen liquor jugs." (32 letters)
"The quick brown fox jumps over a lazy dog" (33 letters)
Invalid Pangrams for testing:
ABCD EFGH IJK LMN OPQR STUVWXY Z
abcdef g h i jklmnopqrstuvwxyz

Related

resolving memory loss between two arrays in C

Good evening. I'm working on a program for class and I am hitting a brick wall when it comes to dealing with arrays using C.
--EDIT-- Full code has been posted.
#define _CRT_SECURE_NO_WARNINGS
#define STRMAX 20
#define MAX 100
#include<stdio.h>
int main()
{
int count = 0;
char strlist[STRMAX][MAX];
int start = 0, end = STRMAX;
for (start; start < end; start++) {
char string[MAX];
printf("Enter a string: ");
fgets(string, MAX - 1, stdin);
printf("\nThe string is: %s", string);
int size = strlen(string);
int result = strcmp(string, "stop\n");
if (result == 0) {
break;
}
strcpy(strlist[start], string);
count = count + 1;
}
char rev[STRMAX][MAX];
int temp = 0;
printf("count is: %d\n",count);
while (count != 0) {
strcpy(rev[temp], strlist[count]);
temp = temp + 1;
count = count - 1;
}
printf(rev);
return 0;
}
The last line, printf(rev); is throwing the warning: "using uninitialized memory 'rev'. "
I do not understand C, its the beginning of this course. However I am NOT looking for a "do my homework for me" answer, more of a "here is a better way to go about this" answer.
the output for the code is:
Enter a string: 1
The string is: 1
Enter a string: 2
The string is: 2
Enter a string: 3
The string is: 3
Enter a string: stop
The string is: stop
count is: 3
╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠3
the "count is: 3" is entirely for debugging. I really don't have a clue why my solution doesn't work. If there is any more information that is needed or anything else you would like to see feel free to ask and i'll update the post! thanks.
--EDIT--
STRMAX and MAX are both definitions set for the 2D array required for keeping an array of strings (20 and 50 respectively)
First of all, the line
strcpy(rev[temp], strlist[count]);
is wrong. Valid indexes for strlist are 0 to count-1, assuming that you only want to read valid strings. However, you are using the indexes 1 to count instead. Therefore, you should move the line
count = count - 1;
before that line.
Also, the line
printf(rev);
does not make sense.
If you want to print all strings in the array, then you should print every string individually, in a loop.
Since you are storing the number of valid strings in the variable temp, you must print that many strings.
for ( int i = 0; i < temp; i++ )
{
printf( "%s\n", rev[i] );
}
Also, you should #include <string.h>, because you are using strcpy and strlen.
Additionally, you probably should remove the trailing newline character from the input obtained from fgets. Otherwise, you will be printing that newline character, which will give you unwanted extra lines, forcing you to compensate by printing less newline characters explicitly. The existance of the newline character is also forcing you to add a newline character to the target string "stop":
int result = strcmp(string, "stop\n");
You will be able to remove that newline character from the target string if you also remove it from the input string.
After making these changes, your code should look like this:
#define _CRT_SECURE_NO_WARNINGS
#define STRMAX 20
#define MAX 100
#include <stdio.h>
#include <string.h>
int main()
{
int count = 0;
char strlist[STRMAX][MAX];
int start = 0, end = STRMAX;
for (; start < end; start++) {
char string[MAX];
printf("Enter a string: ");
fgets(string, MAX - 1, stdin);
//remove trailing newline character
string[strcspn(string,"\n")] = '\0';
printf("The string is: %s\n", string);
int result = strcmp(string, "stop");
if (result == 0) {
break;
}
strcpy(strlist[start], string);
count = count + 1;
}
char rev[STRMAX][MAX];
int temp = 0;
printf("count is: %d\n",count);
while (count != 0) {
count = count - 1;
strcpy(rev[temp], strlist[count]);
temp = temp + 1;
}
for ( int i = 0; i < temp; i++ )
{
printf( "%s\n", rev[i] );
}
return 0;
}
This program has the following output:
Enter a string: 1
The string is: 1
Enter a string: 2
The string is: 2
Enter a string: 3
The string is: 3
Enter a string: stop
The string is: stop
count is: 3
3
2
1

Random Characters Appearing When Printing Arrays

I'm relatively new to coding array functions in C. After numerous tries, I've decided to surrender and ask for help.
I wish to the user to input the words and store them into the 2d array words. The problem is that it prints the words but also prints out random characters.
#include "mp1_lib.h"
void get_words(int n, char words[][16])
{
char c = ' ';
char check;
for(int x=0; x <= n; x++)
{
for(int y=0; y < 16; y++)
{
c = getchar();
check = c;
if (check == '\n')
{
break;
}
words[x][y] = c;
}
}
}
void print_words(int n, char words[][16])
{
for(int x=1; x <= n; x++)
{
for(int y=0; y < 16; y++)
{
if (words[x][y] == '\n')
{
break;
}
putchar(words[x][y]);
}
printf("\n");
}
}
In C, a string is an array of characters with the nul-terminating character '\0' as the character that marks the end of the contents of the string within the array. That is how all string functions like strlen or printf using the '%s' format specifier to print a string -- know where the string stops.
If you do not nul-terminate the array of characters -- then it is not a string, it is simply an array and you cannot pass an un-terminate array to any function expecting a string - or it won't know where the string ends (and in the case of printf will just print whatever unspecified character happens to be in memory until it comes upon a '\0' to stop the output (or SegFaults).
If you don't nul-terminate the words in your array, then you will have to have some way to store the number of characters in each word, so your print function will know where to stop printing. (if you have a two-letter word like "Hi" in a 16-char array, you can only print 2 characters from the array. Especially if it is an uninitialized array, then you will simply get gibberish printed for characters 3-16.
Your second problem is -- "How do you know how many words you have stored in your array?" -- you don't return a value from getwords, so unless you change the function type to int and return the number of words that you stored in your array, your only other option is to pass a pointer to an integer and update the value at that address so the value is available back in the calling function. Either way is fine, you generally only worry about making a value available through a pointer if you are already returning another value and need a second method to make another updated value visible back in the calling function (main() here).
Putting those pieces together, and passing a pointer to the number of words to getwords to make the number of words entered available back in main() (so you know how many words print_words has to print), you could do something similar to the following:
#include <stdio.h>
#include <ctype.h>
#define MAXC 16 /* if you need constants, define them */
#define MAXW 32
void getwords (char (*words)[MAXC], int *n)
{
int col = 0; /* column count */
while (*n < MAXW) { /* while words < MAXW */
int c = getchar(); /* read char */
/* column reaches MAXC-1 or if whitespace or EOF */
if (col == MAXC - 1 || isspace(c) || c == EOF) {
if (col) { /* if col > 0 */
words[(*n)++][col] = 0; /* nul-terminate, increment n */
col = 0; /* set col to zero */
}
if (c == EOF) /* if char EOF - all done */
return;
}
else /* otherwise - just add char to word */
words[*n][col++] = c;
}
}
void prnwords (char (*words)[MAXC], int n)
{
for (int i = 0; i < n; i++) /* loop over each of n-words & print */
printf ("words[%2d]: %s\n", i, words[i]);
}
int main (void) {
char words[MAXW][MAXC] = {""}; /* intiliaze words all zero */
int nwords = 0; /* number of words zero */
getwords (words, &nwords);
prnwords (words, nwords);
return 0;
}
(note: when reading characters into the words array, you must check the number of character read again the maximum characters per-word (MAXC) and the number of words against the maximum number of words/rows in your array (MAXW) to prevent writing outside of your array bounds -- which will invoke Undefined Behavior in your program)
(note: the ctype.h header was included to simplify checking whether the character read was whitespace (e.g. a space, tab, or newline). If you can't use it, then simply use an if (c == ' ' || c == '\t' || c == '\n') instead.)
Example Use/Output
$ echo "my dog has fleas and my cat has none" | ./bin/getwords
words[ 0]: my
words[ 1]: dog
words[ 2]: has
words[ 3]: fleas
words[ 4]: and
words[ 5]: my
words[ 6]: cat
words[ 7]: has
words[ 8]: none
Not too familiar with c. But it appears like you are not addding the new line character to the words array in get_words.
check = c;
if (check == '\n')
{
break;
}
words[x][y] = c;
So when printing in print_words this will never be true.
if (words[x][y] == '\n')
{
break;
}
That means that whatever happens to be in the memory location is what will get printed.
Your words have neither the newline character (which makes your code print garbage) nor the terminating NULLs (which makes them illegal as C strings). At least add words[x][y]="\n" before breaking the inner loop. Or, rather, move the if check after the assignment words[x][y]=c;. And yes, the loop should go from 0 to n-1.
As a side note, you do not need the variable check: just use c.
I tried to assign space as a placeholder for the 15 characters and it worked. Thanks, everyone! :)
#include "mp1_lib.h"
void get_words(int n, char words[][16])
{
char c = ' ';
char check;
for(int x=0; x < n; x++)
{
for(int y=0; y < 16; y++)
{
words[x][y] = ' ';
}
}
for(int x=0; x < n; x++)
{
for(int y=0; y < 16; y++)
{
c = getchar();
check = c;
if (check == '\n')
{
break;
}
words[x][y] = c;
}
}
}
void print_words(int n, char words[][16])
{
for(int x=0; x < n; x++)
{
for(int y=0; y < 16; y++)
{
putchar(words[x][y]);
}
printf("\n");
}
}

Why this program doesn't give right result when used with large strings?

This program takes an input of number of strings followed by the actual strings. The output should be the number of common characters to all strings.
The constraints are:
No of strings <= 100
Length of string <= 100
For example..
Input:
3
abc
bcd
cde
Output:
1
As only c is common to all strings.
It gives right output when used with small inputs.
But when used with large strings like this :https://hr-testcases.s3.amazonaws.com/2223/input19.txt?AWSAccessKeyId=AKIAINGOTNJCTGAUP7NA&Expires=1408959130&Signature=E%2BMnR6MA0gQNkuWHMvc70eCL5Dw%3D&response-content-type=text%2Fplain
It gives wrong output of 58 instead of 19.
This is my code :
#include<stdio.h>
#include<string.h>
void main(){
int n,i,j,count=0;
char s[100][100];
scanf("%d",&n);
for(i=0;i<n;i++){
scanf("%s",s[i]);
}
int t;
int l = strlen(s[0]);
for(i=0;i<l;i++){
t=0;
for(j=1;j<n;j++){
if(strchr(s[j],s[0][i])!='\0'){
t++;
}
}
if(t==n-1)
count++;
}
printf("%d",count);
}
As you iterate over the first string's characters, you might potentially find the same character more than one time.
This means that common chars found more than one time in the first string will be counted more than one time.
This is what causing your program to calculate 58 instead of 19.
Check below some quick update to your program - it treats the duplicates in the first string.
This program calculates 19 on your 100 strings' test case.
#include<stdio.h>
#include<string.h>
void main(){
int n,i,j/*,count=0*/;
int count[26] = {0}; /* counter per char */
char s[100][101];
scanf("%d",&n);
for(i=0;i<n;i++){
scanf("%s",s[i]);
}
int t;
int l = strlen(s[0]);
for(i=0;i<l;i++){
t=0;
/* convert char to integer - assuming lowercase char only */
int char_index = s[0][i] - 'a';
for(j=1;j<n;j++){
if(strchr(s[j],s[0][i])!='\0' && count[char_index] == 0){
t++;
}
}
if(t==n-1)
count[char_index] = 1;
/* count++; */
}
/* count how many chars are 1*/
int count_n = 0;
int index;
for (index = 0; index < 26; index ++)
{
if (count[index] == 1)
count_n ++;
}
printf("\n\n%d",count_n);
}

How to count the number of words that contain at least 3 vowels

I was wondering if I could ask for some help. I am writing a program in C that writes out the number of characters, words, and vowels are in the string(with a few added print statements). I am trying to figure out how to write a code that loops through the string and counts the number of words that contain at least 3 vowels. I feel as if this is a very easy code to write, but it's always the easiest things that seem to elude me. Any help?
Also: Being new to C, how can I get the same results while using the function int vowel_count(char my_sen[]) instead of using the code within my main?
If that's a tad confusing I mean since my main already contains code to count the number of vowels within my input, how can I somewhat transfer said code into this function and still call upon it in main?
#include <stdio.h>
#include <string.h>
#include <ctype.h>
#define SENTENCE 256
int main(void){
char my_sen[SENTENCE], *s; //String that containts at most 256 as well as a pointer
int words = 1, count = 0,vowel_word = 0; //Integer variables being defined
int i,vowel = 0, length; //More definitions
printf("Enter a sentence: ");//Input sentence
gets(my_sen);//Receives and processes input
length = strlen(my_sen); //Stores the length of the input within length
for(i=0;my_sen[i] != '\0'; i++){
if(my_sen[i]=='a' || my_sen[i]=='e' || my_sen[i]=='i' || my_sen[i]=='o' || my_sen[i]=='u' || //Loop that states if the input contains any of the following
my_sen[i]=='A' || my_sen[i]=='E' || my_sen[i]=='I' || my_sen[i]=='O' || my_sen[i]=='U') //characters(in this case, vowels), then it shall be
{ //stored to be later printed
vowel++;
}
if(my_sen[i]==' ' || my_sen[i]=='!' || my_sen[i]=='.' || my_sen[i]==',' || my_sen[i]==';' || //Similar to the vowel loop, but this time
my_sen[i]=='?') //if the following characters are scanned within the input
{ //then the length of the characters within the input is
length--; //subtracted
}
}
for(s = my_sen; *s != '\0'; s++){ //Loop that stores the number of words typed after
if(*s == ' '){ //each following space
count++;
}
}
printf("The sentence entered is %u characters long.\n", length); //Simply prints the number of characters within the input
printf("Number of words in the sentence: %d\n", count + 1); // Adding 1 to t[he count to keep track of the last word
printf("Average length of a word in the input: %d\n", length/count);//Prints the average length of words in the input
printf("Total Number of Vowels: %d\n", vowel);//Prints the number of vowels in the input
printf("Average number of vowels: %d\n", vowel/count);//Prints the average number of vowels within the input
printf("Number of words that contain at least 3 vowels: %d\n", vowel_word);//Prints number of words that contain at least 3 vowels
return 0;
}
It's not much of a problem.
#include <ctype.h>
#include <stdio.h>
#include <string.h>
int vowel_count(char my_sen[])
{
int wcount = 0; // number of words with 3+ vowel chars
int vcount = 0; // current number of vowel chars in the current word
int i = 0; // index into the string
int ch;
while ((ch = my_sen[i++]) != '\0')
{
if (isspace(ch) || !isalpha(ch))
{
// ch is not an alphabetical char, which can happen either
// before a word or after a word.
// If it's after a word, the running vowel count can be >= 3
// and we need to count this word in.
wcount += vcount >= 3; // add 1 to wcount if vcount >= 3
vcount = 0; // reset the running vowel counter
continue; // skip spaces and non-alphabetical chars
}
if (strchr("aeiouAEIOU", ch) != NULL) // if ch is one of these
{
++vcount; // count vowels
}
}
// If my_sen[] ends with an alphabetical char,
// which belongs to the last word, we haven't yet
// had a chance to process its vcount. We only
// do that in the above code when seeing a non-
// alphabetical char following a word, but the
// loop body doesn't execute for the final ch='\0'.
wcount += vcount >= 3; // add 1 to wcount if vcount >= 3
return wcount;
}
int main(void)
{
char sen[] = "CONSTITUTION: We the People of the United States...";
printf("# of words with 3+ vowels in \"%s\" is %d", sen, vowel_count(sen));
return 0;
}
Output (ideone):
# of words with 3+ vowels in "CONSTITUTION: We the People of the United States..." is 3
Btw, you can alter this function to count all things you need. It already finds where words begin and end and so, simple word counting is easy to implement. And word length, too. And so on.
1) Get the string,
2) use strtok () to get each words seperated by space.
3) Loop through each string by char by char to check if it is vowel.
Please check below code
#include<stdio.h>
#include <string.h>
int count_vowels(char []);
int check_vowel(char);
main()
{
char array[100];
printf("Enter a string\n");
gets(array);
char seps[] = " ";
char* token;
int input[5];
int i = 0;
int c = 0;
int count = 0;
token = strtok (array, seps);
while (token != NULL)
{
c = 0;
c = count_vowels(token);
if (c >= 3) {
count++;
}
token = strtok (NULL, seps);
}
printf("Number of words that contain atleast 3 vowels : %d\n", count);
return 0;
}
int count_vowels(char a[])
{
int count = 0, c = 0, flag;
char d;
do
{
d = a[c];
flag = check_vowel(d);
if ( flag == 1 )
count++;
c++;
}while( d != '\0' );
return count;
}
int check_vowel(char a)
{
if ( a >= 'A' && a <= 'Z' )
a = a + 'a' - 'A'; /* Converting to lower case */
if ( a == 'a' || a == 'e' || a == 'i' || a == 'o' || a == 'u')
return 1;
return 0;
}

How to reuse(loop) key in vigenere cipherkey cs50 pset2

I was making a program for Vigenere cipher. I made the program print the cipher text successfully. But, I can't loop the key. so if my key was 'abc' and my plain text was hello, it should print 'hfnlp' not 'hfn'.
#include <stdio.h>
#include <cs50.h>
#include <string.h>
#include <ctype.h>
int main(int argc, string argv[])
{
if(argc != 2)
{
printf("\aError\n");
return 1;
}
else
{
string a = argv[1]; // converts argv[1]
printf("plaintext: ");
string b = get_string(); // takes the plaintext
printf("ciphertext: ");
for(int c = 0, d = strlen(a); c < d; c++)
{
for(int e = 0, f = strlen(b); e < f; e++)
{
if(islower(a[c]))
{
printf("%c\n", b[e] + ( (a[c] - 97) % 26) ); // works for lowercase letters
return 0;
}
else if(isupper(a[i]))
{
printf("%c\n", b[e] + ( (a[c] - 65) % 26) ); // works for uppercase letter
}
else
{
printf("%c", b[e]); // works for non alphabetical inputs
}
if(true)
break;
}
}
printf("\n");
}
}
Your choice of single-letter variable names is odd; it makes it harder to work with your code. I'm not a fan of long names either, but intermediate length variable names (2-8 characters — except for some stylized single-letter names (c, i, j, k, p, s) — is typically appropriate).
You've got trouble because if your key is 6 characters and your string is 24 alphabetic characters, you'll attempt output 144 alphabetic characters because of the loop structure. You only need a single loop that iterates over the characters in the plain text. You have a separate variable that cycles over the length of the key, resetting back to the start when it runs out. In this code, the key length is in keylen (you used d) and the offset (index) into the key is in keyoff (you used c) — but the key is still in a because that's what you used. Left to my own devices, I'd probably use text (or maybe plain) in place of b, textlen in place of f, and I'd use i instead of e for the loop variable. If I wanted to use short indexes, I might use k instead of keyoff. I might also edit the string in situ and print the whole string at the end.
This code also ensures that the alpha characters in the key are in lower case. It doesn't ensure that the key is all alpha; it arguably should and it would be trivial to do so since the key is scanned anyway. As it stands, it is a case of GIGO — garbage in, garbage out.
The code converts the input letter (a-z or A-Z) into an 'offset into the alphabet' by subtracting a or A, converts the key letter into an offset into the alphabet, adds the two offsets modulo 26 (number of letters in the alphabet), and converts the offset back into a letter of the appropriate case.
#include <stdio.h>
#include <cs50.h>
#include <string.h>
#include <ctype.h>
int main(int argc, string argv[])
{
if (argc != 2 || strlen(argv[1]) == 0)
{
fprintf(stderr, "Usage: %s key < text\n", argv[0]);
return 1;
}
string a = argv[1];
int keylen = strlen(a);
for (int i = 0; i < keylen; i++)
a[i] = tolower((unsigned char)a[i]);
printf("key: %s\n", a);
printf("plaintext: ");
string b = get_string();
printf("ciphertext: ");
int keyoff = 0;
// Step through each character of the plain text. Encrypt each
// alpha character with the (lower-case) key letter at a[keyoff],
// incrementing keyoff. Don't increment key offset when processing
// non-alpha data.
for (int e = 0, f = strlen(b); e < f; e++)
{
if (islower(b[e]))
printf("%c", ((b[e] - 'a') + (a[keyoff++] - 'a')) % 26 + 'a');
else if (isupper(b[e]))
printf("%c", ((b[e] - 'A') + (a[keyoff++] - 'a')) % 26 + 'A');
else
printf("%c", b[e]);
if (keyoff >= keylen)
keyoff = 0;
}
printf("\n");
return 0;
}
When compiled to the program vc41 and run, it produces, for example:
$ vc41 abcdef
key: abcdef
plaintext: The quick brown Fox jumped over the lazy Dog.
ciphertext: Tig tyncl dusbn Gqa nzmqgg saes vki qaaa Gsl.
$
I generated an 8-letter random key (it was GZlfmTMk) and ran the code on a number of 'complete alphabet' strings:
$ vc41 GZlfmTMk
key: gzlfmtmk
plaintext: Pack my box with five dozen liquor jugs.
ciphertext: Vznp yr nyd vtyt yufk czeqg xswtzw vnsc.
$ vc41 GZlfmTMk
key: gzlfmtmk
plaintext: The five boxing wizards jump quickly.
ciphertext: Zgp kuoq luwtss pujgqox vnyz wtthwek.
$ vc41 GZlfmTMk
key: gzlfmtmk
plaintext: How vexingly quick daft zebras jump.
ciphertext: Nnh aqquxmkj vgbou jzqy lxnbgr uzyi.
$ vc41 GZlfmTMk
key: gzlfmtmk
plaintext: Bright vixens jump; dozy fowl quack.
ciphertext: Hqtltm hsddyx vnyz; jnkd rhiv wtlhw.
$ vc41 GZlfmTMk
key: gzlfmtmk
plaintext: The quick brown fox jumps over the lazy dog.
ciphertext: Zgp vgbou hqzbz yah ptxue hhox ssj xtli jnr.
$
(I'll note in passing that on a Mac running macOS Sierra 10.12.6 using GCC 7.1.0, this code links without including the (new) CS50 library — there is a system function get_string() that has a different interface to the CS50 version that satisfies the reference but crashes the program. However, it isn't documented by man get_string, so I'm not sure what the system function of that name actually does; I haven't chased it more actively, or found out how extensive the problem is. That caused me a headache that the old CS50 library didn't. Grumble…)
fix like this
#include <stdio.h>
#include <ctype.h>
#include <cs50.h>
int main(int argc, string argv[]){
if(argc != 2 || !*argv[1]){
printf("\aError:The number of command arguments is incorrect.\n");
printf("Usage: %s key_string\n", argv[0]);
return 1;
}
//Since it is `return 1;` in the if-statement,
//the else clause is unnecessary (unnecessarily deepening the nest)
string key = argv[1];//It does not convert.
size_t i, key_len;
unsigned char curr_char;
for(i = 0; (curr_char = key[i]) != '\0'; ++i){
if(!isalpha(curr_char)){
printf("\aError:Only the alphabet can be specified as the key.\n");
return 1;
}
key[i] -= islower(curr_char) ? 'a' : 'A';//Convert to Deviation
}
key_len = i;
i = 0;
printf("plaintext : ");
string plain = get_string();
printf("ciphertext: ");
for(size_t j = 0; (curr_char = plain[j]) != '\0'; ++j){//Scan of plain text should be the main loop.
if(isalpha(curr_char)){
char base_char = islower(curr_char) ? 'a' : 'A';//Avoid using magic numbers
putchar(base_char + (curr_char - base_char + key[i]) % 26);//Make the same process one
if(++i == key_len)
i = 0;//reset key index
} else {
putchar(curr_char);//non alphabetical inputs
}
}
printf("\n");
free(plain);
}

Resources