0

Так уж пришлось, что мне нужно сделать задание в C++ builder 6. И такой вопрос, как изменить маленькую букву на большую через изменение кода символа. Так как это кириллица, функция toUpper не поможет. Пример: а - А, б - Б.

Я пробовал так, но ничего не получилось:

string symbol; 

cin >> symbol;

if (symbol == 'a') {
   symbol -= 32; 
}

cout << symbol;

Так же пробовал ставить условие

 (symbol >= 'а') && (symbol <='п')
trigsen
  • 35
  • Поменяйте string на char. String - это строка, массив символов в обертке. Char - единичный символ. – Wootiae Dec 07 '18 at 21:37
  • Наверное, всё-таки, не кодировку изменить, а регистр? – Alexander Petrov Dec 07 '18 at 21:43
  • Данный вопрос задавался в той или иной форме уже десятки раз. Посмотрите в разделе "Похожие" – tocic Dec 08 '18 at 11:35

2 Answers2

0

На счет функции toupper Вы не правы. Просто перед использованием функций работы с символами сначала нужно установить локализацию, другими словами надо указать с какой таблицей символов будет работать функция. Вот здесь все в описано.

Вот пример ближе к вашему вопросу:

// locale::locale
#include <iostream>       // std::cout
#include <locale>         // std::locale
#include <stdexcept>      // std::runtime_error

int main ()
{
    std::locale loc;     // initialized to locale::classic()

    try {
        loc = std::locale ("Russian");
        std::string s = "ыыыыы";
        for (auto& c:s)
            c = std::toupper(c, loc);
        std::cout << s << '\n';
    }
    catch (std::runtime_error) {
        loc = std::locale (loc, "", std::locale::ctype);
    }

    std::cout << "The selected locale is: " << loc.name() << '\n';

    return 0;
}

UPD

При установке локализации (Подробнее здесь) нужно понимать какая кодировка попадает на вход. Если это внешние данные, то нужно знать в какой кодировке они поступают. Например, при вводе с консоли это может быть 866(OEM) страница, а программа ожидает 1251(ANSI). Для этого нужно явно указать кодировку. Например:

loc = std::locale ("Russian_Russia.866");
Andrey Sv
  • 1,031
  • 1
    "Russian" - implementation-defined локаль – tocic Dec 08 '18 at 11:30
  • locale loc ("Russian"); s[position] = toupper(s[position], loc); При такой записи буквы а - п не переводит вообще, а символы ф - я переводит в крокозябры ( ф перевело в _ ) – trigsen Dec 08 '18 at 11:33
  • Борландовская toUpper в билдере скорее всего не то же самое, что библиотечная toupper. Вполне возможно, что борландовская toUpper работает не обращая внимания на локаль. Транслятор довольно древний и тогда поддержки локали как следует не делали. – pepsicoca1 Dec 08 '18 at 12:05
  • @pepsicoca1 В данном случае человек использует std::string и std::cin как бы логично, что и toupper должен быть стандартным. – Andrey Sv Dec 08 '18 at 12:41
  • @Andrey Sv Как раз человек пишет про toUpper. Это чисто борландовская функция. Это не то же самое, что toupper из библиотеки С++. Это даже не функция Борланд, а метод для борландовских строк (если мне не изменяет мой склероз). – pepsicoca1 Dec 08 '18 at 12:43
  • @pepsicoca1 Я больше запомнил паскалевский UpperCase и AnsiUpperCase. toUpper я вообще не нашел, по крайней мере в исходниках библиотек embarcadero. Такой метод нашелся только в boost, вот я и решил, что человек просто ошибся регистром. – Andrey Sv Dec 08 '18 at 13:12
-1

Пример для латиницы, но для кириллицы тоже будет работать.
Я делаю так, хотя меня за это и ругают некоторые граждане.
Может быть кому-то кажется, что это не очень красиво, зато решение на 101% портабельное.
Будет работать на всех кодировках, и на ASCII, и на EBCDIC и на любой другой.
Для кириллицы будет работать и на КОИ и на CP1251 и на Юникоде.

