С Новым годом! Форум программистов, компьютерный форум, киберфорум
Наши страницы

С++ для начинающих

Войти
Регистрация
Восстановить пароль
 
Рейтинг: Рейтинг темы: голосов - 12, средняя оценка - 4.67
Gepar
1178 / 534 / 20
Регистрация: 01.07.2009
Сообщений: 3,517
#1

Регистронезависимое сравнение строк с русскими буквами - C++

27.11.2012, 20:50. Просмотров 1655. Ответов 14
Метки нет (Все метки)

Необходимо регистронезависимо сравнивать строки string с русскими буквами. Пробовал поиграться с встроенным toUpper но у меня вот так он не работает:
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
    bool compare_nocase(const string &str1, const string &str2)
    {
        string::const_iterator i1 = str1.begin(), i2 = str2.begin();
        std::locale loc = std::locale::classic();
 
        while((i1 != str1.end()) && (i2 != str2.end()))
        {
            if(toupper(*i1,loc) != toupper(*i2,loc))
            {
                return false;
            }
 
            ++i1, ++i2;
        }
 
        return (str1.length() == str2.length());
    }
Те в данном случае возвращается один только если вызвать для "строка"="строка", а для "строка"="сТрока" уже вернёт 0. Что посоветуете?

Добавлено через 3 минуты
Вспоминается мне что в с++ что-то было там по культурам, но помню я тот раздел в книге где я его видел читать не стал, а вот сейчас какраз что-то такое видимо и надо ...
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
27.11.2012, 20:50
Здравствуйте! Я подобрал для вас темы с ответами на вопрос Регистронезависимое сравнение строк с русскими буквами (C++):

Как реализовать сравнение строк с русскими символами - C++
Дело обстоит так: Нужно сравнить на сходство русские слова. Пробовал strcmp - но она что-то лениться с не англоязычными символами работать...

Дан файл, содержащий текст, записанный строчными русскими буквами. Получить в другом файле тот же текст, записанный заглавными буквами - C++
Дан файл, содержащий текст, записанный строчными русскими буквами. Получить в другом файле тот же текст, записанный заглавными буквами.

Вывод русскими буквами - C++
Вообщем в задачке нужно рассчитать всевозможные тройки ФИО. #include <iostream> #include <conio.h> #include <cstring> #include...

Программа не хочет работать с русскими буквами - C++
Здравствуйте! Программа инвертирует цифры в 8 системе счисления, и должна преобразовывать Заглавные Русские буквы в строчные. ...

Ввод и вывод текста русскими буквами - C++
Уже неделю лазаю туда-сюда, в поисках решения. Посмотрите пожалуйста, что можно добавить чтобы в консоли выводили русские буквы. ...

Корректная работа программы с русскими буквами - C++
Здравствуйте. Мне нужно было написать программу, которая ставит кратчайшее слово в конец и из строки убирает все цифры. В принципе,...

14
Toshkarik
1147 / 864 / 51
Регистрация: 03.08.2011
Сообщений: 2,404
Завершенные тесты: 1
27.11.2012, 20:51 #2
Gepar, а размер строки соответствует количеству символов?
0
Gepar
1178 / 534 / 20
Регистрация: 01.07.2009
Сообщений: 3,517
27.11.2012, 20:56  [ТС] #3
Toshkarik, да, конечно.
C++
1
2
3
4
5
6
7
int main()
{
    string str1="строка";
    string str2="стрОка";
    cout<<(str1.length()==str2.length())<<"\t=\t"
        <<stringHelper::compare_nocase(str1,str2)<<endl; //1 = 0
}
0
Toshkarik
1147 / 864 / 51
Регистрация: 03.08.2011
Сообщений: 2,404
Завершенные тесты: 1
27.11.2012, 21:00 #4
Gepar, ну я просто думал, вдруг используется multibyte characters. А смотрели, что выводит toupper? Пробовали вывести через cout?
0
Gepar
1178 / 534 / 20
Регистрация: 01.07.2009
Сообщений: 3,517
27.11.2012, 21:06  [ТС] #5
Toshkarik, если ты о самих строках то в cout выводятся они корректно (при условии использования SetConsoleOutputCP(1251) из windows.h).
0
Toshkarik
1147 / 864 / 51
Регистрация: 03.08.2011
Сообщений: 2,404
Завершенные тесты: 1
27.11.2012, 21:07 #6
Gepar, как я и думал, у меня используется multibyte. Размер строки из 6 русских букв равен 12. Возможно у Вас так же.
0
Gepar
1178 / 534 / 20
Регистрация: 01.07.2009
Сообщений: 3,517
27.11.2012, 21:35  [ТС] #7
Что-то свой toUpper не помог, видимо там разница меняется между символами ...
C++
1
2
3
4
5
6
7
8
9
10
wchar_t toUpper(const wchar_t ch)
{
    static wchar_t A = 'А';
    static wchar_t a = 'а';
    static int diff= A - a;
    if(ch<A)
        return ch+diff;
    else
        return ch;
}
Хотя проанализировав задачу выявил что мне не очень то нужно сравнивать строки с русскими символами, в принципе мне достаточно переводить первый символ первого слова в предложении в нижний регистр ... но тем не менее мне нужно как-то это сделать.

