I've taken a code from here for a simple Caesar cipher, and I've modified it so that the user will define the cipher key. But the program crashes every time I tried to run it.
#include <stdio.h>
int main()
{
char array[100], cipher[100];
int c=0, x=0, y=0;
int z;
printf("This Program will encrypt according to your needs\n");
printf("Enter the cipher key\n");
scanf("%d",&z);
printf("Enter the sentence");
while((c=getchar()) != '\n')
{
array[x++]=(char)c;
cipher[y++]=(char)(c+z);
}
array[x]=0;
cipher[y]=0;
printf("%s\n",cipher);
return 0;
}
It doesn't crash. The while loop ends instantly since the '\n' is in input buffer after scanf and this gets read first
The scanf that reads in the key leaves a newline in the input buffer. Then when you call getchar for the first time, it returns \n, so the while loop is never entered.
You're not actually crashing, but just never getting an opportunity to enter in the string to encode.
You need to add an extra call to getchar after the scanf but before the loop to consume the newline:
scanf("%d",&z);
getchar();
#include<stdio.h>
#include<conio.h>
#include<string.h>
#include<ctype.h>
void main()
{
char p[20];
int key,i,enc;
clrscr();
printf("Enter Plain text=");
gets(p);
printf("\n Enter Key=");
scanf("%d",&key);
for(i=0;i<strlen(p);i++)
{
p[i]=tolower(p[i]);
enc=((p[i]-97)+key)%26;
printf("%c",enc+97);
}
}
#include <stdio.h>
#include <conio.h>
void main()
{
int i, c;
char str[100];
printf("Enter the Text Message : ");
gets(str);
for (i = 0; i < strlen(str); i++)
{
switch (str[i])
{
case 'x':
str[i] = 'a';
continue;
case 'y':
str[i] = 'b';
continue;
case 'z':
str[i] = 'c';
continue;
case 'X':
str[i] = 'A';
continue;
case 'Y':
str[i] = 'B';
continue;
case 'Z':
str[i] = 'C';
continue;
}
if (str[i] >= 'a' && str[i] < 'x')
str[i] = str[i] + 3;
else if (str[i] >= 'A' && str[i] < 'X')
str[i] = str[i] + 3;
}
printf("Message After Encryption : \n");
puts(str);
for (i = 0; i < strlen(str); i++)
{
switch (str[i])
{
case 'a':
str[i] = 'x';
continue;
case 'b':
str[i] = 'y';
continue;
case 'c':
str[i] = 'z';
continue;
case 'A':
str[i] = 'X';
continue;
case 'B':
str[i] = 'Y';
continue;
case 'C':
str[i] = 'Z';
continue;
}
if (str[i] >= 'd' && str[i] <= 'z')
str[i] = str[i] - 3;
else if (str[i] >= 'D' && str[i] < 'Z')
str[i] = str[i] - 3;
}
printf("Message After Decryption : \n");
puts(str);
getch();
}
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#define MAXSIZE 1024
int main(int argc, char* argv[])
{
char in[MAXSIZE];
char en[MAXSIZE] = {0};
//Input any Sting to encrypt in upper case or lower case
//or also mixed-up in any case.
read(STDIN_FILENO, in, MAXSIZE);
encrypt(in, en);
printf("%s\n%s\n", in, en);
bzero(in, strlen(in));
decrypt(en, in);
printf("%s\n%s\n", en, in);
return 0;
}
int encrypt(char* input, char* cipher)
{
int i;
for(i = 0; i < strlen(input); i++)
{
if(input[i] >= 97 && input[i] <= 122)
{
cipher[i] = input[i]+23 <= 122 ? input[i] + 23 : input[i] - 3;
}else if(input[i] >= 65 && input[i] <= 90)
{
cipher[i] = input[i]+23 <= 90 ? input[i] + 23 : input[i] - 3;
}else
cipher[i] = input[i];
}
return 0;
}
int decrypt(char* cipher, char* output)
{
int i;
for(i = 0; i < strlen(cipher); i++)
{
if(cipher[i] >= 97 && cipher[i] <= 122)
{
output[i] = cipher[i]-23 >= 97 ? cipher[i] - 23 : cipher[i] + 3;
}else if(cipher[i] >= 65 && cipher[i] <= 90)
{
output[i] = cipher[i]-23 >= 65 ? cipher[i] - 23 : cipher[i] + 3;
}else
output[i] = cipher[i];
}
return 0;
}
Here is a complete code in C for Caesar cipher
#include<stdio.h>
#include<conio.h>
#include<string.h>
#include<stdlib.h>
int main()
{
int i,key;
char plain[100],cipher[100];
printf("Enter key:");
scanf("%d",&key);
key=key%26; // adjusting key
fflush(stdin);
printf("Enter text:");
gets(plain);
for(i=0;i<strlen(plain);i++)
{
if(isalpha(plain[i]))
{
if(islower(plain[i]))
cipher[i]=(plain[i]+key-'a')%26+'a';
else
cipher[i]=(plain[i]+key-'A')%26+'A';
}
else
cipher[i]=plain[i];
}
cipher[i]='\0';
printf("After ciphering: %s",cipher);
getch();
return 0;
}
Related
It's supposed to do the following
Ask for input : Stack (e.g)
Ask for key : qwertyuioplkjhgfdsazxcvbnm (e.g)
Convert into cipher text : Azqel
Here's the new updated code:
//Encrypting user input by using 26 character long alphabetic key provided by user
#include <stdio.h>
#include <string.h>
int main(){
char key[26];
char text[1000];
//Prompt user for key
do{
printf("Provide a 26 character long key : ");
scanf("%s", key);
//If key is empty, exit code
if(strlen(key) == 0){
printf("Error: Empty input");
return 1;
}
//If key is incomplete, prompt user again for complete key
if(strlen(key)!= 26){
printf("Error: Incomplete key\n");
}
}while(strlen(key) != 26);
//If key has values other than alphabets, exit code
for(int i= 0, n= strlen(key); i<n; i++){
if((key[i]< 'a' || key[i]> 'z') && (key[i]< 'A' || key[i]> 'Z')){
printf("Error: Invalid key");
return 2;
}
}
//If key has repeated values, exit code
for(int i= 0; i< strlen(key); i++){
for(int j= i+ 1; key[j]!= '\0'; j++){
int x, y;
if(islower(key[i])){
x = key[i] - 'a';
}
else {
x = key[i] - 'A';
}
if(islower(key[j])){
y = key[j] - 'a';
}
else {
y = key[j] - 'A';
}
if(x == y){
printf("Error: Repeated characters in key");
return 3;
}
}
}
//Prompt user for input
printf("Plaintext : ");
scanf("%s", text);
//If input is empty, exit code
if(strlen(text) == 0){
printf("Error: Empty input");
return 4;
}
printf("Ciphertext: ");
for(int i= 0, n= strlen(text); i< n; i++){
//Encrypting small letters
if(text[i] >= 'a' && text[i] <= 'z'){
printf("%c", key[text[i]-'a']);
}
//Encrypting capital letters
else if(text[i] >= 'A' && text[i] <= 'Z'){
printf("%c", key[text[i]-'A']-('a'-'A'));
}
//Printing characters other than alphabets
else{
printf("%c", text[i]);
}
}
return 0;
}
The bug where code was treating lower case characters and upper case characters differently even if they were same has been fixed now.
If the key is for example : qwertyuioplkjhgfdsazxcvbmM (it has the letters 'm' and 'M' but they were being treated as different characters)
you can try this:
#include <stdio.h>
#include <string.h>
int main(){
char s[1000];
char t[26];
printf("Text: ");
scanf("%s", s);
printf("Key: ");
scanf("%s", t);
for(int i= 0, n= strlen(s); i< n; i++){
if(s[i] >= 'a' && s[i] <= 'z') printf("%c", t[s[i]-'a']);
else printf("%c", t[s[i]-'A'] + ('A'-'a'));
}
return 0;
}
and as said in the comments, try not to use numbers like 97 and 122, use 'a' and 'z' instead.
and for the bug mentioned in the updated code, instead of a simple check like key[j] == key[i] do this
int x, y;
if(islower(key[i])) x = key[i] - 'a';
else x = key[i] - 'A';
if(islower(key[j])) y = key[j] - 'a';
else y = key[j] - 'A';
if(x == y){
printf("Error: Repeated characters in key");
return 3;
}
or you can use a bool check[26], traverse the key, make the value of a character true if(islower(key[i])) check[key[i]-'a'] = true; else check[key[i]-'A'] = true; and lastly check whether the entire bool array is true.
I want to count letters,numbers,symbols using function password Seems like it doesn't count out numbers correctly because i get 0 for every printf in the end
#include <stdio.h>
void password(char * str[],int together,int numbers,int symbols,int i,int uppercase,int lowercase);
int main()
{
char str[100];
int together, numbers, symbols, i,uppercase,lowercase;
together = numbers = symbols = i = uppercase = lowercase = 0;
printf("password : ");
gets(&str);
printf(" %s", str);
password(&str,together,numbers,symbols,i,uppercase,lowercase);
printf("Number of letters = %d\n", together);
printf("number uppercase = %d\n", uppercase);
printf("Number lowecase = %d\n", lowercase);
printf("numbers = %d\n", numbers);
printf("Simboli = %d", symbols);
if (together >= 8 && numbers >= 2){
printf("\nPassword is correct");
}else{
printf("\nPassword isn't correct");
}
return 0;
}
void password(char * str[],int together,int numbers,int symbols,int i,int uppercase,int lowercase){
while(*str[i]!='\0')
{
if((*str[i]>='a' && *str[i]<='z') || (*str[i]>='A' && *str[i]<='Z'))
{
together++;
}
else if(*str[i]>='0' && *str[i]<='9')
{
numbers++;
}
else if(*str[i] >= 'A' && *str[i] <= 'Z') {
uppercase++;
}
else if(*str[i] >= 'a' && *str[i] <= 'z'){
lowercase++;
}
else
{
symbols++;
}
i++;
}
}
I get zeroes for every number,letter & symbol program runs without any error I tried changing some stuff but I am currently learning C so it is hard for me!
Few points : 1) There is no need to pass i as argument since you can get the length of your string with strlen from string.h (which returns a size_t type and not an int). 2) You passed your arguments as value, which means that they'll only change locally to your function. 3) Don't use the gets function that is not safe, you may want to use fgets or scanf.
#include <string.h>
#include <stdio.h>
void password(char *str, int *together, int *numbers, int *symbols, int *uppercase, int *lowercase){
for(size_t i=0; i<strlen(str); i++){
if(str[i] >= '0' && str[i] <= '9') (*numbers)++;
if(str[i] >= 'A' && str[i] <= 'Z') (*uppercase)++;
if(str[i] >= 'a' && str[i] <= 'z') (*lowercase)++;
if(str[i] >= '!' && str[i] <= '/') (*symbols)++;
}
*together = (*uppercase) + (*lowercase);
}
int main(void){
char str[100] = "Pa$$w0/2d";
int together = 0;
int numbers = 0;
int symbols = 0;
int uppercase = 0;
int lowercase = 0;
password(str, &together, &numbers, &symbols, &uppercase, &lowercase);
printf("Letters = %d\n", together);
printf("Uppercase = %d\n", uppercase);
printf("Lowercase = %d\n", lowercase);
printf("Numbers = %d\n", numbers);
printf("Symbols = %d\n", symbols)
return 0;
}
I have a problem with my homework. I need to count quantity of upper case and quantity of vowels in string. Unfortunately, it always returns number 0 which looks as it doesn't change in function. Everything works until this one.
Here is my code:
#include <stdio.h>
#include <conio.h>
#include <string.h>
char *StringChange(char *text, int *upper, int *chars);
int main(void) {
char text[40];
int upper, chars;
puts("Type a string");
gets(text);
StringChange(text, &upper, &chars);
puts("Change words to start with upper case and change white spece to *");
puts(text);
printf("Quantity of upper case in string: %d\n", upper);
printf("Quantity of vowels: %d", chars);
getch();
return 0;
}
char *StringChange(char *text, int *upper, int *chars) {
int i, length;
length = strlen(text);
for (i = 1; i <= length; i++) {
if (text[i - 1] == '*' && (text[i] >= 'a' && text[i] <= 'z')) {
text[i] = text[i] - 32;
}
if (text[i] == ' ') {
text[i] = '*';
}
if (text[i] >= 'A' && text[i] <= 'Z') {
*upper = *upper + 1;
/* *upper++; that also doesn't work */
}
if (text[i] == 'a' || text[i] == 'e' || text[i] == 'i' || text[i] == 'o' || text[i] == 'u' || text[i] == 'y') {
*chars = *chars + 1;
/* *chars++; that also doesn't work */
}
}
if (text[0] >= 'a' && text[0] <= 'z') {
text[0] = text[0] - 32;
}
return (text);
}
I tried your code and I do get non-zero results -- depending on the input, of course, so maybe you are only testing on strings that produce zero.
However, the results are not always correct. There are two problems I found in the code:
1) As pointed out in a comment, you should initialize upper and chars to 0.
2) You are starting the loop at index 1, not index 0. I think you did this so you could look at text[i-1] inside the loop, but it is causing you to exclude the first character from your totals. You should start the loop index and 0 and figure out a different way to handle it within the loop. (Hint - note that the first if within the loop and the one following the loop have similar conditions and the same body.)
There are multiple issues in your code:
you should never use gets().
the variables upper and chars are not initialized
the function StringChange make a special case of text[0] but does not update the counts for this initial byte.
you hard code the conversion of lowercase to uppercase for ASCII.
you should stop at the end of the string
all white space is not replaced, on whitespace followed by a lowercase letter.
uppercase vowels should be counted too.
Here is a modified version:
#include <stdio.h>
char *StringChange(char *text, int *upper, int *chars);
int main(void) {
char text[200];
int upper, vowels;
puts("Type a string");
if (fgets(text, sizeof text, stdin)) {
StringChange(text, &upper, &chars);
puts("Change words to start with upper case and change white space to *");
puts(text);
printf("Quantity of upper case in string: %d\n", upper);
printf("Quantity of vowels: %d\n", vowels);
}
getchar();
return 0;
}
char *StringChange(char *text, int *upper, int *vowels) {
int i, at_start = 1;
*upper = *vowels = 0;
for (i = 0; text[i] != '\0'; i++) {
char c = text[i];
if (at_start && c >= 'a' && c <= 'z') {
c += 'A' - 'a';
text[i] = c;
}
if (c == ' ') {
c = '*';
text[i] = c;
at_start = 1;
} else {
at_start = 0;
}
if (c >= 'A' && c <= 'Z') {
(*upper)++; // *upper++ would just increment the pointer, leading to undefined behavior
}
if (strchr("aeiouyAEIOUY", c) {
(*vowels)++;
}
}
return text;
}
int main() {
int s, b;
int hist[26] = { 0 };
int hist2[26] = { 0 };
char char1, char2;
printf("Hello Netta, enter the letters you would like us to repeat ending with $:\n");
scanf("%c", &char2);
while (char2 != '$') {
if (char2 >= 'A' && char2 <= 'Z')
char2 = char2 + 32;
int char3 = char2 - 'a';
hist2[char3]++;
scanf("%c", &char2);
if (char2 < 0)
break;
}
printf("How many times would you like to loop?\n");
if (!scanf("%d", &s))
return 0;
printf("Enter the string you would like to be checked ending with $:\n");
scanf("%c", &char1);
if (char1 >= 'A' && char1 <= 'Z')
char1 = char1 + 32;
while (char1 != '$' && char1 > 0) {
int char3 = char1 - 'a';
hist[char3]++;
scanf("%c", &char1);
}
for (int i = 0; i < 26; i++) {
if (hist[i] > s * hist2[i]) {
printf("Not enough letters\n");
b = 0;
break;
} else {
b = 1;
}
}
if (b)
printf("Congratulations! you have enough letters to create your song and win the Eurovision!\n");
return 0;
}
//so basically this a homewrok in my university they asked us to do the program input is char and a loop and it compare it with one more input how many times you can loop each letter (no need to check that the input is true but the loop number int
Your program has many problems:
scanf() returns the number of successful conversions. Compare the return value to 1 in your program instead of testing 0, which would never happen for "%c" anyway. Furthermore, the char2 would not be modified if the stream is at end of file.
You must check of char2 is a letter before indexing into the array, otherwise you may access beyond the array boundaries and have undefined behavior.
presentation is important: use proper indentation and spacing for the program to be readable.
include the necessary headers such as <stdio.h>
Here is an improved version:
#include <stdio.h>
int main() {
int hist[26] = { 0 };
int hist2[26] = { 0 };
int s;
char c;
printf("Hello Netta, enter the letters you would like us to repeat ending with $:\n");
while ((scanf("%c", &c) == 1 && c != '$') {
if (c >= 'A' && c <= 'Z')
hist2[c - 'A']++;
else if (c >= 'a' && c <= 'z')
hist2[c - 'a']++;
}
printf("How many times would you like to loop?\n");
if (scanf("%d", &s) != 1)
return 1;
printf("Enter the string you would like to be checked ending with $:\n");
while (scanf("%c", &c) == 1 && c != '$') {
if (c >= 'A' && c <= 'Z')
hist[c - 'A']++;
else if (c >= 'a' && c <= 'z')
hist[c - 'a']++;
}
for (int i = 0; i < 26; i++) {
if (hist[i] > s * hist2[i]) {
printf("Not enough letters\n");
break;
}
}
if (i == 26)
printf("Congratulations! you have enough letters to create your song and win the Eurovision!\n");
return 0;
}
I have a problem. I've wrote a program that changes input according to chosen argument. Program works how I want it to work, but it wasnt accepted because it need to work on whole lines (with fgets I belive) instead of characters one by one. Second thing is it should print values in main function.
I can't deal with none with that problems, could I get some help.
main.c
#include <stdlib.h>
#include <stdio.h>
#include "WordTools.h"
int main(int argc, char *argv[]) {
char string[1000];
size_t i = 0;
while (i < sizeof string) {
int ch = getchar();
if (ch == EOF) break;
string[i] = ch;
i++;
}
string[i] = 0;
switch (argc > 1 && argv[1][1]) {
case 'l':
case 'L':
makeLower(string);
break;
case 'u':
case 'U':
break;
case 'c':
case 'C':
makeChange(string);
break;
case 'n':
case 'N':
makeName(string);
break;
default:
makeUpper(string);
break;
}
return 0;
}
WordTools.c
#include <stdio.h>
#include <ctype.h>
#include "WordTools.h"
void makeLower(char *s) {
int i;
for(i = 0; s[i] != '\0'; i++){
s[i] = tolower(s[i]);
}
printf("%s", s);
}
void makeUpper(char *s) {
int i;
for(i = 0; s[i] != '\0'; i++){
s[i] = toupper(s[i]);
}
printf("%s", s);
}
void makeChange(char *s) {
int i;
for(i = 0; s[i] != '\0'; i++){
if ((s[i] >= 65) && (s[i] <= 90)) s[i] = tolower(s[i]);
else if ((s[i] >= 97) && (s[i] <= 122)) s[i] = toupper(s[i]);
}
printf("%s", s);
}
void makeName(char *s) {
int i;
s[0]=toupper(s[0]);
for(i = 1; s[i] != '\0'; i++){
s[i] = tolower(s[i]);
}
printf("%s", s);
}