Модераторы: bsa
  

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Проблема с кодировкой 
V
    Опции темы
Ares4322
Дата 29.5.2013, 13:46 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 339
Регистрация: 25.9.2007
Где: Россия, Москва

Репутация: нет
Всего: 3



Доброго времени суток!

Товарищу в универе дали задачку. 
По сути, это простенькая БД.
Вот условия:
https://docs.google.com/file/d/1fm82IlH6vc1...dit?usp=sharing

Надо решить на C++. 

Я в нем не очень силен. Основную логику переписал с примера, который был у парня. Вот код
Код

#include <cstdlib>
#include <iostream>
#include "/usr/include/ncurses.h"   //lin
//#include <conio.h>    //win
#include <string.h>
#include <string>

using namespace std;

struct book {
    char surname[20];
    char city[30];
    char tel[11];
};

void make_f() {
    FILE *f;
    int l, i;
    struct book x;
    cout << "Введите количество записей:";
    cin >> l;
    f = fopen("test.txt", "w"); //открыли файл
    for (i = 0; i < l; i++) {
        cout << "Введите фамилию:";
        cin >> x.surname;
        cout << "Введите город:";
        cin >> x.city;
        cout << "Введите номер телефона:";
        cin >> x.tel;
        fprintf(f, "%s %s %s\n", x.surname, x.city, x.tel); // записали число в файл
    }
    fclose(f); // закрыл файл
}

void see_f() {
    FILE *f;
    struct book x;
    int a;
    f = fopen("test.txt", "r"); // открыли файл
    while (!feof(f)) {
        fscanf(f, "%s %s %s\n", x.surname, x.city, x.tel); //прочитали число из файла
        printf("%s %s %s\n", x.surname, x.city, x.tel);
    }
    fclose(f); //закрыли файл
}

