Using c code to make a caesar cipher? - c

Hello good people of the stack overflow.
Explanation
I am trying to to the following.
My program needs to take a stream of letters as the input and then for the output rotate 13 paces forward.
For example
A becomes N
B becomes O
C becomes P
D becomes Q
and so on
For this program I need to use the ascii table. So for example lower case a=97 once my program is done it becomes n=110
I wrote a little formula for this
c=(c+13-97)% 26+97 where c is my letter. as you can see if c=97 then c will end up being 110.
So here is my program
As it is seen I used an if statment to determine if I have a capital or lower case letter.
/* 97 is lower case a in ascii and 122 is lower case z*/
# include <stdio.h>
int main() {
char c;
printf("please enter a character:");
while (c!=-1) {
c=getchar();
putchar (c);
if ( c>=97 && c<=122) {
c=(c+13-97)% 26+97 ;
printf("%c \n " ,c);
}
else
c=(c+13-65) % 26 +65 ;
printf("%c \n " ,c);
}
return 0;
}
My problem is with the output for example if I plug in a
instead of n I get
an
n
1

Your code is absolutely fine with some minor changes in it.
/* 97 is lower case a in ascii and 122 is lower case z*/
# include <stdio.h>
int main()
{
char c;
printf("please enter a character:");
while (c!=-1)
{
c=getchar();
//putchar (c); // Avoid Printing entered character
if ( c>=97 && c<=122)
{
c=((c+13-97)% 26)+97 ;
printf("%c \n " ,c);
}
else
{ // Braces missing
c=((c+13-65) % 26) +65 ;
printf("%c \n " ,c);
}
return 0;
}
}
Output :
please enter a character : a
n

One other issue that you will run into is the need to flush the \n remaining in the input buffer before reading the next character. Basically, what occurs is after a character is entered and the user presses Enter, c is read from the input buffer, but '\n' remains. So the next time the loop is entered \n is already present in the input buffer and is taken as c for that iteration.
To prevent this from occurring, the easiest way to flush the input buffer is to declare a throw-away int say int flush and following each read of a character, add the following:
do { flush=getchar(); } while (flush != '\n');
This will extract all remaining characters from the input buffer preparing it for the next read. (Note: fflush does not do this for input streams) An implementation with this incorporated is:
#include <stdio.h>
int main () {
int c = 0; /* Always initialize variables */
int flush = 0;
int new = 0;
printf ("\nPlease enter a character (ctrl+d to exit):\n\n");
while (printf (" char: ") && (c = getchar()) != -1) {
do { flush=getchar(); } while (flush != '\n'); /* flush input buffer */
if (c >= 'a' && c <= 'z')
{
new = (c + 13 - 97) % 26 + 97;
printf ("\t lower-case '%c' becomes: '%c'\n\n", c, new);
}
else if (c >= 'A' && c <= 'Z')
{
new = (c + 13 - 65) % 26 + 65;
printf ("\t upper-case '%c' becomes: '%c'\n\n", c, new);
}
else
{
printf ("\n invalid character, try again\n\n");
}
}
printf ("\n\nexiting.\n\n");
return 0;
}
output:
Please enter a character (ctrl+d to exit):
char: a
lower-case 'a' becomes: 'n'
char: b
lower-case 'b' becomes: 'o'
char: n
lower-case 'n' becomes: 'a'
char: o
lower-case 'o' becomes: 'b'
char: A
upper-case 'A' becomes: 'N'
char: B
upper-case 'B' becomes: 'O'
char: N
upper-case 'N' becomes: 'A'
char: O
upper-case 'O' becomes: 'B'
char:
exiting.
Good luck with your project. Drop a comment if you run into additional problems.
Multiple Character Version Using getline
Regarding your question about line input. Here is a version using getline to read multiple characters from stdin:
#include <stdio.h>
int main () {
int new = 0;
ssize_t nread = 0; /* number of chars read by getline */
char *line = NULL; /* string holding chars - getline allocates when NULL */
size_t n = 0; /* limit number of bytes to (ignored when 0) */
char *p = NULL; /* point to use to iterate over each char in line */
int index = 0; /* simple index for formatted output. */
printf ("\nPlease enter characters to translate (ctrl+d to exit):\n");
while (printf ("\n input: ") && (nread = getline (&line, &n, stdin) != -1)) {
index = 0; /* reset index */
p = line; /* assign pointer to line */
printf ("\n"); /* just because it looks nice */
while (*p != '\n') /* getline consumes the '\n' */
{
if (*p >= 'a' && *p <= 'z')
{
new = (*p + 13 - 97) % 26 + 97;
printf ("\t char[%2d] : %c => %c\n", index, *p, new);
}
else if (*p >= 'A' && *p <= 'Z')
{
new = (*p + 13 - 65) % 26 + 65;
printf ("\t char[%2d] : %c => %c\n", index, *p, new);
}
else
{
printf ("\n char[%2d] : %c => invalid character\n", index, *p);
}
p++;
index++;
}
}
printf ("\n\nexiting.\n\n");
return 0;
}
output:
Please enter characters to translate (ctrl+d to exit):
input: aAbBcCmMnNoO
char[ 0] : a => n
char[ 1] : A => N
char[ 2] : b => o
char[ 3] : B => O
char[ 4] : c => p
char[ 5] : C => P
char[ 6] : m => z
char[ 7] : M => Z
char[ 8] : n => a
char[ 9] : N => A
char[10] : o => b
char[11] : O => B
input:
exiting.