char my_to_upper(char ch){
char retchar;

switch(ch){
case 'a':retchar='A';break;
case 'b':retchar='B';break;
case 'c':retchar='C';break;
case 'd':retchar='D';break;
case 'e':retchar='E';break;
case 'f':retchar='F';break;
case 'g':retchar='G';break;
case 'h':retchar='H';break;
case 'i':retchar='I';break;
case 'j':retchar='J';break;
case 'k':retchar='K';break;
case 'l':retchar='L';break;
case 'm':retchar='M';break;
case 'n':retchar='N';break;
case 'o':retchar='O';break;
case 'p':retchar='P';break;
case 'q':retchar='Q';break;
case 'r':retchar='R';break;
case 's':retchar='S';break;
case 't':retchar='T';break;
case 'u':retchar='U';break;
case 'v':retchar='V';break;
case 'w':retchar='W';break;
case 'x':retchar='X';break;
case 'y':retchar='Y';break;
case 'z':retchar='Z';break;

default: retchar=ch;break;
}

return retchar;
}

UPD1:

В большинстве случаев для кириллицы это не будет работать, т.к. буквы в большинстве случаев занимают > 1 байта, а размер char в большинстве случаев равен 1 байту – Tocic 5 минут назад

Не, ну для Юникода, конечно, надо брать тип wchar_t.
Если входной символ wchar_t, то и выходной символ, естественно, тоже будет wchar_t.
Идея в том, что схема со switch работать будет и для всех типов символов (в том числе и для wchar_t), и для всех кодировок.
В конце концов, если уж быть пуристом, можно сделать шаблон.

template <class T> T my_to_upper(T ch){
    T retchar;

    switch(ch){
    case 'a':retchar='A';break;
    case 'b':retchar='B';break;
    case 'c':retchar='C';break;
    case 'd':retchar='D';break;
    case 'e':retchar='E';break;
    case 'f':retchar='F';break;
    case 'g':retchar='G';break;
    case 'h':retchar='H';break;
    case 'i':retchar='I';break;
    case 'j':retchar='J';break;
    case 'k':retchar='K';break;
    case 'l':retchar='L';break;
    case 'm':retchar='M';break;
    case 'n':retchar='N';break;
    case 'o':retchar='O';break;
    case 'p':retchar='P';break;
    case 'q':retchar='Q';break;
    case 'r':retchar='R';break;
    case 's':retchar='S';break;
    case 't':retchar='T';break;
    case 'u':retchar='U';break;
    case 'v':retchar='V';break;
    case 'w':retchar='W';break;
    case 'x':retchar='X';break;
    case 'y':retchar='Y';break;
    case 'z':retchar='Z';break;

    default: retchar=ch;break;
    }

    return retchar;
    }

UPD2:

Для кириллицы в кодировке CP1251 (которая как раз используется в Борланд 6.0 Билдер), будет работать и вариант с char.

UPD3:

Ваш код для char можно записать как return symbol < 65 || symbol > 122 ? symbol : ((char)(((int)symbol) + 32)); – LLENN 10 секунд назад

Это будет работать для кодировки ASCII. Но, к примеру, для кодировки EBCDIC это работать не будет.

UPD4:

@pepsicoca1 '...' - это литерал типа char – Tocic 10 минут назад

Правильно, но на этот случай у нас есть switch с винтом.

