Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 5 years ago.
Improve this question
I found this Caesar cipher encryption code on the web and I'm trying to understand how it works
#include<stdio.h>
int main()
{
char message[100], ch;
int i, key;
printf("Enter a message to encrypt: ");
gets(message);
printf("Enter key: ");
scanf("%d", &key);
for(i = 0; message[i] != '\0'; ++i){
ch = message[i];
if(ch >= 'a' && ch <= 'z'){
ch = ch + key;
if(ch > 'z'){
ch = ch - 'z' + 'a' - 1;
}
message[i] = ch;
}
else if(ch >= 'A' && ch <= 'Z'){
ch = ch + key;
if(ch > 'Z'){
ch = ch - 'Z' + 'A' - 1;
}
message[i] = ch;
}
}
printf("Encrypted message: %s", message);
return 0;
}
Meaning of if(ch >= 'a' && ch <= 'z')
Like does c include the alphabet as an array or something or how does it know that the letter is b or others ?
Adding an int to a char in ch = ch + key;
this math thing ch = ch - 'Z' + 'A' - 1;
And thanks very very much
The codes adds a certain value (key) to each inputed character and "rotates" the character in the range a-z if small caps and A-Z if big caps.
In C each single character has an implicit ascii/int value and the compare operator is used to decide if the inputted character is in the set of characters a-z (which are aligned after each other) or if it is in the set of A-Z which also follow behind each other.
The rest of the code deals with the wraparound if the inputted character plus the key "overshoots" f.e. z or Z and loops it around by substracting the value of 'z' and adding the value of 'a' -1 so that the resulting char is again one in the selected range of a-z or A-Z
Related
I'm trying to make this program such that the user could type any given string of characters, and the program would separate alphanumerical characters from the rest, print them into a second string, and finally print the final result into the screen.
I've already tried using scanf ("%[^\n]%*c", string);, but it doesn't seem to work since the size of the string is not specified beforehand, and is rather defined by STR_SIZE.
char string[STR_SIZE];
printf("please type in a string \n");
scanf("%s", string);
printf("string: \n %s \n", string);
int size = (strlen(string));
char alfanumerico[STR_SIZE];
int count = 0;
int count2 = 0;
while(count <= size)
{
if(string[count] >= '0' && string[count] <= '9')
{
alfanumerico[count2] = string[count];
count2++;
}
if(string[count] >= 'a' && string[count] <= 'z')
{
alfanumerico[count2] = string[count];
count2++;
}
if(string[count] >= 'A' && string[count] <= 'Z')
{
alfanumerico[count2] = string[count];
count2++;
}
if(string[count] ==' ')
{
alfanumerico[count2] = string[count];
count2++;
}
count++;
}
printf("alphanumerical characters typed: \n %s \n", alfanumerico);
Given the user typed a string such as: -=-=[[][][]}}Hello 123 ```//././.
I expect the output to be: Hello 123
scanf is not the way to go, especially if your input might contain white-spaces on which scanf would stop reading more inputs and wouldn't store spaces for instance.
You should use fgets which lets you limit the input data according to the buffer this data is stored in. So something like:
fgets(string, STR_SIZE, stdin)
should work.
About the size - you should have some limitation about the maximum size of the string and then STR_SIZE should be set to this number. It should be part of your program requirements or just a size that makes sense if you're making the requirements. It must be defined before you're reading input from the user because the buffer memory is allocated before reading to it.
A comment about style, unrelated to your question - always try to decrease code duplication to 0. The line alfanumerico[count2] = string[count]; count2++; appears 4 times in your code. A more elegant minimal if statement with exactly the same functionality would be:
if ((string[count] >= '0' && string[count] <= '9') ||
(string[count] >= 'a' && string[count] <= 'z') ||
(string[count] >= 'A' && string[count] <= 'Z') ||
(string[count] == ' '))
{
alfanumerico[count2] = string[count];
count2++;
}
and to be even more minimal:
char c = string[count];
if ((c >= '0' && c <= '9') ||
(c >= 'a' && c <= 'z') ||
(c >= 'A' && c <= 'Z') ||
(c == ' '))
{
alfanumerico[count2] = c;
count2++;
}
It's also more readable and more maintainable - if you want to change the variable count to i you do it in one place instead of 8.
Also, always close a scope in a new line.
Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 4 years ago.
Improve this question
As a part of an assignment I've got, I need to get from a user a digit only using the <stdio.h> library.
do {
scanf("%d",&num);
} while (num>9 || num<0);
But the program will get from the user also chars and other things.
Any advice?
One way of solving this is getting the ASCII value of the scanned "digit" and making sure it lies between ASCII values 0X30 and 0X39 (or 48 and 57).
Seeing your logic, you seem to be interested in numbers greater than 9 (multiple digit numbers) and numbers less than 0 (signed numbers/integers).
I suggest instead of using scanf better use something like getchar which will return one character at a time.
A simple way to scan multiple digit numbers using getchar can be:
int getNumber()
{
int sign = 1;
int i = 0;
int ch;
ch = getchar();
if((ch == '-') || (ch == '+')) //check sign
{
if(ch == '-') sign = -1;
}
else
{
if (ch > '9' || ch < '0')
return NULL; // Your requirement - it's a non number
i *= 10;
i += ch - '0';
}
while ((ch = getchar()) != '\n') //get remaining chars
{
if (ch > '9' || ch < '0')
return NULL; // Your requirement - it's a non number
i *= 10;
i += ch - '0';
}
i *= sign; //change sign
return i;
}
You can call this function in place of scanf.
You can use getchar() to read a single character from stdin and then compare it to the ASCII values for 0 and 9 (your upper and lower bounds for a single character). The digit as an integer is equal to the character code minus the character code for 0.
#include <stdio.h>
int main(void) {
char c;
while((c = getchar()) >= '0' && c <= '9')
printf("Digit is: %d\n", c - '0');
return 0;
}
Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 5 years ago.
Improve this question
So i recently started c language with no prior knowledge of coding or computer science. Wrote this piece of code to find value of a word using scrabble points as below:
1:AEILNORSTU 2:DG 3:BCMP 4:FHVWY 5:K 8:JX 10:QZ.
# include <stdio.h>
# include <ctype.h>
# include <conio.h>
int main (void)
{
int n=0;
char ch;
clrscr();
printf("Enter the SCRABBLE word\n");
ch = getchar();
while(ch!='\n')
{
toupper(ch);
if(ch =='A'||'E'||'I'||'L'||'N'||'O'||'R'||'S'||'T'||'U')
n=n+1;
else if (ch =='D'||'G')
n=n+2;
else if (ch =='B'||'C'||'M'||'P')
n=n+3;
else if (ch =='F'||'H'||'V'||'W'||'Y')
n=n+4;
else if (ch =='K')
n=n+5;
else if (ch =='J'||'X')
n=n+8;
else if (ch =='Q'||'Z')
n=n+10;
ch = getchar();
}
printf("The value is %d",n);
return 0;
}
So what happens when i run this code is that :
Enter the SCRABBLE word
eg: barrier
The value is 7
though it should be 9 as b carries 3 points as noted above the code,a carries 1,r carriers 1,again r 1 point,i carries 1 point and the last two alphabet are one point each so thats 3+1+1+1+1+1+1=9
An expression like ch =='D'||'G' is equal to (ch == 'D')||'G'.
In other words you first perform the sub-expression ch == 'D'. Then you do a logical or using 'G'. The result will always be true since 'G' is non-zero, and everything non-zero is true in C.
You want ch == 'D' || ch == 'G' instead, to check if ch is equal to 'D' or if ch is equal to 'G'.
This is very basic and every good beginners book would have told you so.
In the specific case of the code you show, the very first check will always be true because of this, and you will not check any other cases.
you forgot to get the return value of toupper. Also you don't check it
(according to man 3 toupper, the function will return the same char in case of failure)
Then your conditions aren't good:
if (ch == 'Q' || 'Z') is different from if (ch == 'Q' || ch == 'Z')
The || means if the right or the left condition is true and in the first case (ch == 'Q') is not always true, but 'Z' is always true.
This means your first condition :
if(ch =='A'||'E'||'I'||'L'||'N'||'O'||'R'||'S'||'T'||'U')
is always true
Here are littles corrections you can apply, this might work
char tmp;
ch = getchar();
while(ch!='\n')
{
//Stocking in a tmp char to check return value
tmp = ch;
//Here
ch = toupper(ch);
if (ch == tmp)
{
//Error
break;
}
{...}
else if (ch =='Q'|| ch =='Z')
n += 10;
ch = getchar();
}
Edit : Correction of return value of toupper();
Hey guys I'm starting to learn C, and I was asked to code a program specifically, a caesar cipher (so, the idea is to replace any letter in the message by a letter three positions down the alphabet.)
My implementation should read a line of text and then either performs encryption or decryption, depending on the first character read. If the first character is $, then I'm supposed to encrypt the rest of the line, and precede the output by the character ?. If the first character is ?, then I'm supposed to decrypt the rest of the line, and precede my output by the character $.
So for example: ?Wr eh, ru qrw wr eh
the output should be: $To be, or not to be
and vice versa.
So this is my code so far:
#include <stdio.h>
int main(void){
char code[100], ch;
int i;
scanf("%s", &code);
if(code[0] == '$'){
for(i = 0; code[i] != '\0'; ++i){
ch = code[i];
if(ch >= 'a' && ch <= 'z'){
ch = ch + 3;
if(ch > 'z'){
ch = ch - 'z' + 'a' - 1;
}
code[i] = ch;
}
else if(ch >= 'A' && ch <= 'Z'){
ch = ch + 3;
if(ch > 'Z'){
ch = ch - 'Z' + 'A' - 1;
}
code[i] = ch;
}
}
printf("?%s\n", code);
return 0;
}
}
But the problem is, it returns the first character and stops whenever there are space.
Like for example I enter: $To be it outputs to: ?$To
Can someone please help me figure out what I'm doing wrong?
Here's a sample using getchar() to get you started:
#include <stdio.h>
int main() {
int ch; // Either EOF or one of the chars in 0-255
while ((ch = getchar()) != EOF) {
if ('A' <= ch && ch <= 'Z') {
int offset = ch - 'A';
printf("%c", 'a' + offset);
} else {
printf("%c", ch);
}
}
}
Now, this code isn't perfect in a lot of ways, but it does demonstrate how to use getchar(). Every time getchar() is called, it fetches the next char from standard input and returns it as an int. That's because when the input is over, it returns the special value EOF, which is outside the range of char.
The while loop here is a common idiom. When execution reaches the loop, it first has to call getchar(), whose result is stored into ch. Then it checks whether ch is EOF. If not, then the loop processes the character that was read. Otherwise, it exits and the program ends.
The body of the loop prints every character it sees, while converting the uppercase letters to lowercase.
I'm learning c language and I hit a wall, if you would like to help me I appreciate (here is the ex: "Write a program that reads characters from the standard input to end-of-file. For each character, have the program report whether it is a letter. If it is a letter, also report its numerical location in the alphabet and -1 otherwise." btw is not homework).The problem is with the \n i don't know how to make it an exception. I'm new around here please let me know if I omitted something. Thank you for your help.
int main(void)
{
char ch;
int order;
printf("Enter letters and it will tell you the location in the alphabet.\n");
while ((ch = getchar()) != EOF)
{
printf("%c", ch);
if (ch >= 'A' && ch <= 'Z')
{
order = ch - 'A' + 1;
printf(" %d \n", order);
}
if (ch >= 'a' && ch <= 'z')
{
order = ch - 'a' + 1;
printf(" %d \n", order);
}
if (order != (ch >= 'A' && ch <= 'Z') || (ch >= 'a' && ch <= 'z'))
{
if (ch == '\n');
else if (order != (ch >= 'A' && ch <= 'Z') || (ch >= 'a' && ch <= 'z'))
printf(" -1 \n");
}
}
system("pause");
}
You are talking about an "exception" which can be interpreted in other ways in programming.
I understand that you want that '\n' be "excepted" in the set of nonalphabetical characters, that is, that it doesn't generate the error value -1.
Since you are using console to run the program, a sequence of character is going to be read till ENTER key is pressed, which generates the character \n. So, I'm not pretty sure that the while() condition you used, that compares against EOF, it's a good decision of yours.
I would put there directly the comparisson against '\n'.
while ((ch = getchar()) != '\n')
To inform if ch is a letter or not, we could use string literals. The following use of string assignment would deserve more explanation, but I will omit it. It's valid with string literals:
char *info;
if (order != -1)
info = "is a letter";
else
info = "is not a letter";
You are assuming an encoding where the letters are in contiguous increasing order (as in ASCII).
By assuming that, it's enough to work with uppercase or lowercase letters, since you are only interested in the position that the letter occupy in the alphabet. So, you can choose to work with uppercase, for example, in this way:
if (ch >= 'a' && ch <= 'z')
ch = (ch - 'a' + 'A');
The effect of that line of code is that ch is converted to uppercase, only if ch is a lowercase letter. Another kind of character is not affected.
As a consequence, from now on, you only have uppercase letters, or nonalphabetical characters.
Then it's easy to code the remaining part:
if (ch >= 'A' && ch <= 'Z')
order = ch - 'A' + 1; // It brings no. position of letter in alphabet
else
order = -1; // This is the erroneous case
A printf() at the end of the loop could bring all the information about the character:
printf(" %16s: %4d \n", info, order);
The resulting code is shorter in more clear:
#include <stdio.h>
int main(void) {
char ch;
int order;
char *info;
while ((ch = getchar()) != '\n') {
printf("%c",ch);
if (ch >= 'a' && ch <= 'z') /* Converting all to uppercase */
ch = (ch - 'a' + 'A');
if (ch >= 'A' && ch <= 'Z')
order = ch - 'A' + 1; /* Position of letter in alphabet */
else
order = -1; /* Not in alphabet */
if (order != -1)
info = "is a letter";
else
info = "is not a letter";
printf(" %16s: %4d \n", info, order);
}
}
If you need to end the input by comparing against EOF, then the type of ch has to be changed to int instead of char, so you can be sure that the EOF value (that is an int) is properly held in ch.
Finally, this means that ch needs initialization now, for example to a neutral value in the program, as '\n'.
Finally, just for fun, I add my super-short version:
#include <stdio.h>
int main(void) {
int ch, order;
while ((ch = getchar()) != '\n') {
order = (ch>='a' && ch<='z')? ch-'a'+1:((ch>='A' && ch<='Z')? ch-'A'+1: -1);
printf("%c %8s a letter: %4d \n", ch, (order != -1)? "is":"is not", order);
}
}
The C language does not have exceptions. Exceptions were first introduced into programming in C++. You can do it manually in C using setjmp() and longjmp(), but it really isn't worth it.
The two most popular of doing error handling in C are:
Invalid return value. If you can return -1 or some other invalid value from a function to indicate 'there was an error', do it. This of course doesn't work for all situations. If all possible return values are valid, such as in a function which multiplies two numbers, you cannot use this method. This is what you want to do here - simply return -1.
Set some global error flag, and remember to check it later. Avoid this when possible. This method ends up resulting in code that looks similar to exception code, but has some serious problems. With exceptions, you must explicitly ignore them if you don't want to handle the error (by swallowing the exception). Otherwise, your program will crash and you can figure out what is wrong. With a global error flag, however, you must remember to check for them; and if you don't, your program will do the wrong thing and you will have no idea why.
First of all, you need to define what you mean by "exception"; do you want your program to actually throw an exception when it sees a newline, or do you simply want to handle a newline as a special case? C does not provide structured exception handling (you can kind-of sort-of fake it with with setjmp/longjmp and signal/raise, but it's messy and a pain in the ass).
Secondly, you will want to read up on the following library functions:
isalpha
tolower
as they will make this a lot simpler; your code basically becomes:
if ( isalpha( ch ) )
{
// this is an alphabetic character
int lc = tolower( ch ); // convert to lower case (no-op if ch is already lower case)
order = lc - 'a' + 1;
}
else
{
// this is a non-alphabetic character
order = -1;
}
As for handling the newline, do you want to just not count it at all, or treat it like any other non-alphabetic character? If the former, just skip past it:
// non-alphabetic character
if ( ch == '\n' )
continue; // immediately goes back to beginning of loop
order = -1;
If the latter, then you don't really have to do anything special.
If you really want to raise an honest-to-God exception when you see a newline, you can do something like the following (I honestly do not recommend it, though):
#include <setjmp.h>
...
jmp_buf try;
if ( setjmp( try ) == 0 ) // "try" block
{
while ( (ch = getchar() ) != EOF )
{
...
if ( ch == '\n' )
longjmp( try, 1 ); // "throw"
}
}
else
{
// "catch" block
}
I'm having hard time trying to understand why you even try to handle '\n' specifically.
You might be trying to implement something like this:
int main(void)
{
char ch;
int order;
printf("Enter letters and it will tell you the location in the alphabet.\n");
while ((ch = getchar()) != EOF)
{
printf("%c", ch);
if (ch >= 'A' && ch <= 'Z') {
order = ch - 'A' + 1;
printf(" %d \n", order);
} else if (ch >= 'a' && ch <= 'z') {
order = ch - 'a' + 1;
printf(" %d \n", order);
} else if (ch == '\n') { } else {
printf(" -1 \n");
}
}
system("pause");
}
While this is a good solution, I would recommend rewriting it in a more optimal way:
int main(void)
{
char ch;
printf("Enter letters and it will tell you the location in the alphabet.\n");
while ((ch = getchar()) != EOF)
{
int order;
if (ch != '\n'){
if (ch >= 'A' && ch <= 'Z' || ch >= 'a' && ch <= 'z') {
order = ch & 11111B;
printf("Letter %d\n", order);
} else {
order = -1;
printf("Not letter: %d\n", order);
}
}
}
system("pause");
}
This way the program relies on specific way letters coded in ASCII