0

I am trying to convert all lowercase to uppercase letter, using the ASCII table! It is very easy to deal and i have figured out the code. Problem is, that if there is a space between the words, then the program will only change the first word and after the space it will not print anything.

Example
Word: Andreas Gives: ANDREAS
Word: TeSt123Ha Gives: TEST123HA
BUT!!!
Word: Hello 45 Gives: HELLO
after the space it prints nothing!

I know that the space in ASCII table is equal to 32, and in my code i tell the program that if the current code that you are reading is not between 97 and 122, then don't perform any changes!

But it is still not working!

char currentletter;
int i;

for (i=0; i<49; i++)    
{
    currentletter = str[i];

    if ((currentletter > 96) && (currentletter < 123))
    {
        char newletter;
        newletter = currentletter - 32;
        str[i] = newletter;
    }
    else
    {
        str[i] = currentletter;
    }
}
printf("%s\n", str);
Yu Hao
  • 119,891
  • 44
  • 235
  • 294
Andrei Cusnir
  • 2,735
  • 1
  • 14
  • 21
  • 4
    You don't show how `str` is initialized - I'll bet the words after the space aren't even in there (is `str` initialized with `argv[1]`?) What happens if you do `printf("%s\n", str);` *before* the case conversion code? – Michael Burr Sep 13 '14 at 08:18
  • 1
    @MichaelBurr: Good point. `scanf("%s", str)` is another contender for single-word input. – M Oehm Sep 13 '14 at 08:53
  • Your `else` branch is not the source of the problem but still completely redundant. – 5gon12eder Sep 13 '14 at 09:01
  • The 32 in your program is 'a'-'A'. In addition to ASCII, this will probably work with the character set/encoding/code page you are actually using. Maybe Windows-1252 or Unicode/UTF-8? Use `locale` (Linux) or `chcp` (Windows) to check. Of course, those characters sets have more letters that you aren't accounting for. – Tom Blodget Sep 13 '14 at 10:30
  • @Tom: in Windows-1252 and in UTF8 this code is still valid, since the codes for 32 up to 126 are all the same. But perhaps you were thinking of EBCDIC. – Jongware Sep 13 '14 at 10:49
  • @Jongware My points are 1) yes, this algorithm works for the [ISO basic Latin alphabet](http://en.wikipedia.org/wiki/ISO_basic_Latin_alphabet) in character set encodings that are likely being used and 2) _ASCII is not what is likely being used._ – Tom Blodget Sep 13 '14 at 18:40

3 Answers3

11

flipping the 5th lowest bit should help.

Each lowercase letter is 32 + uppercase equivalent. This means simply flipping the bit at position 5 (counting from least significant bit at position 0) inverts the case of a letter. https://web.stanford.edu/class/cs107/lab1/practice.html

char *str;
int str_size = sizeof(str);

for(int i=0; i<str_size;i++){
   if((str[i]>96) && (str[i]<123)) str[i] ^=0x20;
} 
Guest0x20
  • 126
  • 1
  • 4
2

You have mentioned in one of the comments that you use scanf("%s", str); to get the string. The problem is that %s will stop scanning once it finds a whitespace character. In your case, it stops scanning when it sees the space character.

Use fgets() if you want to scan one whole line:

fgets(str, sizeof(str), stdin);

Once thing to note here is that fgets will scan in the newline character into the string as well.


Your code can be simplified to:

for (int i = 0; str[i] != '\0'; i++) // Loop until the NUL-terminator
{
    if ((str[i] >= 'a') && (str[i] <= 'z')) // If the current character is a lowercase alphabet
        str[i] = str[i] - ('a' - 'A');      // See the ASCII table to understand this:
                                            // http://www.asciitable.com/index/asciifull.gif
}

printf("%s\n", str);

Or a more easier way would be to use tolower from ctype.h:

#include <ctype.h>

for(int i = 0; str[i] != '\0'; i++) // Loop until the NUL-terminator
{
    str[i] = tolower(str[i]); // Convert each character to lowercase (It does nothing if the character is not an alphabet)
}

printf("%s\n", str);
Spikatrix
  • 20,225
  • 7
  • 37
  • 83
-1

I gave it a try using STL and a Lambda just for fun:

string input = "";
getline(cin, input);
transform(input.begin(), input.end(), input.begin(), [](char c) { return (c > 96 && c < 123) ? c ^= 0x20 : c; });
copy(input.begin(), input.end(), ostream_iterator<char>(cout, " "));

I compiled and tested with c++ 17 in Visual Studio 2019, and did not perform exhaustive testing!

Cozmo
  • 53
  • 3