Try to use += on string to stack char(s) in C - c

I know it sounds real stupid, but It is cuz I just lightly learned Java and Python last year...
now I am try to do C properly with CS50.
on week 2, there is Caesar encipher text program task.
I tried to use += on string to stack char(s) one by one.
And of course it didn't work.
but is there any other way to do it similarly?
here is the code
#include <stdio.h>
#include <cs50.h>
#include <ctype.h>
#include <string.h>
#include <stdlib.h>
string encipher(string x, int y);
int main(int argc, string argv[])
{
string key = argv[1];
bool num_flag = false;
for (int i = 0; i < strlen(key); i++)
{
int k = isdigit(key[i]);
if (k == 0)
{
num_flag = true;
}
}
if (num_flag == true)
{
printf("Usage: ./caesar key\n");
}
else
{
int keys = atoi(argv[1]);
string c = get_string("plaintext: ");
string ciphertext = encipher(c, keys);
printf("ciphertext: %s\n", ciphertext);
}
}
string encipher(string x, int y)
{
string cip = "";
for (int i = 0; i < strlen(x); i++)
{
int low = islower(x[i]);
int upper = isupper(x[i]);
if (low != 0)
{
char lo = x[i] - 97;
char c = (lo + y) % 26;
char l = c + 97;
cip += l;
}
else if (upper != 0)
{
char up = x[i] - 65;
char c = (up + y) % 26;
char u = c + 65;
cip += u;
}
else
{
cip += x[i];
}
}
return cip;
}
.
I changed code to pass the test, but not perfect either...
#include <stdio.h>
#include <cs50.h>
#include <ctype.h>
#include <string.h>
#include <stdlib.h>
string encipher(string x, int y);
int main(int argc, string argv[])
{
if(argc != 2)
{
printf("Usage: ./caesar key\n");
}
else
{
string key = argv[1];
bool num_flag = false;
for (int i = 0; i < strlen(key); i++)
{
int k = isdigit(key[i]);
if (k == 0)
{
num_flag = true;
}
}
if (num_flag == true)
{
printf("Usage: ./caesar key\n");
}
else
{
int keys = atoi(argv[1]);
string c = get_string("plaintext: ");
string cipher = encipher(c, keys);
printf("ciphertext: %s\n", cipher);
}
}
}
string encipher(string x, int y)
{
for (int i = 0; i < strlen(x); i++)
{
int low = islower(x[i]);
int upper = isupper(x[i]);
if (low != 0)
{
char lo = x[i] - 97;
char c = (lo + y) % 26;
char l = c + 97;
x[i] = l;
}
else if (upper != 0)
{
char up = x[i] - 65;
char c = (up + y) % 26;
char u = c + 65;
x[i] = u;
}
}
return x;
}
Thanks for helping newbie!

with strncat() you can add chars to an existing string.
( strncat(char DESTINATION STRING, const char SOURCE STRING, AMOUNT OF CHARS YOU WANT TO ADD FROM THE SOURCE) )

In C you can't add string like other high-level languages. You have to use a special function in string.h. Like strcat(first_string, second_string);
An alternative is: char *strncat(char *dest, const char *src, size_t n) to add the first n characters (you can interprete size_t like int).

Related

C command line argument validation errors