void work_f() {
    char tt[3];
    FILE *f;
    struct book x;
    int i;

    cout << "Выберите вариант поиска (по индексу):" << endl;
    cout << "1. Данные о тех, чья фамилия начинается с 'И', а телефон – с '905'" << endl;
    cout << "2. Данные о тех, чья фамилия начинается с 'К', а город – с 'Гжель'" << endl;
    cout << "3. Данные о тех, кто живет в Москве и имеет  телефон, оканчивающийся на '67'" << endl;
    cout << "4. Данные о тех, чья фамилия начинается с 'Д', а телефон – с '321'" << endl;
    cout << "5. Данные о тех, чья фамилия начинается с 'Р', а город – 'Псков'" << endl;
    cout << "6. Данные о тех, кто живет в г. Гжель и имеет телефон, оканчивающийся на '43'" << endl;
    cout << "7. Данные о тех, чья фамилия начинается с 'С', а телефон – с '456'" << endl;
    cout << "8. Данные о тех, чья фамилия начинается с 'М', а город – 'Киев'" << endl;
    cout << "9. Данные о тех, кто живет в Москве и имеет телефон, начинающийся на '125'" << endl;
    cout << "10. Данные о тех, чья фамилия начинается с 'Я', а телефон – с '567'" << endl;
    cout << "11. Данные о тех, чья фамилия начинается с 'Н', а город – 'Москва'" << endl;
    cout << "12. Данные о тех, кто живет в Киеве и имеет телефон, оканчивающийся на '12'" << endl;
    cout << "13. Данные о тех, чья фамилия начинается с 'А', а телефон – с '100'" << endl;
    cout << "14. Данные о тех, чья фамилия начинается с 'Б', а город – 'Львов'" << endl;
    cout << "15. Данные о тех, кто живет во Львове и имеет телефон, оканчивающийся на '00'" << endl;
    cout << "16. Данные о тех, чья фамилия начинается с 'И', а телефон – с '905'" << endl;
    cout << "17. Данные о тех, чья фамилия начинается с 'К', а город – 'Гжель'" << endl;
    cout << "18. Данные о тех, кто живет в Москве и имеет телефон, оканчивающийся на '67'" << endl;
    cout << "19. Данные о тех, чья фамилия начинается с 'Д', а телефон – с '321'" << endl;
    cout << "20. Данные о тех, чья фамилия начинается с 'Р', а город – 'Псков'" << endl;
    cout << "21. Данные о тех, кто живет в г. Гжель и имеет телефон, оканчивающийся на '43'" << endl;
    cout << "22. Данные о тех, чья фамилия начинается с 'С', а телефон – с '456'" << endl;
    cout << "23. Данные о тех, чья фамилия начинается с 'М', а город – 'Киев'" << endl;
    cout << "24. Данные о тех, кто живет в Москве и имеет телефон, начинающийся на '125'" << endl;
    cout << "25. Данные о тех, чья фамилия начинается с 'Я', а телефон – с '567'" << endl;
    cout << "26. Данные о тех, чья фамилия начинается с 'Н', а город – 'Москва'" << endl;
    cout << "27. Данные о тех, кто живет в Киеве и имеет телефон, оканчивающийся на '12'" << endl;
    cout << "28. Данные о тех, чья фамилия начинается с 'А', а телефон – с '100'" << endl;
    cout << "29. Данные о тех, чья фамилия начинается с 'Б', а город – 'Львов'" << endl;
    cout << "30. Данные о тех, кто живет во Львове и имеет телефон, оканчивающийся на '00'" << endl;

    cin >> i;

    if (i > 0 && i < 31) {
        f = fopen("test.txt", "r"); // открыли файл

        while (!feof(f)) {
            fscanf(f, "%s %s %s\n", x.surname, x.city, x.tel);
            int found = 0;
//            string surname(x.surname);
//            string city(x.city);
//            string tel(x.tel);
//            string tmp(&x.surname[0]);
            switch (i) {
                case 1:
                case 16:
                    if ((x.surname[0] == 'И')&&(x.tel[0] == '9')&&(x.tel[1] == '0')&&(x.tel[2] == '5')) found = 1;
                    break;
                case 2:
                case 17:
                    if ((x.surname[0] == 'K')&&(strcmp(x.city, "Гжель") == 0)) found = 1;
                    break;
                case 3:
                case 18:
                    if ((strcmp(x.city, "Москва") == 0)&&(x.tel[9] == '6')&&(x.tel[10] == '7')) found = 1;
                    break;
                case 4:
                case 19:
                    if (x.surname[0] == 'Д' && (x.tel[0] == '3')&&(x.tel[1] == '2')&&(x.tel[2] == '1')) found = 1;
                    break;
                case 5:
                case 20:
                    if (x.surname[0] == 'Р' && (strcmp(x.city, "Псков") == 0)) found = 1;
                    break;
                case 6:
                case 21:
                    if ((strcmp(x.city, "Гжель") == 0) && (x.tel[9] == '4')&&(x.tel[10] == '3')) found = 1;
                    break;
                case 7:
                case 22:
                    if ((x.surname[0] == 'С')&&(x.tel[0] == '4')&&(x.tel[1] == '5')&&(x.tel[2] == '6')) found = 1;
                    break;
                case 8:
                case 23:
                    if ((x.surname[0] == 'М')&&(strcmp(x.tel, "Киев") == 0)) found = 1;
                    break;
                case 9:
                case 24:
                    if ((strcmp(x.city, "Москва") == 0)&&(x.tel[0] == '1')&&(x.tel[1] == '2')&&(x.tel[2] == '5')) found = 1;
                    break;
                case 10:
                case 25:
                    if ((x.surname[0] == 'Я')&&(x.tel[0] == '5')&&(x.tel[1] == '6')&&(x.tel[2] == '7')) found = 1;
                    break;
                case 11:
                case 26:
                    if ((x.surname[0] == 'Н')&&(strcmp(x.city, "Москва") == 0)) found = 1;
                    break;
                case 12:
                case 27:
                    if ((strcmp(x.city, "Киев") == 0)&&(x.tel[9] == '1')&&(x.tel[10] == '2')) found = 1;
                    break;
                case 13:
                case 28:
                    if ((x.surname[0] == 'А')&&(x.tel[0] == '1')&&(x.tel[1] == '0')&&(x.tel[2] == '0')) found = 1;
                    break;
                case 14:
                case 29:
                    if ((x.surname[0] == 'Б')&&(strcmp(x.tel, "Львов") == 0)) found = 1;
                    break;
                case 15:
                case 30:
                    if ((strcmp(x.city, "Львов") == 0)&&(x.tel[9] == '0')&&(x.tel[10] == '0')) found = 1;
                    break;
            }
            if (found == 1) {
                cout << x.surname << " " << x.city << " " << x.tel << endl;
            }
        }

        fclose(f);
    } else {
        cout << "Неизвестный индекс варианта поиска. Выход из режима поиска.";
    }
    getch();
}

int main() {
    int k;
    setlocale(LC_ALL, "Russian"); //русификация
    do {

        cout << "Выберите действие (по индексу):" << endl;
        cout << "1. Создать базу  " << endl;
        cout << "2. Просмотреть базу  " << endl;
        cout << "3. Искать в базе  " << endl;
        cout << "5. Выйти из программы" << endl;
        cin >> k;
        switch (k) {
            case 1: make_f();
                break;
            case 2: see_f();
                break;
            case 3: work_f();
                break;
        }
    } while (k != 5);

    getch();
}



