My program’s goal is to receive from the standard input a text, and a ‘number’, and to return to the screen the text after shifting of the letters ‘number’ times (for shift 3, ‘a’ becomes ‘d’, ‘e’ becomes ‘g’). It should only shift the lower case letter and should be cyclic (letter ‘y’ in a shift of 3 should become ‘a’ again).
I have some bugs, though. If I shift ‘t’ 11 times, it’ll come to ‘e’, but if I shift ‘t’ 12 times, I get space (” “). Why? Here’s my code:
3 int main(int argc, char *argv[]) {
4 if (argc != 2) {
5 printf ("Wrong input\n");
6 return 1;
7 }
8 int shift = atoi (argv[1]);
9 int c;
10 while ((c = getchar()) != EOF) {
11 if (c >= 'a' && c <= 'z') {
12 char newch = c + shift;
13 if (newch > 'z') {
14 newch = 'a' + (newch - 'z' - 1);
15 }
16 if (newch < 'a') {
17 newch = 'z' - ('a' - newch - 1);
18 }
19 putchar (newch);
20 }
21 else
22 putchar(c);
23 }
24 return 0;
25 }
Also, when compiling I receive those warnings:
shift_chars.c: In function `main':
shift_chars.c:8: warning: implicit declaration of function `atoi'
shift_chars.c:8: warning: ISO C90 forbids mixed declarations and code
What do those mean?
The first warning means you did not include
<stdlib.h>, which is whereatoi()is declared.The second warning means that you declared variables (
shiftetc) after you had some executable code. C++ allows that; C99 allows that; ISO C 90 (ANSI C 89) did not allow that. In older C, all variables in a block had to be defined before any executable statements.Also, if you are shifting 3 and translate ‘y’ to ‘a’ you have a bug — it should be ‘b’ (‘z’, ‘a’, ‘b’).
One of your problems is that the code for ‘z’ is 122, and adding 11 to 122 wraps you to a negative value if your characters (
chartype) are signed; you do not have this problem ifcharis unsigned. You’d probably do best to use anintinstead ofcharwhile computing the new character value.You might find it easier to manage if you calculate:
The
c - 'a'gives you an index into the alphabet: a = 0, b = 1, … z = 25. Add the shift; take the result modulo 26 to get the offset into the alphabet again; then add the result to'a'to get the correct letter. Sincec - 'a'generates an integer (because allcharvalues are promoted toint), this avoid any overflows inchar.Indeed, you could avoid
newchaltogether and simply compute:You can then omit the
putchar()at line 19, and drop theelse, leaving theputchar(c);to output both transformed and untransformed characters.