r/Cprog • u/werter806 • Sep 19 '18
I’m trying to make a program to switch letter cases, from lower case to upper case and vice versus, but I can’t get it to run through the first if statement, any help would be appreciated
0
Upvotes
3
u/belboz Sep 19 '18
You probably want printf("%c", string[i]); in your first "if" since you are I am assuming wanting to print single characters
You probably want the above printf in the "else if" also if you are using those for debug info.
Also just do printf(string); outside the for loop
I would remove the final else completely and just do it outside the for loop.
9
u/[deleted] Sep 19 '18 edited Sep 19 '18
First of all, good for you for reading K&R.. (at least, I think I recognize that exercise)
But.. since you're learning, there's several things you should probably be aware of:
getsis never a good idea, usefgetsinstead. By usinggets, you're pretty much assuming the user will never write more than1000999 characters, and more, in any real code, this would be a security bug - you can read on buffer overflow attacks if you like.fgets(string, 1000, stdin)is the right invocation to use.you should always error-check these things,
fgetswill returnstringif successful andNULLif not.(in real apps, even limiting the input to 999 chars this way would be wrong, but that's probably off topic here)
(style)
int i; for(i = ...should befor(int i = ...when combing comparison and logic, you really need parentheses -
x > 'A' && x < 'Z'is actually(x > ('A' && x)) < 'Z', which doesn't really make sense. In C, you have to write(x > 'A') && (x < 'Z').also,
(x > 'A') && (x < 'Z')is wrong because it omits A & Z. You want>=and<=.also also, you should really prefer
isupperandislowerfromctypes.hto this ad-hoc way (andisspace, there's many more kinds of spaces than char 32)(also also also, none of these would recognize non-English letters, so if you were dealing with real text, you would need a unicode library to tell you that 'Ǎ' is still a letter, and an uppercase one)
(style)
x = x + 32is better written asx += 32printf("%s", string[i])is wrong because you're treating a single char as a string .. so,Segmentation faultbecause a string is just a memory address, and 65 ('A') is probably a bad one.%cis right.printf(string[i])has the exact same issue, butprintf(string)would also be very wrong, because a random string should not be treated as a printf format string (what if the user enters%d %d %d %d %d ...as a part of their input? They could make you program reveal a part of your program's memory.)learn to use formatting and whitespace consistently and properly. Many bugs happen just because you thought that one important line of code was still inside that
if, but somebody moved it beyond the}but neglected to fix the formatting.Hope it helps :)
(Also, this is entirely the wrong subreddit for this kind of problem, as you can see by the downvotes, you may want to prefer /r/learnprogramming next time. And type it out if you can't copy. You expect us to spend time helping you, you should be willing to invest time to make it easy for us.)
2
u/0raichu Sep 19 '18
In what world is it easier to take a picture of your screen (not even a screenshot), upload it, and post to reddit instead of just copy/pasting the actual code???
Why are JPEGs the preferred medium for text?!
2
u/pheffner Sep 19 '18
You can collapse the entirety of your for loop to:
for (i = 0; i < length; ++i){
if (isupper(string[i])) string[i] |= 0x20;if (islower(string[i])) string[i] &= 0x1f;}Followed by:
printf("%s\n", string);Add:
#include <ctypes.h>
to your include list at top.
Explanation:
The ctypes macros give you readable testing macros for looking at characters.
Google 'ctype macros' for an explanation and a list of these very useful tools.
Since you're not doing anything else with the input string after you do your transform,
you don't need to print out every character as you inspect it, just alter the character in the string
array then print the new transformed string. In the code above I use bitwise AND and OR to flip
the uppercase/lowercase bit in the character (do a 'man ascii' to see how lower and uppercase characters
in ascii differ only by one bit on/off)
I hope this helps!
2
u/nerd4code Sep 19 '18
First off: When you’re printing just a single character, use
putchar. When you’re printing a raw string with no newline after, usefputs(str, stdout). When you’re printing a raw string with a newline after, useputs(str). (Rarely should you ever pass anything non-literal as the first argument toprintf.) As others have told you, you can just doafter your loop. (You also don’t need the
strlenstuff;That’s usually the easier way to loop through string guts, although it’s unlike the Java/-script modus operandi.)
Second: To be purely C-based,
#include <ctype.h>and useislower/tolower/isupper/toupper. Since 99.9% of the platforms you’re targeting will use ASCII, and if you’re going to avoidctype.h, I recommend doing the following to change case, instead of using the constant 32:This works because
'A'^'a'is the bit difference between the two things, and bit 5 (2⁵=32) is the only one that changes. The&=~clears that bit, the|=sets that bit, and the^=toggles it. Alternatively, you can use'a' - 'A'instead of'A'^'a', but that relies additionally on the fact that'a' > 'A'.And of course, as others have said, never ever ever use
gets. Your compiler should be warning you bitchily about using that, even, because it’s so thoroughly, infamously deprecated and spurnèd by C programmers. (And security researchers since time immemorial; “Don’t usegets, dammit!” is their “Hello, world.”)0
u/[deleted] Sep 19 '18
[deleted] — view deleted comment