Добавлено через 58 секунд
Toshkarik, у меня размер строки = количеству символов в ней, но это проблему не решает так как нужно что-то апаратно независимое для возможности перевода из верхнего регистра в нижний русских букв.

Добавлено через 17 минут
Ладно, для моей задачи вполне должно быть достаточно функции toLov для перевода первого символа в словах. Вот такая работает у меня вполне нормально, знать бы ещё как она себя поведёт на другой машине
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
wchar_t toLov(const wchar_t ch)
{
    static wchar_t A = 'А';
    static wchar_t a = 'а';
    static int diff= a - A; // = 32
    if(ch>=A && ch<a) // в верхнем регистре
        return ch+diff;
    else
        return ch;
}
 
int main()
{
    SetConsoleCP(1251);
    SetConsoleOutputCP(1251);
    string str1="Абрикос";
    string str2="Мазда";
    string str3="Ява";
    str1[0]=toLov(str1[0]);
    str2[0]=toLov(str2[0]);
    str3[0]=toLov(str3[0]);
    cout<<str1<<'\n'<<str2<<'\n'<<str3<<endl;
}
Проверьте если кому не трудно
0
Toshkarik
1147 / 864 / 51
Регистрация: 03.08.2011
Сообщений: 2,404
Завершенные тесты: 1
27.11.2012, 21:36 #8
Цитата Сообщение от Gepar Посмотреть сообщение
toLov

Не по теме:

toLow

1
Gepar
1178 / 534 / 20
Регистрация: 01.07.2009
Сообщений: 3,517
27.11.2012, 21:44  [ТС] #9
Что любопытно такой вот toUp работает правильно если проверять работу в main, а вот в функции при проходе итератором говорит что коды не совпадают
C++
1
2
3
4
5
6
7
8
9
10
wchar_t toUp(const wchar_t ch)
{
    static wchar_t A = 'А';
    static wchar_t a = 'а';
    static int diff= a - A; // = 32
    if(ch>=a && ch<A) // в нижнем регистре
        return ch;
    else
        return ch-diff;
}
При этом
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
    bool compare_nocase(const string &str1, const string &str2)
    {
        string::const_iterator i1 = str1.begin(), i2 = str2.begin();
        std::locale loc = std::locale::classic();
 
        while((i1 != str1.end()) && (i2 != str2.end()))
        {
            if(toUp(*i1) != toUp(*i2))
            {
                return false;
            }
 
            ++i1, ++i2;
        }
 
        return (str1.length() == str2.length());
    }
говорит что "стрОка" = "строка" false

Добавлено через 47 секунд
Toshkarik, а, это я воевал с ещё 3мя вариантами изменяя немного название функции чтобы не гризлись и сразу находились рядышком, это исправить недолго

Добавлено через 3 минуты
Хотя вот так уже работает правильно:
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
wchar_t toLow(const wchar_t ch)
{
    static wchar_t A = 'А';
    static wchar_t a = 'а';
    static int diff= a - A; // = 32
    if(ch>=A && ch<a) // в верхнем регистре
        return ch+diff;
    else
        return ch;
}
 
    bool compare_nocase(const string &str1, const string &str2)
    {
        string::const_iterator i1 = str1.begin(), i2 = str2.begin();
        std::locale loc = std::locale::classic();
 
        while((i1 != str1.end()) && (i2 != str2.end()))
        {
            if(toLow(*i1) != toLow(*i2))
            {
                return false;
            }
 
            ++i1, ++i2;
        }
 
        return (str1.length() == str2.length());
    }