Thank you everyone who helped me yesterday. I have one more issue with my code.
The purpose of the program is to take a command line argument and use it as a key to encrypt some plaintext entered by the user and to shift it by the number of letters given. The program should accept a single command-line argument, a non-negative integer. If any of the characters of the command-line argument is not a decimal digit, the program should print the message Usage: ./caesar key and return from main a value of 1.
When I test it, I receive the following error messages:
handles lack of key
failed to execute program due to segmentation fault
:( handles non-numeric key
timed out while waiting for program to exit
#include <cs50.h>
#include <stdio.h>
#include <ctype.h>
#include <string.h>
#include <math.h>
#include <stdlib.h>
//Declare the encrypting function
void encrypt(string plaintext, int k, string ciphertext);
int main(int argc, string argv[])
{
string plaintext;
int n = strlen(plaintext);
char ciphertext[n+1]; //the lenght of the plaintext+ 1 extra char which i
int k = atoi(argv[1]); //Convert string into an integer, i.e parsing
if (argc != 2)
{
printf("Usage: ./caesar key\n");
return 1;
}
else
{
for (int i = 0, m = strlen(argv[1]); i < m; i++)
{
if (isdigit(argv[1][i]))
{
plaintext = get_string("Plaintext:");
encrypt(plaintext, k, ciphertext); //calling the encryption function
printf("ciphertext: %s\n", ciphertext);
return 0;
}
else
{
printf("Usage: ./caesar key\n");
return 1;
}
}
}
}
void encrypt(string plaintext, int k, string ciphertext)
{
for (int i = 0, n = strlen(plaintext); i < n; i++)
{
if (isupper(plaintext[i]))
{
int pi = plaintext[i] - 65;
char ci = ((pi + k) % 26) + 65;
ciphertext[i] = ci;
}
else if (islower(plaintext[i]))
{
int pi1 = plaintext[i] - 97;
char ci1 = ((pi1 + k) % 26) + 97;
ciphertext[i] = ci1;
}
else
{
ciphertext[i] = plaintext[i];
}
}
}
I've updated your code as little as possible. Most of it was just re-arranging things.
int main(int argc, string argv [])
{
// Check for correct number of args
if (argc != 2)
{
puts("Please supply a key.");
puts("Usage: ./caesar key");
return 0;
}
// Check that argv[1] is all digits (i.e. positive integer)
for (int i = 0, n = strlen(argv[1]); i < n; i++) {
if (!isdigit(argv[1][i])) {
puts("Usage: ./caesar key");
return 1;
}
}
// Get user string
string plaintext = get_string("Plaintext:");
if (!plaintext) return 1;
// My compiler does not allow VLAs so I use malloc
char *ciphertext = malloc(strlen(plaintext) + 1);
int k = atoi(argv[1]); //Convert string into an integer, i.e parsing
encrypt(plaintext, k, ciphertext); //calling the encryption function
printf("ciphertext: %s\n", ciphertext);
// Free up allocated mem
free(ciphertext);
free(plaintext);
return 0;
}
void encrypt(string plaintext, int k, string ciphertext)
{
int n = strlen(plaintext);
for (int i = 0; i < n; i++)
{
if (isupper(plaintext[i]))
{
int pi = plaintext[i] - 65;
char ci = ((pi + k) % 26) + 65;
ciphertext[i] = ci;
}
else if (islower(plaintext[i]))
{
int pi1 = plaintext[i] - 97;
char ci1 = ((pi1 + k) % 26) + 97;
ciphertext[i] = ci1;
}
else
{
ciphertext[i] = plaintext[i];
}
}
// Don't forget to append nul-terminator
ciphertext[n] = '\0';
}

Strange char appears in the output

I'm trying to obfuscate word which is stored in string and my code sometimes works and sometimes doesn't. Here is my code:
// main function
int main(int argc, string argv[])
{
string k, plaintext;
int size, i = 0, key = 0;
k = argv[1];
size = strlen(k);
if (argc < 2 || !isNummeric(k, size) || k < 0)
return 1;
else
plaintext = GetString();
size = strlen(plaintext);
char ciphertext[size];
key = atoi(k);
while(i < size)
{
if (isalpha(plaintext[i]))
{
encipher(key, i, &ciphertext[i], plaintext);
}
else
{
ciphertext[i] = plaintext[i];
}
i++;
}
printf("%s\n",ciphertext);
}
A key is received from the user to shift each letter and I need to check whether the key is numeric value or not so I made isNummeric function to do that
bool isNummeric(string k, int size)
{
int c=0;
for(int i=0; i<size; i++)
{
if(!isdigit(k[i]))
c++;
}
if(c==0)
return true;
return false;
}
Now to encipher I made function to shift each letter:
void encipher(int k, int i, char *pt, string plaintext)
{
int p, c;
if(islower(plaintext[i]))
{
p=plaintext[i]-'a';
c=(p+k)%26;
*pt=c+97;
}
else
{
p=plaintext[i]-'A';
c=(p+k)%26;
*pt=c+65;
}
}
Assembling multiple comments from the question into fixed code yields the following code which seems to work:
#include <cs50.h>
#include <ctype.h>
#include <stdio.h>
#include <string.h>
static bool isNumeric(string k, int size)
{
for (int i = 0; i < size; i++)
{
if (!isdigit((unsigned char)k[i]))
return false;
}
return true;
}
/* There are too many arguments to this function - but it works */
static void encipher(int k, int i, char *pt, string plaintext)
{
int p, c;
if (islower((unsigned char)plaintext[i]))
{
p = plaintext[i] - 'a';
c = (p + k) % 26;
*pt = c + 'a';
}
else
{
p = plaintext[i] - 'A';
c = (p + k) % 26;
*pt = c + 'A';
}
}
int main(int argc, string argv[])
{
string k = argv[1];
if (argc < 2 || !isNumeric(k, strlen(k)))
return 1;
string plaintext = GetString();
int size = strlen(plaintext);
char ciphertext[size + 1];
int key = atoi(k);
for (int i = 0; i < size; i++)
{
if (isalpha(plaintext[i]))
{
encipher(key, i, &ciphertext[i], plaintext);
}
else
{
ciphertext[i] = plaintext[i];
}
}
ciphertext[size] = '\0';
printf("%s\n", ciphertext);
}
The program was called csr13, and gives the following outputs:
$ csr13 4
The Quick Brown Fox Jumped Over The Lazy Dog
Xli Uymgo Fvsar Jsb Nyqtih Sziv Xli Pedc Hsk
$ csr13 22
Xli Uymgo Fvsar Jsb Nyqtih Sziv Xli Pedc Hsk
The Quick Brown Fox Jumped Over The Lazy Dog
$
A better design for the encipher function would pass the single character plus the 'key' offset and would return the encrypted character:
#include <assert.h>
#include <cs50.h>
#include <ctype.h>
#include <stdio.h>
#include <string.h>
static bool isNumeric(string k, int size)
{
for (int i = 0; i < size; i++)
{
if (!isdigit((unsigned char)k[i]))
return false;
}
return true;
}
static int encipher(int k, int c)
{
assert(isalpha(c));
if (islower(c))
return (c - 'a' + k) % 26 + 'a';
else
return (c - 'A' + k) % 26 + 'A';
}
int main(int argc, string argv[])
{
string k = argv[1];
if (argc < 2 || !isNumeric(k, strlen(k)))
return 1;
string plaintext = GetString();
int size = strlen(plaintext);
char ciphertext[size + 1];
int key = atoi(k);
for (int i = 0; i < size; i++)
{
if (isalpha(plaintext[i]))
ciphertext[i] = encipher(key, plaintext[i]);
else
ciphertext[i] = plaintext[i];
}
ciphertext[size] = '\0';
printf("%s\n", ciphertext);
}

What's wrong with my CS50 Vigenere code?

I've been going round in circles with this now for a few hours. It manages the first word of the recommended test (Meet me at the park at eleven am) gets over the first spaces, gives a correct letter for m then prints several spaces before ending. Many thanks in advance.
#include <stdio.h>
#include <cs50.h>
#include <string.h>
#include <ctype.h>
int allstralpha();
int main(int argc, string argv[])
{
string keyw = argv[1];
if(argc == 2 && allstralpha(keyw))
{
string plaint = GetString();
int c = 0;
int kl = strlen(keyw);
int k = 0;
int p = 0;
int j = 0;
for(int i = 0, n = strlen(plaint); i < n; i++)
{
if(isalpha(plaint[i]))
{
if(isupper(keyw[j]))
{
k = keyw[(j % kl)] - 65;
if(isupper(plaint[i]))
{
p = plaint[i] -65;
c = ((k + p) % 26) + 65;
printf("%c", (char) c);
}
else if(islower(plaint[i]))
{
p = plaint[i] -97;
c = ((k + p) % 26) + 97;
printf("%c", (char) c);
}
}
else if(islower(keyw[j]))
{
k = keyw[(j % kl)] - 97;
if(isupper(plaint[i]))
{
p = plaint[i] - 65;
c = ((k + p) % 26) + 65;
printf("%c", (char) c);
}
else if(islower(plaint[i]))
{
p = plaint[i] - 97;
c = ((k + p) % 26) + 97;
printf("%c", (char) c);
}
}
j++;
}
else
{
printf("%c", (char) plaint[i]);
}
}
}
else
{
printf("Sorry that is not a vaild parameter\n");
return 1;
}
}
int allstralpha(string s)
{
for(int i = 0, n = strlen(s); i < n; i++)
{
if(!isalpha(s[i]))
{
return 0;
}
}
return 1;
}
int allstralpha();
int allstralpha(string s)
{
...
}
Your function definition and declaration don't match. You should declare int allstralpha(string s);
In first line of main:
int main(int argc, string argv[])
{
string keyw = argv[1];
...
}
First you should check if (argc > 1) before accessing argv[1]
For the actual code itself, you provide the plain text, but I can't see the keyword.
I use these values from wikipedia, vigenère cipher for testing:
Plaintext: ATTACKATDAWN
Key: LEMONLEMONLE
Ciphertext: LXFOPVEFRNHR
Minimum code to finish this:
#include <stdio.h>
#include <string.h>
#include <ctype.h>
int main(int argc, const char* argv[])
{
const char *str = "Meet me at the park at eleven am";
const char *key = "bacon";
int keylen = strlen(key);
int len = strlen(str);
for (int i = 0, j = 0; i < len; i++)
{
int c = str[i];
if (isalnum(c))
{
//int k = function of key and `j`...
//offset k...
if (islower(c))
{
c = (c - 'a' + k) % 26 + 'a';
}
else
{
c = (c - 'A' + k) % 26 + 'A';
}
j++;
}
putchar(c);
}
putchar('\n');
return 0;
}

Caesar Cipher not returning correct key

So my decrypter program seems to not be able to find the key and implement it by itself. I noticed that if I changed the key to equal -5 which is the correct key it would print out the decrypted text correctly. However I am unable to figure out how to make the program figure it out by itself without having me to put it in manually. Any help would be greatly appreciated! Thank you!
rotUtils.h
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#include "rotUtils.h"
int rotate(int c, int n){
if (n == 0) return c;
int nRot = abs(n) % (RANGECHAR + 1);
if(n > 0)
return rotatePlus(c + nRot);
else
return rotateMinus(c - nRot);
}
int rotatePlus(int sum){
int diff = sum - MAXCHAR;
if (sum > MAXCHAR) sum = MINCHAR + diff - 1;
return sum;
}
int rotateMinus(int sum){
int diff = MINCHAR - sum;
if (sum < MINCHAR) sum = MAXCHAR - diff + 1;
return sum;
}
decrypt.cpp
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <ctype.h>
#include "rotUtils.h"
bool solved( char decodearr[], char dictarr[][30], int size1, int size2){
char* compared;
bool result = false;
for(int j = 0; j < size2; j++){
compared = strstr( decodearr, dictarr[j]);
}
if( compared != '\0'){
result = true;
}
return result;
}
int decode( char codearr[], char dictarr[][30], int size1, int size2)
{
bool solution = false;
int key = -50; This is where I had to change it to -5 to solve
char decodearr[10000];
while(solution == false && key < 51)
{
for( int i = 0; i < size1; i++)
{
if(!isspace(codearr[i]))
{
decodearr[i] = rotate(codearr[i], key);
}
else
decodearr[i] = codearr[i];
}
solution = solved( decodearr, dictarr, size1, size2);
if( solution == false)
{
key++;
}
}
for( int j = 0; j < size1; j++)
{
codearr[j] = decodearr[j];
}
return key;
}
int main( int argc, char* argv[])
{
char* file = argv[1];
char* dictionary = argv[2];
char code[10000];
char dict[30000][30];
FILE* codeFile;
codeFile = fopen(file, "r");
int i = 0;
int j = 0;
int key;
FILE* dictFile;
dictFile = fopen(dictionary, "r");
while(!feof(codeFile))
{
code[i] = fgetc(codeFile);
i++;
}
code[ i ]= '\0';
fclose(codeFile);
while(!feof(dictFile))
{
fscanf(dictFile, "%s", dict[j]);
j++;
}
key = decode(code, dict, i, j);
fclose(dictFile);
for(int k = 0; k < i; k++)
{
printf("%c", code[k]);
}
printf( "\nThe key is: %d\n", key);
return 0;
}
Solved() will only return true if there is a match on the last dictionary word currently, you have to move that check inside. You could print to screen whenever you find a key that has a match on your dictionary and/or keep a list of possible keys then print after you are done with them all, right now you would exit as soon as you find any match even if it was just luck.

Wrapping Text Using Modulo

I am trying to cipher some plain text using a string key. Anyway if the plain text is greater than the key the key is suppose to continue using the key..I have used modulo to make the key start over again but for some reason it is not working...what is wrong with the code? By the way the key status upper or lower status is not a factor so this is why I change it to lower. Any help rendered would be appreciated. //Code cleaned up as suggested.
#include <stdio.h>
#include <cs50.h>
#include <string.h>
#include<stdlib.h>
#include<ctype.h>
int main (int argc, string argv[])
{
if (argc != 2)
{
printf("Ouch missing key\n");
return 1;
}
//get encryption keyword from argv array
string k= (argv[1]);
//test for non aplha character in plain text message
int x;
for (x = 0; x <strlen(argv[1]); x++)
{
if(isalpha(k[x]) == false)
{
printf("Ouch ensure value is alphabetical only\n");
return 1;
}
}
string m;
m = GetString(); //get plain text from prompt
for (int i= 0, j = 0; i< strlen(m) && j<= strlen(k); i++, j++)
{
if (
isalpha(m[i]) && isupper(m[i]))
{
m[i]= (m[i]-'a' + (tolower(k[j % strlen(k)])-'a')) % 26 + 'A';
}
else if (
isalpha(m[i]) && islower(m[i])
)
{
m[i] = (m[i] - 'a' + (tolower(k[j %strlen(k)])- 'a')) % 26 + 'a';
}
else
m[i] = m[i];
}
printf("%s\n", m);
}
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <ctype.h>
#include <cs50.h>
int main (int argc, string argv[]){
if (argc != 2){
printf("Ouch missing key\n");
return 1;
}
string k = argv[1];
int len_k = strlen(k);
for (int i = 0; i < len_k; ++i){
if(isalpha(k[i]))
k[i] = tolower(k[i]);
else {
printf("Ouch ensure value is alphabetical only\n");
return 1;
}
}
string m;
m = GetString();
for (int i= 0; i< m[i] ; ++i){
if(isupper(m[i]))
m[i]= (m[i]-'A' + k[i % len_k] - 'a') % 26 + 'A';
else if(islower(m[i]))
m[i]= (m[i]-'a' + k[i % len_k] - 'a') % 26 + 'a';
else
m[i] = m[i];//no effect, no need
}
printf("%s\n", m);
free(m);
return 0;
}
If your coding language is C fix main() by,
int main (int argc, string argv[])
to
int main (int argc, char * argv[])

Resources