The while loop should be
while ((c=getchar()) != EOF)
Your code is checking the value of c before c is initialized. You should have gotten a warning about that.
You should not be using hard-coded ASCII values in your code. Lower case a is 'a'. Lower case z is 'z'. So, for example, you can write
if ( c >= 'a' && c <= 'z' )
Note that stdin buffers characters until you press the return key. When you do press the return key, getchar will give you the character that you typed followed by a newline '\n' character. Your code only handles lower case and upper case characters. You need to modify the code to handle non-alpha characters correctly, e.g. spaces, punctuation, newlines.

Related

Shifting characters in string

Hi I want to write a program which takes a string and a number as input and then shifts the elements of string by given number, and also the string is always capital letters and the output should only be capital letters too
example 1 : -1 , "AB CD"
output 1 : "ZA BC"
example 2 : +3 , "ABC"
output 2 : "DEF"
I have written this code but if there is a space in my string , the program doesnt work properly
for example : -1 "AA AA"
the output is : "ZZ" But i was expecting "ZZ ZZ"
int main()
{
char str[100] = {NULL},y;
int n,x,i=0;
scanf_s("%d", &n);
scanf_s("%s", str);
while (str[i] != NULL) {
x = str[i];
if (x + n >= 65 && x + n <= 90) {
y = x + n;
str[i] = y;
}
else if (x + n < 65) {
while (x + n < 65) {
x += 26;
}
y = x + n;
str[i] = y;
}
else if (x + n > 90) {
while (x + n > 90) {
x -= 26;
}
y = x + n;
str[i] = y;
}
i++;
}
printf("%s", str);
return 0;
}
After reading non-whitespace, the scanf specifier %s stops when it encounters whitespace.
Instead of "%s", use " %99[^\n]" to:
read and ignore leading whitespace, then
read up to 99 characters, or until a newline character is encountered.
Reading at most 99 characters is important, as you must leave room in your buffer for the null-terminating byte, and not limiting the amount of data read can easily lead to buffer overflows.
The return value of scanf_s should be checked to ensure the expected number of conversions took place, before any data is used.
if (1 != scanf_s("%d", &n))
/* error! */;
Note that scanf_s requires a secondary argument when using %s or %[, which is the size of the buffer
char buf[10];
if (1 != scanf_s("%9s", buf, (rsize_t) sizeof buf))
/* error! */;
which is supposed to be of type rsize_t. If you are using the MSVC versions of these functions, this type is unsigned.
Due to the pitfalls involved with using scanf properly, and the portability issues of scanf_s, consider instead using fgets to read lines of input (and strtol to parse an integer).
For clarity, consider using character constants like 'A' and 'Z', instead of integer constants like 65 and 90.
As is, your current code does not account for non-alphabetic characters, and will shift those. Consider the use of isalpha or isupper to filter the application of the shift.
Note NULL is usually considered a pointer value. Use '\0', or just 0, to represent the null-terminating byte.

Solving KNKING exercise 14, chapter 8. Reverse the words

I'm reading K.N.King C programming and I have an issue about it.
I'm solving project 5, chapter 12 which is modify project 14 from chapter 8 by using the pointer .
Project 8.14
Write a program that reverses the words in a sentence:
Enter a sentence: you can cage a swallow can't you?
Reversal of sentence: you can't swallow a cage can you?
Hint: Use a loop to read
the characters one by one and store them in a one-dimensional char
array. Have the loop stop at a period, question mark, or exclamation
point (the "terminating character"), which is saved in a separate char
variable. Then use a second loop to search backward through the array
for the beginning of the last word. Print the last word, then search
backward for the next-to-last word. Repeat until the beginning of the
array is reached. Finally, print the terminating character.
#include <stdio.h>
#include <ctype.h>
#define N 100
int main()
{
char arr[N] = {0};
char *p, *q, mark = 0;
int c;
p = arr;
while((c = getchar()) != '\n' && p < arr + N)
{
if(c == '?' || c == '.' || c == '!')
{
mark = c;
break;
}
else
*p++ = c;
}
*p = '\0';
while(p >= arr)
{
while(*--p != ' ' && p != arr);
q = p == arr ? arr : p + 1;
while(*q != '\0' && *q != ' ')
{
printf("%c", *q++);
}
if(p >= arr)
printf(" ");
}
printf("\b%c", mark);
printf("\n");
}
the problem is if I enter enter a sentence "My name is jiyong!", expected output is "jiyong is name My!" but the output always has '\xxx'. How can I get rid off? and what is these '\xxx' things?
ran under Xcode 12.4
The second loop looks too complicated to me. You are required to scan the string backwards and print every word found, right? But you're not required to retain the whole sentence...?
So we can replace every space character with zero, thus terminating each word.
while((c = getchar()) != '\n' && p < arr + N)
{
if(c == '?' || c == '.' || c == '!')
{
mark = c;
break;
}
else
*p++ = (c == ' ') ? '\0' : c;
}
*p = '\0';
Then we can seek words backwards and print them as strings instead of iterating over their characters:
while(--p > arr) // all words except the first one
{
if(!*p && p[1]) //p[1] or *(p + 1)
printf("%s ", p+1);
}
printf("%s", arr); // the first word goes last
if(mark)
printf("%c", mark);
printf("\n");
I assumed p gets incremented at least once in the first loop, that is the input line is never empty. But that seems a valid assumption (although not very safe) as the input is defined as 'a sentence', so it should not be empty...

fgets() and scanf() not working properly in unison. Buffer problem encountered

My assignment: -
Write a program that replaces the occurence of a given character (say
c) in a primary string (say PS) with another string (say s).
Input: The first line contains the primary string (PS) The next line
contains a character (c) The next line contains a string (s)
Output: Print the string PS with every occurence of c replaced by s.
Test case 1: -
Input: -
abcxy
b
mf
Expected output: -
amfcxy
Test case 2: -
Input: -
Al#bal#20owL
l
LL
Expected output: -
ALL#baLL#20owL
My code below: -
#include <stdio.h>
#include <stdlib.h>
int main() {
char PS[101];
char c;
char S[11];
fgets(PS, 101, stdin); //PS value input.
scanf("%c", &c);
if (c == '\n' || c == '\0') {
scanf("%c", &c); //Clearing the buffer. I want the real value of 'c' from STDIN not '\n'
}
fgets(S, 11, stdin); //S value input.
int i = 0;
while (PS[i] != '\0') { //Removing the '\n' from PS
if (PS[i] == '\n') {
PS[i] = '\0';
break;
}
i++;
}
i = i - 1; //i now holds the value of the size of the string PS (excluding '\0')
int j = 0;
while (S[j] != '\0') {
if (S[j] == '\n') {
S[j] = '\0';
break;
}
j++;
}
j = j - 1; //j now holds the value of the size of the string S (excluding '\0')
int k = 0; //work as an initializer
int move = 0; //work as an initializer.
while (PS[k] != '\0') { //This loops checks the whole array for the same character mentioned in char 'c'
if (PS[k] == c) {
for (move = i; move > k; move --) { //This loop advances the all the characters in PS by '(j - 1)' steps to make space for string S characters.
PS[move + (j - 1)] = PS[move];
}
for (move = 0; move < j; move++) { //This loop adds all the characters of string S into string PS at the relevant place.
PS[k + move] = S[move];
}
i = i + (j - 1); // 'i' now holds the new value of size of string PS after adding all the characters of string S.
}
k++;
}
puts(PS);
return 0;
}
Now the problem is that the code is not taking the input for string S.
After inputting first 2 inputs, it executes and gives a gibberish answer. I cannot figure out the bug, but what I do know is that there is some issue related to the buffer in C. Please help.
Edit: -
Thanks to #WeatherVane I have now edited the code with this: -
scanf("%c", &c);
if (c == '\n' || c == '\0') {
scanf("%c", &c); //Clearing the buffer. I want the real value of 'c' from STDIN not '\n'
}
char x;
x = getchar(); //New addition. It eats the '\n' after scanf().
fgets(S, 11, stdin); //S value input.
Now my code is working fine but the output is still not correct. It is sometimes failing to copy the last char from string S or giving me gibberish output.
The problem with the code was: -
i = i - 1; //i now holds the value of the size of the string PS (excluding '\0')
j = j - 1; //j now holds the value of the size of the string S (excluding '\0')
The value of i and j are the true values of the size of string PS and string S; not i = i - 1 and j = j - 1.
Lesson learnt from this assignment: -
scanf() does not treat '\n' in any way. It WILL be left in the
buffer.
If possible use fgets and then remove '\n' from your respective array/pointer.
Be extra careful of your C buffer when dealing with chars and strings.
The final correct code is: -
#include <stdio.h>
#include <stdlib.h>
int main()
{
char PS[101];
char c;
char S[11];
fgets(PS, 101, stdin); //PS value input.
scanf("%c", &c);
if(c == '\n' || c == '\0')
{
scanf("%c", &c); //Clearing the buffer. I want the real value of 'c' from STDIN not '\n'
}
char x;
x = getchar(); //New addition. It eats the '\n' after scanf().
fgets(S, 11, stdin); //S value input.
int i = 0;
while(PS[i] != '\0') //Removing the '\n' from PS
{
if(PS[i] == '\n')
{
PS[i] = '\0';
break;
}
i++;
}
i = i; //i now holds the value of the size of the string PS (excluding '\0')
int j = 0;
while(S[j] != '\0')
{
if(S[j] == '\n')
{
S[j] = '\0';
break;
}
j++;
}
j = j; //j now holds the value of the size of the string S (excluding '\0')
int k = 0; //work as an initializer
int move = 0; //work as an initializer.
while(PS[k] != '\0') //This loops checks the whole array for the same character mentioned in char 'c'
{
if(PS[k] == c)
{
for(move = i; move > k; move --) //This loop advances the all the characters in PS by '(j - 1)' steps to make space for string S characters.
{
PS[move + (j - 1)] = PS[move];
}
for(move = 0; move < j; move++) //This loop adds all the characters of string S into string PS at the relevant place.
{
PS[k + move] = S[move];
}
i = i + (j - 1); // 'i' now holds the new value of size of string PS after adding all the characters of string S.
}
k++;
}
puts(PS);
return 0;
}
Warning: -
The above code is very unoptimised and unreadable. Do not use it for
long term projects. It just "works".
Any suggestions for improvements of the above code are welcomed in
the comments.
Further necessary reading material recommended if you face any issue regarding C buffer in the future: -
Read 1
Read 2

Write a function that reads line by line from the console and prints the number of characters for each line loaded

Write a function that reads line by line from the console and prints the number of characters for each line loaded, The maximum length of the line being read should be 20 characters.
I have someting that just goes throught loop and print over and over to input string.
I'm having problem with - Print number of characters after each user input and set max character input to 20 for exampe. Someone to help me?
char str[str_size];
int alp, digit, splch, i;
alp = digit = splch = i = 0;
printf("\n\nCount total number of alphabets, digits and special characters :\n");
printf("--------------------------------------------------------------------\n");
do {
printf("Input the string : ");
fgets(str, sizeof str, stdin);
} while (str[i] != '\0');
if ((str[i] >= 'a' && str[i] <= 'z') || (str[i] >= 'A' && str[i] <= 'Z'))
{
alp++;
}
else if (str[i] >= '0' && str[i] <= '9')
{
digit++;
}
else
{
splch++;
}
i++;
printf("Number of Alphabets in the string is : %d\n", alp + digit + splch);
}
I do not understand what you do with do while loop in your code. So i just propose another loop for your case. I'm not sure but hope that code is what you want.
int main() {
char str[22];
int alp, digit, splch, i;
printf("\n\nCount total number of alphabets, digits and special characters :\n");
printf("--------------------------------------------------------------------\n");
printf("Input the string : ");
while (fgets(str, sizeof str, stdin)){
alp = digit = splch = 0;
for (i = 0; i < strlen(str); i++ ) {
if ((str[i] >= 'a' && str[i] <= 'z') || (str[i] >= 'A' && str[i] <= 'Z'))
{
alp++;
}
else if (str[i] >= '0' && str[i] <= '9')
{
digit++;
}
else if(str[i] != '\n')
{
splch++;
}
}
printf("alp = %d, digit = %d, splch = %d\n", alp, digit, splch);
printf("Input the string : ");
}
return 0;
}
OT, for determine the alpha or digit, you can use isdigit() and isalpha() functions. It's more simple than something you used in your code.
It seems the program can look the following way
#include <stdio.h>
#include <ctype.h>
#include <string.h>
int main(void)
{
enum { str_size = 22 };
char str[str_size];
puts( "\nCount total number of alphabets, digits and special characters");
puts( "--------------------------------------------------------------");
while ( 1 )
{
printf( "\nInput a string less than or equal to %d characters (Enter - exit): ",
str_size - 2 );
if ( fgets( str, str_size, stdin ) == NULL || str[0] == '\n' ) break;
unsigned int alpha = 0, digit = 0, special = 0;
// removing the appended new line character by fgets
str[ strcspn( str, "\n" ) ] = '\0';
for ( const char *p = str; *p != '\0'; ++p )
{
unsigned char c = *p;
if ( isalpha( c ) ) ++alpha;
else if ( isdigit( c ) ) ++digit;
else ++special;
}
printf( "\nThere are %u letters, %u digits and %u special characters in the string\n",
alpha, digit, special );
}
return 0;
}
The program output might look like
Count total number of alphabets, digits and special characters
--------------------------------------------------------------
Input a string less than or equal to 20 characters (Enter - exit): April, 22, 2020
There are 5 letters, 6 digits and 4 special characters in the string
Input a string less than or equal to 20 characters (Enter - exit):
If the user will just press the Enter key the loop will finish.
Pay attention to that the program considers white space and punctuation characters as special characters.

