Преобразование нижнего регистра в верхний с помощью ASCII

Я пытаюсь преобразовать все строчные буквы в прописные, используя таблицу ASCII! Это очень легко иметь дело, и я понял код. Проблема в том, что если между словами есть пробел, то программа изменит только первое слово и после пробела ничего не напечатает.

Пример
Word: Andreas Выдает: ANDREAS
Word: TeSt123Ha Выдает: TEST123HA
НО!!!
Word: Hello 45 Выдает: HELLO
после пробела ничего не печатает !

Я знаю, что пробел в таблице ASCII равен 32, и в своем коде я говорю программе, что если текущий код, который вы читаете, не находится между 97 и 122, то не вносите никаких изменений!

Но он все еще не работает!

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);

person Andrei Cusnir    schedule 13.09.2014    source источник
comment
Вы не показываете, как инициализируется str — держу пари, что слов после пробела там даже нет (str инициализируется с помощью argv[1]?) Что произойдет, если вы сделаете printf("%s\n", str); до преобразования регистра код?   -  person Michael Burr    schedule 13.09.2014
comment
@MichaelBurr: Хороший вопрос. scanf("%s", str) — еще один претендент на ввод одного слова.   -  person M Oehm    schedule 13.09.2014
comment
Ваша ветка else не является источником проблемы, но все же полностью избыточна.   -  person 5gon12eder    schedule 13.09.2014
comment
32 в вашей программе — это «а» — «А». В дополнение к ASCII это, вероятно, будет работать с набором символов/кодировкой/кодовой страницей, которую вы фактически используете. Может быть, Windows-1252 или Unicode/UTF-8? Используйте locale (Linux) или chcp (Windows) для проверки. Конечно, в этих наборах символов есть больше букв, которые вы не учитываете.   -  person Tom Blodget    schedule 13.09.2014
comment
@Tom: в Windows-1252 и в UTF8 этот код все еще действителен, поскольку все коды от 32 до 126 одинаковы. Но, возможно, вы имели в виду EBCDIC.   -  person Jongware    schedule 13.09.2014
comment
@Jongware Мои точки зрения таковы: 1) да, этот алгоритм работает для базового латинского алфавита ISO в символах установить кодировки, которые, вероятно, используются, и 2) ASCII, скорее всего, не используется.   -  person Tom Blodget    schedule 13.09.2014


Ответы (3)


переворачивание 5-го младшего бита должно помочь.

Каждая строчная буква эквивалентна 32 + прописным буквам. Это означает, что простое переключение бита в позиции 5 (считая с младшего значащего бита в позиции 0) инвертирует регистр букв. 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;
} 
person Guest0x20    schedule 22.05.2018

У вас есть упомянутый в одном из комментариев, что вы используете scanf("%s", str); чтобы получить строку. Проблема в том, что %s прекратит сканирование, как только найдет символ пробела. В вашем случае он останавливает сканирование, когда видит пробел.

Используйте fgets(), если вы хотите отсканировать всю строку:

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

Здесь следует отметить, что fgets также будет сканировать символ новой строки в строку.


Ваш код можно упростить до:

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);

Или более простым способом было бы использовать tolower из 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);
person Spikatrix    schedule 13.09.2014

Я попробовал использовать STL и Lambda просто для удовольствия:

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, " "));

Я скомпилировал и протестировал C++ 17 в Visual Studio 2019 и не проводил исчерпывающего тестирования!

person Cozmo    schedule 04.07.2019
comment
Вопрос помечен c, а не С++ - person Spikatrix; 05.07.2019