абрикос = АбРиКос true
0
Toshkarik
1147 / 864 / 51
Регистрация: 03.08.2011
Сообщений: 2,404
Завершенные тесты: 1
27.11.2012, 21:47 #10
Gepar, так я вообще не понимаю смысл использования wchar_t в этих функциях.
0
Gepar
1178 / 534 / 20
Регистрация: 01.07.2009
Сообщений: 3,517
27.11.2012, 22:14  [ТС] #11
Toshkarik, ну ... в общем-то раз уж я начала сравнивать коды с static wchar_t A = 'А' и static wchar_t a = 'а' то чтобы правильно сравнивалось нужен wchar_t и для входного аргумента.
0
MrGluck
Модератор
Эксперт CЭксперт С++
7498 / 4614 / 694
Регистрация: 29.11.2010
Сообщений: 12,633
27.11.2012, 22:34 #12
http://www.boost.org/doc/libs/1_51_0...nversions.html

Добавлено через 13 минут
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
#include <iostream>
#include <string>
#include <clocale>
#include <cctype>
#include <algorithm>
 
bool foo(const std::wstring &s1, const std::wstring &s2)
{
    if (s1.length() != s2.length() )
        return false;
    return std::equal(s1.begin(), s1.end(), s2.begin(),
        [](wchar_t c1, wchar_t c2) { return std::wcscoll(&c1, &c2); } );
}
 
int main()
{
    setlocale(LC_ALL, "");
    std::wstring str1 = L"привет", str2 = L"приВеТ", str3 = L"привет";
    std::cout<< std::boolalpha<< foo(str1, str2);
    return 0;
}
1
Gepar
1178 / 534 / 20
Регистрация: 01.07.2009
Сообщений: 3,517
28.11.2012, 19:34  [ТС] #13
MrGluck, boost это конечно хорошо, но это когда пишешь что-то для себя, а когда пишешь какую-то курсовую или ещё чего то преподаватели это всё не одобряют.
0
MrGluck
Модератор
Эксперт CЭксперт С++
7498 / 4614 / 694
Регистрация: 29.11.2010
Сообщений: 12,633
28.11.2012, 20:36 #14
Цитата Сообщение от Gepar Посмотреть сообщение
MrGluck, boost это конечно хорошо, но это когда пишешь что-то для себя, а когда пишешь какую-то курсовую или ещё чего то преподаватели это всё не одобряют.
Я выше код написал, который буст не использует и корректно работает.

Добавлено через 44 минуты
Я бы даже сказал так:
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
#include <iostream>
#include <string>
#include <clocale>
 
bool foo(const std::wstring &s1, const std::wstring &s2)
{
    if (s1.length() != s2.length() )
        return false;
    return std::wcscoll(s1.c_str(), s2.c_str());
}
 
int main()
{
    setlocale(LC_ALL, "");
    std::wstring str1 = L"привет", str2 = L"приВеТ";
    std::cout<< std::boolalpha<< foo(str1, str2);
    return 0;
}
1
Gepar
1178 / 534 / 20
Регистрация: 01.07.2009
Сообщений: 3,517
28.11.2012, 21:26  [ТС] #15
MrGluck, да то мне что-то вместо boolalpha буст привидился, извиняюсь.
0
28.11.2012, 21:26
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
28.11.2012, 21:26
Привет! Вот еще темы с ответами:

как вывести русскими буквами слово С++ - C++
#include &lt;iostream&gt; #include &lt;cmath&gt; #include &lt;string&gt; using namespace std; int main(){ string word; cin&gt;&gt;word; ...

fopen и путь к файлу c русскими буквами - C++
Всем привет:) Вот столкнулся с такой проблемой - необходимо открыть файл, путь к которому вводится в консоли. Для открытия файла...

Неправильно работает функция strcmp c русскими буквами - C++
Пытаюсь сравнить строку с литералом. void main() { setlocale(LC_ALL, &quot;Rus&quot;); string s1; cin &gt;&gt; s1; int k =...

Массив словаря почему-то не работает с русскими буквами - C++
Дан двумерный массив словаря, почему не работает с русскими буквами, а работает только с английскими, помогите разобраться: #include...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
15
Ответ Создать тему
Опции темы

КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2017, vBulletin Solutions, Inc.