How to print ASCII value of 2 characters?

I'm trying to print ASCII value of "\t" i.e escape sequence.
But my program only prints the ASCII value of "\" i.e ASCII value will be 92.
Is there any way to print ASCII value of 2 characters ?
Help would be really appreciated.I have included my code below.
#include<stdio.h>
main()
{
char b=0;
printf("Enter any character to print it's ASCII value : ");
scanf("%c",&b);
printf("The ASCII value of '%c' is %d",b,b);
return 0;
}
Capture input of backslash and handle it as a separate input. A switch can be used to print the result for the escaped characters.
#include <stdio.h>
int main( void) {
char b=0;
printf("Enter any character to print it's ASCII value : ");
if ( 1 == scanf(" %c",&b)) {
if ( b == '\\') {//read a backslash
if ( 1 == scanf(" %c",&b)) {
switch ( b) {
case 't' :
printf("The ASCII value of '\\t' is %d\n", '\t');
break;
case '\\' :
printf("The ASCII value of '\\' is %d\n", '\\');
break;
default :
printf ( "not handled yet\n");
}
}
}
else {
printf("The ASCII value of '%c' is %d\n",b,b);
}
}
return 0;
}
Output
Enter any character to print it's ASCII value : \t
The ASCII value of '\t' is 9
Enter any character to print it's ASCII value : \\
The ASCII value of '\' is 92
To get the code for a backslash, two backslashes must be entered
This code might help you understand what is going on here:
#include <stdio.h>
const char* escaped(int ch) {
switch (ch) {
case '\t': return "tab";
case '\n': return "newline";
case '\r': return "carriage return";
// continue with other escaped characters
default: return "not escaped";
}
}
int main()
{
char b = 0;
printf("Enter any character to print it's ASCII value : ");
scanf("%c", &b);
printf("The ASCII value of '%c' is %d and is also known as: %s\n", b, b, escaped(b));
}
Just to be really clear, for a tab, at the keyboard you just press the tab key. You do not enter the string "\t". The string "\t" will be interpreted as 2 characters: '\' and 't'.
The \ escape code is something you would use in writing strings in your C code.
For example, if you type the string "trying" into some C source code, then you are entering the stream of characters: t r y i n g but if you type the string: "\trying" then the first character is indicating that this is an escaped character and is a convenient way to indicate that you really wanted a tab followed by the characters: r y i n g.
With the above code, if you enter "\t" scanf is only getting from stdin, one character at a time, so it just takes the first character, the backslash (start of an escape sequence), and will print out:
Enter any character to print it's ASCII value : \t
The ASCII value of '\' is 92 and is also known as: not escaped
the 't' character is still in the input stream and the program has not handled this character.
scanf does not interpret "\t" as a tab but as the character stream \ followed by t. That is causing your confusion.
You will experience some problems in running this code. For example, you want to try backspace, which is \b or decimal 8 value. scanf will probably ignore it and assume you are attempting to backspace a previous character. But for other escaped characters such as tab character and newline it will work.
Have a read of this: https://en.wikipedia.org/wiki/Escape_character
#define INV (EOF -1)
int z = 0, tmp = INV;
char buff[6] = "\\0";
while (1)
{
if (tmp == INV)
z = getchar();
else
{
z = tmp;
tmp = INV;
}
if (z == EOF || tmp == EOF) break;
if (z == '\\')
{
tmp = getchar();
switch (tmp)
{
case 't':
z = '\t';
tmp = INV;
break;
case 'b':
z = '\b';
tmp = INV;
break;
case 'r':
z = '\r';
tmp = INV;
break;
case 'n':
z = '\n';
tmp = INV;
break;
// add here anothere ones
default:
break;
}
}
printf("Char \\0%03o - '%c'\t\t has the ascii code of %03d decimal 0x%02X hexadecimal\n", z, z < 32 ? ' ' : z, z, z);
}

Resources