БлогNot. Visual C++: кириллица в консоли и поиск кириллицы

Visual C++: кириллица в консоли и поиск кириллицы

Этот небольшой учебный пример класса (Visual Studio) иллюстрирует следующие действия:

  • простейшее консольное меню, без борландо-специфичных функций консоли из conio.h (а как всё-таки сделать по-борландовски?);
  • загрузка данных из файла в динамически сформированные массивы - свойства класса (а вообще-то, не забывайте что есть более современные методы из библиотеки <fstream>);
  • ввод и вывод кириллицы в консоли; если при первом запуске программы видите всё-таки "кракозябры" вместо русских букв, прочитайте комментарий в начале файла (как сменить шрифт консоли на Lucida Console);
  • поиск строк кириллицы без учёта регистра символов и с возможным неполным соответствием (методы find, strstr, lowercase).

Вот полный исходник примера:

//Вставьте этот файл в пустой проект Visual C++
//Если при запуске программы в консоли не видно русского текста - щёлкните по кнопке системного меню
//окна консоли, выберите пункт меню Свойства, вкладку Шрифт и установите Lucida Console.
//Файл данных data.txt закодирован в Windows-1251 (русская Windows) и находится в папке приложения,
//пример файла - внутри комментария /* ... */
/*
Велосипед 1500
коньки 900
*/
#include <conio.h>
#include <stdio.h>
#include <windows.h>
#include <locale.h>
 
class Class {
 FILE *file; //дескриптор файла с данными
 char **s; //строки данных
 int *n; //числа с данными
 int len,num; //макс.длина строки и количество строк
 int openfile (); //служебная - открыть и прочитать файл с данными
 int lowercase (char); //служебная - перевод символа в нижний регистр
 int strstr (const char *, const char *); //служебная - поиск подстроки в строке без учёта регистра символов
public:
 bool enabled; //доступность данных
 Class (); //конструктор
 ~Class (); //деструктор
 int find (char *); //поиск строки
 int find (int); //поиск числа
 char *gets(int); //получить строку с нужным номером
 inline int getlen () { return len; } //получить макс.длину строки
};

int Class::openfile() { //считает количество строк и размер строки, выделяет память, загружает данные
 len = num = 0;
 enabled = false; 
 file = fopen ("data.txt","rb");
 if (file==NULL) return 0; 
 int c;
 int kol=0;
 while (!feof(file)) {
  fread (&c,sizeof(char),1,file);
  kol++;
  if ((char)c=='\n') {
   if (kol>len) len=kol;
   kol=0;
   num++;
  }
 }
 if ((char)c!='\n') num++; //в конце не пустая строка? тогда num на 1 меньше, чем прочитали строк
 s = new char * [num];
 len++; //с "запасом" в 1 символ
 for (int i=0; i<num; i++) s[i] = new char [len];
 n = new int [num];
 fseek (file,0,SEEK_SET);
 for (int i=0; i<num; i++) {
  fscanf (file,"%s",s[i]);
  fscanf (file,"%d",&n[i]);
 }
 fclose (file);
 enabled = true; 
 return 1;
} 

Class::Class () {
 if (!openfile()) enabled = false;
}

Class::~Class () {
 int n = this->num;
 delete [] this->n;
 for (int i=n-1; i>-1; i--) delete s[i];
 delete [] s;
}

int Class::lowercase (char c) {
 const char lo[] = "abcdefqhijklmnopqrstuvwxyzабвгдеёжзийклмнопрстуфхцчшщъыьэюя";
 const char up[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZАБВГДЕЁЖЗИЙКЛМНОПРСТУФХЦЧШЩЪЫЬЭЮЯ";
 int len = strlen(up);
 for (int i=0; i<len; i++)
  if (up[i] == c) return lo[i];
 return c;
}

int Class::strstr (const char *str, const char *p) {
 int i = 0;
 while (str) {
  const char * s1 = str;
  const char* p1 = p;
  while (lowercase(*s1) == lowercase(*p1)) {
   s1++; p1++;
   if (*p1 == '\0' || *s1 == '\0') break;
  }
  if (*p1 == '\0') return i;
  if (*s1 == '\0') return -1;
  str++;
  i++;
 }
 return -1;
}

int Class::find (char *s) {
 if (!enabled) return -1;
 for (int i=0; i<num; i++) {
  int pos = strstr(this->s[i],s);
  if (pos!=-1) return i; //Только первое вхождение
 }
 return -1;
}

int Class::find (int n) {
 if (!enabled) return -1;
 for (int i=0; i<num; i++) {
  if (this->n[i]==n) return i; //Только первое вхождение
 }
 return -1;
}

char * Class::gets (int n) {
 if (n>-1 && n<num) return this->s[n];
 return NULL;
}

int main () {
 SetConsoleCP(1251);
 SetConsoleOutputCP(1251);
 setlocale(LC_ALL,"Russian");
 char ch;
 Class *c = new Class();
 if (c->enabled == NULL) {
  printf ("\nОшибка: файл data.txt не найден в папке приложения\n");
  system ("pause");
  return 1;
 }
 char *buf = new char [c->getlen()];
 do {
  system("cls");
  printf ("\n1. Найти строку\n2. Найти число\n0. Выход\n");
  ch = getch();
  int pos,n;
  switch (ch) {
   case '1': 
    printf ("\nВведите строку для поиска: ");
    fflush (stdin);
    scanf ("%s",buf);
    pos = c->find (buf);
    if (pos!=-1) printf ("\nНайдено: %s в позиции %d\n",c->gets(pos),pos+1);
    else printf ("\nНе найдено\n");
    break;
   case '2': 
    printf ("\nВведите число для поиска: ");
    fflush (stdin);
    scanf ("%d",&n);
    pos = c->find (n);
    if (pos>-1) printf ("\nНайдено: %s в позиции %d\n",c->gets(pos),pos+1);
    else printf ("\nНе найдено\n");
   break;
   case '0': 
    return 0;
   default:
   break;
  }
  system ("pause");
 } while (ch!=27);
 delete buf;
 delete c;
 return 0;
}

23.04.2015, 11:33 [10844 просмотра]


теги: c++ учебное язык studio

К этой статье пока нет комментариев, Ваш будет первым