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);
}
Related
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).
C does some spooky things when I put the nonAlphaCount declaration above the for loop. I can't explain why the outputs are different.
For version 1 (int declaration above main method) my input output was:
INPUT: ./Vigenere.exe bacon
Enter plain text: Meet me at the park at eleven am
OUTPUT: Negh zf av huf pcfx bt gzrwep oz
For version 2 ( int declaration above for loop )
INPUT: ./Vigenere.exe bacon
Enter plain text: Meet me at the park at eleven am
OUTPUT: NRQQ M[L \M^^ KQXXZQZ M
#include <stdio.h>
#include <string.h>
#include <ctype.h>
#include <unistd.h>
const int INPUT_LEN = 255;
const int ALPHABET_LEN = 26;
int nonAlphaCount = 0;
int main (int count, char *args[])
{
char plainText[INPUT_LEN];
char *cipherText;
char *keyWord;
if ( count < 2 || count > 2)
{
printf("There is no key");
return 1;
}
strcpy(keyWord, args[1]);
int keyWord_LEN = strlen(keyWord);
printf("Enter plain text: ");
fgets (plainText, INPUT_LEN, stdin);
int strLength = strlen(plainText);
cipherText = malloc(strLength);
printf("%s", plainText);
for (int i = 0; i < strLength; i++ ){
if(plainText[i] == '\0' || plainText[i] == '\n'|| plainText[i] == '\r')
break;
if(isalpha(plainText[i]))
{
// Default lower
int asciiUpperOrLower = 97;
int keyUpperOrLower = 97;
if(isupper(plainText[i]))
asciiUpperOrLower = 65;
if(isupper(keyWord[i % keyWord_LEN]))
keyUpperOrLower = 65;
int Key = keyWord[(i - nonAlphaCount) % keyWord_LEN] - keyUpperOrLower;
int alphabetBaseletter = ((plainText[i] - asciiUpperOrLower + Key) % ALPHABET_LEN);
cipherText[i] = alphabetBaseletter + asciiUpperOrLower;
}
else{
cipherText[i] = plainText[i];
nonAlphaCount++;
}
}
// Set string terminator.
cipherText[strLength - 1] = '\0' ;
printf("%s", cipherText);
return 0;
}
#include <stdio.h>
#include <string.h>
#include <ctype.h>
#include <unistd.h>
const int INPUT_LEN = 255;
const int ALPHABET_LEN = 26;
int main (int count, char *args[])
{
char plainText[INPUT_LEN];
char *cipherText;
char *keyWord;
if ( count < 2 || count > 2)
{
printf("There is no key");
return 1;
}
strcpy(keyWord, args[1]);
int keyWord_LEN = strlen(keyWord);
printf("Enter plain text: ");
fgets (plainText, INPUT_LEN, stdin);
int strLength = strlen(plainText);
cipherText = malloc(strLength);
printf("%s", plainText);
**int nonAlphaCount = 0;**
for (int i = 0; i < strLength; i++ ){
if(plainText[i] == '\0' || plainText[i] == '\n'|| plainText[i] == '\r')
break;
if(isalpha(plainText[i]))
{
// Default lower
int asciiUpperOrLower = 97;
int keyUpperOrLower = 97;
if(isupper(plainText[i]))
asciiUpperOrLower = 65;
if(isupper(keyWord[i % keyWord_LEN]))
keyUpperOrLower = 65;
int Key = keyWord[(i - nonAlphaCount) % keyWord_LEN] - keyUpperOrLower;
int alphabetBaseletter = ((plainText[i] - asciiUpperOrLower + Key) % ALPHABET_LEN);
cipherText[i] = alphabetBaseletter + asciiUpperOrLower;
}
else{
cipherText[i] = plainText[i];
nonAlphaCount++;
}
}
// Set string terminator.
cipherText[strLength - 1] = '\0' ;
printf("%s", cipherText);
return 0;
}
Both programs exhibit undefined behaviour in
char *keyWord;
...
strcpy(keyWord, args[1]);
which is revealed by the compiler warning: "uninitialized local variable 'keyWord' used". You have not allocated any memory.
If one of the programs happened to work, so be it.
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;
}
I want to divide *eString to substrings. Substrings should be like that:
y_{1} = y_{1}y_{m+1}y_{2m+1}...
y_{2} = y_{2}y_{m+2}y_{2m+2}...
y_{m} = y_{m}y_{2m}y_{3m}...
where y is the element of *eString, and y is the substring of these elements.
For instance, if an user expects the key length which is 5, there should be (string size / 5) substrings. y_{1} has to contain the fist element of each divided substring. So, how can I implement this?
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define ALPHA 26
char *ReadFile(char *);
int main(int argc, char *argv[])
{
double frequency[ALPHA] = {0};
int c = 0;
int keylen = 0;
int counter = 0;
double indexofCoincidence = 0,total = 0;
const char *eString = ReadFile("cipher.txt");
int len = 0;
if (eString) {
puts("The encrypted text is:");
puts(eString);
puts("");
len = strlen(eString);
printf("The length of text is %d\n",len);
}
puts("");
while(eString[c]!= '\0'){
if(eString[c]>= 'a' && eString[c]<='z')
frequency[eString[c]-'a']++;
c++;
}
puts("The letters frequencies are :\n");
for(c=0; c<ALPHA;c++){
if(frequency[c]!= 0)
printf("%c : %.3f\t",c+'a',(frequency[c]/len));
total += (frequency[c]*(frequency[c]-1));
}
indexofCoincidence = (total/((len)*(len-1)));
printf("\n\nIndex of Coincidence : %.3f\n",indexofCoincidence);
if(indexofCoincidence < 0.060){
printf("\nIt looks like randomly.\n");
}
printf("Enter the your expected key length : ");
scanf("%d",keylen);
printf("\n");
char *y;
while(counter != keylen)
{
for(int i = 0; i<(len/keylen);i++){
y[counter] = *eString();
}
counter++
}
return EXIT_SUCCESS;
}
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(void){
char *eString = "The quick brown fox jumps over the lazy dog";
int keylen = 5;
int len = strlen(eString);
int y_len = (len + keylen) / keylen + 1;
int i,j;
char **y = malloc(keylen * sizeof(*y));
for(i=0; i < keylen; ++i){
y[i] = malloc(y_len * sizeof(**y));
}
char *p = eString;
i = j = 0;
while(*p){
y[i % keylen][j] = *p++;
y[i % keylen][j+1] = 0;
if(++i % keylen == 0)
++j;
}
//check print & deallocate
for(i = 0; i < keylen; ++i){
printf("y_{%d} : %s\n", i+1, y[i]);
free(y[i]);
}
free(y);
return 0;
}
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.