БлогNot. getline getlin'у рознь или доля гласных в русском тексте

getline getlin'у рознь или доля гласных в русском тексте

В этой лекции о файловых потоках сказано только самое нужное и скучное, законченных примеров нет. Восполним этот пробел по итогам вчерашних занятий.

Полезная мысль обсуждения - не нужно путать std::istream::getline (которому нужен char * с известным размером буфера) с std::getline (ему достаточно string, а размер буфера явно не задаётся, для работы нужно указать #include <string>).

Возможно, в консоли русской Windows, помимо сделанной в листинге "русификации", понадобится нажать Alt+пробел, затем выбрать пункт меню Свойства, вкладку Шрифт, а на ней - шрифт Lucida Console.

1. Прочитать текстовый файл посимвольно и найти в нём процент русских гласных.

#include <iostream>
#include <fstream>
#include <string>
#include <Windows.h>
using namespace std;

int main() {
 setlocale(LC_ALL, "RUS");
 SetConsoleCP(1251); SetConsoleOutputCP(1251); //для Studio
 ifstream file; file.open("data.txt"); if (!file) return 1;
 string str;
 string vowels = "аеёиоуыэюяАЕЁИОУЫЭЮЯ";
 int all = 0, cnt = 0;
 while (1) {
  if (file.eof()) break;
  getline (file,str); //!Читаем нормально, не заботясь о длине строк!
  cout << str << endl; //!Медленно!
  int len = str.size();
  for (int i = 0; i < len; i++) {
   all++;
   string c = str.substr(i, 1);
   if (vowels.find(c) != string::npos) cnt++;
  }
 }
 cout << ((cnt+0.)/all*100.) << "%" << endl;
 cin.sync(); cin.get(); return 0;
}

Проверено на большом файле .txt в кодировке Windows-1251, а именно, "Войне и мире", взятом отсюда.

На самом деле мы считаем здесь процент символов файла, являющихся русскими гласными, так что результат будет зависеть, например, от длины строки исходного текста. Точнее было бы отказаться от класса string и считать процент гласных именно среди русских букв:

#include <iostream>
#include <fstream>
#include <string>
#include <cstring>
#include <Windows.h>
using namespace std;

bool isalpha_ru (unsigned char c) {
 return (c>=0xC0 && c<=0xFF || c==0xA8 || c==0xB8);
}

int main() {
 setlocale(LC_ALL, "RUS");
 SetConsoleCP(1251); SetConsoleOutputCP(1251); //для Studio
 ifstream file; file.open("data.txt"); if (!file) return 1;
 string str;
 const char vowels[] = "аеёиоуыэюяАЕЁИОУЫЭЮЯ";
 int all = 0, cnt = 0, len;
 unsigned char c;
 while (1) {
  if (file.eof()) break;
  getline (file,str);
  len = str.size();
  for (int i = 0; i < len; i++) {
   c=(unsigned char)str[i];
   if (isalpha_ru(c)) all++; 
   if (strchr(vowels,(int)c)) cnt++;
  }
 }
 cout << ((cnt+0.)/all*100.) << "%" << endl;
 cin.sync(); cin.get(); return 0;
}

Преобразования типов и проч. подогнаны под Studio.

Эта программа говорит, что в "Войне и мире" Л.Н. Толстого 42,47% русских букв являются гласными. У Спектатора, помнится, для множества русских текстов получалось 41,92%, но он "ё" не считал, очкарик :)

2. Прочитать файл в оперативную память. Актуально в весьма многих случаях.

#include <iostream>
#include <fstream>
using namespace std;

int main() {
 ifstream is("data.txt",ios::binary);
 if (is) {
  is.seekg(0, is.end);
  int len = is.tellg();
  is.seekg(0, is.beg);
  char *buf = new char[len];
  if (!buf) { return 1; /* No memory */ }
  is.read(buf, len);
  if (is) cout << "All read";
  else cout << "Only " << is.gcount() << " characters read";
  is.close();
  //Делаем что-то с содержимым файла в buf
  delete[] buf;
 }
 cin.sync(); cin.get(); return 0;
}

3. Вычислить контрольную сумму файла размерностью sizeof(int).

Метод вычисления - побитовое исключающее "или" над "порциями" данных размера sizeof(int). Отдельно нужно позаботиться о "хвосте" файла, остающемся, если его размер в байтах не кратен sizeof(int).

#include <iostream>
#include <fstream>
#include <cstring>
using namespace std;

int main() {
 ifstream file; file.open("data.txt", ios::in | ios::binary); if (!file) return 1;
 int sum = 0, n = 0;
 const int SIZE = sizeof(int);
 char buf[SIZE];
 while (!file.eof()) {
  file.read((char *)&buf, SIZE);
  if (file) {
   memcpy(&n,buf, SIZE);//"переделали" buf (char *) в n (int)
   sum ^= n;
  }
  else { //больше не можем прочитать - достигнут "хвост" файла
   int tail = file.gcount();
   if (tail) {
    for (int i = 1; i <= tail; i++) n |= (buf[i] << ((SIZE - i) * 8));
    sum ^= n;
    cout << tail << " byte(s) in tail" << endl;
   }
   break;
  }
 }
 cout << "Checksum=" << sum << endl;
 cin.sync(); cin.get(); return 0;
}

03.11.2016, 15:30 [6458 просмотров]


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

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