Ломается программа при вводе con

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

#include <iostream>
#include <fstream>

using namespace std;

char ruski[][32] = { "АБВГДЕЁЖЗИЙКЛМНОПРСТУФХЦЧШЩЫЭЮЯ", "абвгдеёжзийклмнопрстуфхцчшщыэюя" };
char eng[][5] = { "A", "B", "V", "G", "D", "E", "E", "ZH", "Z", "I", "Y", "K", "L", "M", "N", "O", "P", "R", "S", "T", "U", "F", "KH", "TS", "CH", "SH", "SHCH", "Y", "E", "YU", "YA" };
char ruski1[] = "ЪъЬь";

int srch(char* s, char ch)
{
    int i = 0;
    while (s[i] != '\0')
    {
        if (s[i] == ch)
        {
            return i;
        }
        i++;
    }
    return -1;
}

int main()
{
    setlocale(LC_ALL, "Rus");
    char fname[100];
    cout << "Укажите файл, пожалуйста: ";
    cin.getline(fname, 100);
    ifstream sr(fname);
    if (!sr.is_open())
    {
        cout << "\nТакого файла нету\n\n";
    }
    else
    {
        ofstream sw("res.txt");
        if (!sw.is_open())
        {
            cout << "\nНе создаётся файл\n\n";
        }
        else
        {
            int k;
            char ch;
            while (!sr.eof())
            {
                sr.get(ch);
                if (sr.eof())
                {
                    break;
                }
                k = srch(ruski[0], ch);
                if (k < 0)
                {
                    k = srch(ruski[1], ch);
                }
                if (k >= 0)
                {
                    cout << eng[k];
                    sw << eng[k];
                }
                else
                {
                    if (srch(ruski1, ch) < 0)
                    {
                        cout << ch;
                        sw << ch;
                    }
                }
            }
            cout << "\nВсё\nНу и результат записан в \"res.txt\"\n\n";
            sw.close();
        }
        sr.close();
    }
    cin.get();
    return 0;
    system("pause");
}

Ответы (1 шт):

Автор решения: TheRyuTeam

Проблемы:

  1. Русский символ != 1 байт, т.е длинна русского алфавита (без ь, Ъ) в char будет 63.
  2. Все зависит от кодировки файла, который читаешь (например, при utf-8 у меня первый символ = 208, т.е в данной кодировке файла кириллица кодируется ДВУМЯ байтами, если файл в Windows-1251 - символ = 192). Т.е Ваш вариант поиска не работает с utf-8!
  3. Так же кодировка исходника должна совпадать с кодировкой читаемого файла. Например - файл для чтения в Windows-1251, а исходник в utf-8 - поиск НЕ СРАБОТАЕТ!

Варианты решения:

  1. Условливаемся, что кодировка входного файла - какая-то конкретная(например utf-8)
  2. Используя эту статью анализируем данные, определяем кодировку файла, работаем с определенной кодировкой

Как сделал я:

Выставил кодировку входного файла в utf-8. Запустил этот код под отладкой:

#include <iostream>
#include <fstream>

using namespace std;

const char russianUpper[] = "АБВГДЕЁЖЗИЙКЛМНОПРСТУФХЦЧШЩЫЭЮЯ"; 
const char russianLower[] = "абвгдеёжзийклмнопрстуфхцчшщыэюя";

const char englishAnalogue[][5] = {
    "A", "B", "V", "G", "D", "E", "E", "ZH", "Z", "I", "Y", "K", "L", "M", "N", "O",
    "P", "R", "S", "T", "U", "F", "KH", "TS", "CH", "SH", "SHCH", "Y", "E", "YU", "YA"
};


int srch(const char* s, char fb, char sb)
{
    for (int i = 0; s[i + 1] != '\0'; i += 2)
    {
        if (s[i] == fb && s[i + 1] == sb)
            return i / 2;
    }

    return -1;
}

int main()
{
    setlocale(LC_ALL, "Rus");
    char fname[100];
    cout << "Укажите файл, пожалуйста: ";
    cout.flush();
    cin.getline(fname, 100);
    ifstream sr(fname);
    if (!sr.is_open())
    {
        cout << "Can not open \"" << fname << "\".";
        return -1;
    }

    ofstream sw("res.txt");
    if (!sw.is_open())
    {
        cout << "Can not create output file.\n";
        return -2;
    }

    while (true)
    {
        const char ch = sr.get();
        if (sr.eof())
            break;

        // If first byte is russian first byte (utf-8 only)
        if (ch == -48 || ch == -49)
        {
            // Russian second byte
            const char sch = sr.get();

            int k = srch(russianUpper, ch, sch);
            if (k < 0)
                k = srch(russianLower, ch, sch);

            if (k >= 0)
            {
                cout << englishAnalogue[k];
                sw << englishAnalogue[k];
            }
        }
        else
        {
            cout << ch;
            sw << ch;
        }
        
    }
    sw.close();
    
    sr.close();

    cout << "\nJobs done!\nResult is in \"res.txt\".\n";


    return 0;
}

Как это работает: зная, что кириллица в utf-8 занимает 2 байта и первый байт - гарантированно 208 или 209, смотрим первый байт - если русский - читаем второй и ищем в алфавите, иначе просто выводим.

→ Ссылка