wchar_t my_to_upper(wchar_t ch){
wchar_t retchar;

switch(ch){
case L'a':retchar=L'A';break;
case L'b':retchar=L'B';break;
case L'c':retchar=L'C';break;
case L'd':retchar=L'D';break;
case L'e':retchar=L'E';break;
case L'f':retchar=L'F';break;
case L'g':retchar=L'G';break;
case L'h':retchar=L'H';break;
case L'i':retchar=L'I';break;
case L'j':retchar=L'J';break;
case L'k':retchar=L'K';break;
case L'l':retchar=L'L';break;
case L'm':retchar=L'M';break;
case L'n':retchar=L'N';break;
case L'o':retchar=L'O';break;
case L'p':retchar=L'P';break;
case L'q':retchar=L'Q';break;
case L'r':retchar=L'R';break;
case L's':retchar=L'S';break;
case L't':retchar=L'T';break;
case L'u':retchar=L'U';break;
case L'v':retchar=L'V';break;
case L'w':retchar=L'W';break;
case L'x':retchar=L'X';break;
case L'y':retchar=L'Y';break;
case L'z':retchar=L'Z';break;

default: retchar=ch;break;
}

return retchar;
}
pepsicoca1
  • 5,019
  • В большинстве случаев для кириллицы это не будет работать, т.к. буквы в большинстве случаев занимают > 1 байта, а размер char в большинстве случаев равен 1 байту – tocic Dec 08 '18 at 11:32
  • Вы пробовали запускать свой код для wchar_t? Вы сравниваете его с char – tocic Dec 08 '18 at 12:06
  • @Tocic Я сравниваю его с символом ch. А символ ch в варианте шаблонной функции имеет тип T. Соответственно, константа (к примеру) 'r', тоже имеет тип T. Если инстанцировать шаблон типом wchar_t, то все будет правильно. – pepsicoca1 Dec 08 '18 at 12:10
  • '...' - это литерал типа char в вашем коде – tocic Dec 08 '18 at 12:14
  • Бессмысленный switch заменяется как: return symbol < 65 || symbol > 122 ? symbol : ((char)(((int)symbol) + ((symbol > 90) ? -32 : 32))); –  Dec 08 '18 at 12:15
  • Вот теперь ваш код работает для wchar_t, но является непортабельным – tocic Dec 08 '18 at 12:36
  • @Tocic Это почему же непортабельным? – pepsicoca1 Dec 08 '18 at 12:37
  • @pepsicoca1 из-за типа wchar_t, который может занимать 2 или 4 байта – tocic Dec 08 '18 at 12:38
  • @Tocic Когда Вы будете транслировать этот код на разных платформах, то транслятор сам поставит нужный на этой платформе размер wchar_t. И Вам не придется править свой текст. Так что все портабельно. – pepsicoca1 Dec 08 '18 at 12:40
  • @pepsicoca1 как вы будете портабельно переводить symbol из вопроса автора в wchar_t для вашей функции? – tocic Dec 08 '18 at 12:43
  • @Tocic Символ 'п' что-ли? Так и напишу L'п'. А в чем проблемы? – pepsicoca1 Dec 08 '18 at 12:45
  • @pepsicoca1 Какой 'п'? symbol из кода автора вопроса – tocic Dec 08 '18 at 12:47
  • @Tocic В вопросе symbol это вообще строка. – pepsicoca1 Dec 08 '18 at 12:49
  • @pepsicoca1 Да, и её просто так нельзя подать на вход вашей функции. – tocic Dec 08 '18 at 12:54
  • @Tocic Естественно на вход этой функции нельзя подать строку, так как эта функция конвертирует один символ. Если нужно конвертировать строку, то надо применить эту функцию ко всем символам строки. Но это не отменяет того факта, что решение со switch портабельное. – pepsicoca1 Dec 08 '18 at 12:56
  • @pepsicoca1 Вы не предоставили решение. Вы написали функцию (после длительных споров), которая для wchar_t даёт другой wchar_t. Если решением является "надо применить эту функцию ко всем символам строки", то оно неверно, потому что std::string - это массив char, и вы снова приводите char к wchar_t (а метода перевода вы не предоставили). Мне надоело с вами спорить уже, почитайте лучше тут про типы литералов – tocic Dec 08 '18 at 13:01
  • @Tocic Это все не важно. Важно что функция конвертации, которая использует switch, портабельная. И эта функция не зависит ни от кодировки, ни от размера типа wchar_t. – pepsicoca1 Dec 08 '18 at 13:16