Но есть проблемы. Не работает функция поиска (work_f). Как мне кажется проблемы с кодировкой и это проявляется в сравнениях c русскими символами в блоке switch функции work_f. 
Подскажите, так ли это и что нужно сделать, чтобы все заработало?

Добавлено через 2 минуты и 46 секунд
Забыл написать.
Я эту программу писал под Linux. Может в Win будет по другому.
PM MAIL   Вверх
bsa
Дата 29.5.2013, 14:13 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Модератор
Сообщений: 9185
Регистрация: 6.4.2006
Где: Москва, Россия

Репутация: 85
Всего: 196



В Linux используется кодировка UTF-8. В ней символы кириллицы занимают два байта. Таким образом, код вида x.surname[0] == 'Д' работать будет некорректно. Чтобы этого избежать необходимо использовать wchar_t вместо char. Соответственно все функции для работы со строками будут содержать букву w в названии, например: strcmp -> wcscmp. В этом случае вместо 'Д' надо писать L'Д', а вместо "Введите фамилию" - L"Введите фамилию".
PM   Вверх
Ares4322
Дата 29.5.2013, 14:19 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 339
Регистрация: 25.9.2007
Где: Россия, Москва

Репутация: нет
Всего: 3



Вот такая строка работает
Код

strcmp(x.city, "Гжель")==0

Видимо, дело не в этом.
PM MAIL   Вверх
bsa
Дата 29.5.2013, 14:46 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Модератор
Сообщений: 9185
Регистрация: 6.4.2006
Где: Москва, Россия

Репутация: 85
Всего: 196



Ares4322, strcmp работает корректно с кодировкой UTF-8.
PM   Вверх
Ares4322
Дата 29.5.2013, 14:47 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 339
Регистрация: 25.9.2007
Где: Россия, Москва

Репутация: нет
Всего: 3



Вы же сами написали 
Код

 strcmp -> wcscmp

PM MAIL   Вверх
bsa
Дата 29.5.2013, 14:50 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Модератор
Сообщений: 9185
Регистрация: 6.4.2006
Где: Москва, Россия

Репутация: 85
Всего: 196



Ares4322, strcmp не будет работать со строкой wchar_t *. Для этого и существует wcscmp. Чтобы сделать из строки char'ов строку wchar_t необходимо использовать mbstowcs(), а обратно wcstombs().

Добавлено через 1 минуту и 38 секунд
Да, забыл написать, что особенностью кодировки UTF-8 является то, что один символ может занимать от одного байта (символы ASCII) до 4-х. Именно поэтому с ней напрямую мало кто работает.
PM   Вверх
Ares4322
Дата 29.5.2013, 15:09 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 339
Регистрация: 25.9.2007
Где: Россия, Москва

Репутация: нет
Всего: 3



Спасибо за отклик. Товарищ сказал, что можно не использовать Кириллицу. Так что задача упрощается.
PM MAIL   Вверх
feodorv
Дата 29.5.2013, 15:15 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Комодератор
Сообщений: 2214
Регистрация: 30.7.2011

Репутация: 12
Всего: 45



Цитата(Ares4322 @  29.5.2013,  14:46 Найти цитируемый пост)
Как мне кажется

Но ведь можно же выдать отладочную информацию на экран. Посмотреть, что с чем сравнивается, и правильно ли сравнивается.
Что содержится в файле test.txt, кракозябры или нормальный текст?

Добавлено через 50 секунд
Цитата(Ares4322 @  29.5.2013,  16:09 Найти цитируемый пост)
Товарищ сказал

А если препод захочет кириллицу?


--------------------
Напильник, велосипед, грабли и костыли - основные инструменты программиста...
PM MAIL   Вверх
  
Ответ в темуСоздание новой темы Создание опроса
Правила форума "C/C++: Для новичков"
JackYF
bsa

Запрещается!

1. Публиковать ссылки на вскрытые компоненты

2. Обсуждать взлом компонентов и делиться вскрытыми компонентами

  • Действия модераторов можно обсудить здесь
  • С просьбами о написании курсовой, реферата и т.п. обращаться сюда
  • Вопросы по реализации алгоритмов рассматриваются здесь


Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, JackYF, bsa.

 
1 Пользователей читают эту тему (1 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | C/C++: Для новичков | Следующая тема »


 




[ Время генерации скрипта: 0.1095 ]   [ Использовано запросов: 21 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.