Работа с потоками ввода-вывода, буфером и указателями, страница 2

  // Считываем строчку, конец которой определяется кодом перевода строки '\n'. Максимальный размер указываем как второй параметр

  cin.getline (buf, gMaxLen, '\n');

  fs << buf << endl; //Сбрасываем буфер в поток вывода, связанный с файлом

}

fs.flush();    // Необходимо вызвать для окончательной записи в файл. Ее задача поместить содержимое внутреннего буфера в файл

}

// Эта функция подсчитывает число значимых символов в файле (т.е. за исключением служебных, пробелов etc.)

// а также количество слов и помещает эти занчения в параметры length и nWords

void GetLengthAndWords (fstream& fs, int& length, int& nWords)

{

length = 0; nWords = -1; // Устанавливаем начальные значения (nWords = -1 будет свидетельствовать об ошибке)

char buf[gMaxLen + 1]; // Организуем буфер

fs.clear(); // Сбрасываем указатель файла (обязательное действие см. MSDN Q146445)

fs.seekg (0, ios::beg); // Позиционируем указатель на начало файла

for (; !fs.eof(); nWords++) // Организуем цикл от начала файла и до конца, считаем число слов...

{

  fs >> buf;

  length += (int)strlen(buf); //...и число символов

}

}

// Эта функция заполняет буфер buffer содержимым файла fs и устанавливает указатели pointers на начала слов

// таким образом буфер представляется одномерным непрерывным массивом слов без каких-либо

// разделяющих символов, символов перевода каретки и пр.

void PopulateBuffer (fstream& fs, char buf[], char* pointers[])

{

fs.clear(); // Сбрасываем указатель файла (обязательное действие см. MSDN Q146445)

fs.seekg(0, ios::beg);

for ( ; !fs.eof(); pointers++)

{

  fs >> buf; // Считываем одно слово в буфер

  *pointers = buf; // Устанавливаем указатель на начало буфера

  buf += strlen (buf); // Сдвигаем начало буфера на длину слова

}

*buf = 0; // Устанавливаем конец буфера

*pointers = 0; // Устанавливаем конец массива указателей

}

void ShowPointersById (char* pointers[], int id) // Вспомогательная функция, выводящая слово по индексу

{

if (pointers[id] && pointers[id+1]) // Длину слова определяем вычитая указатели

  cout.write( pointers[id], pointers[id+1] - pointers[id]);// Выводим столько, сколько надо

}

void ShowWords (char* pointers[], int count) // Выводим count слов на экран

{

cout<<"\n\nWords:\n\n";

for (int i=0;  i<count;  i++)

{

   cout<<'\n'<<i+1<<".\t";

   ShowPointersById (pointers, i);     

}

}

//====== Вывод count слов в порядке определяемом массивом order

void PrintPointersByOrder(char* pointers[], int order[], int count)

{

cout<<"\n\nOrdered Words:\n\n";

for (int i=0; i<count; i++)

{

  cout<<'\n'<<i+1<<".\t";

  ShowPointersById (pointers, order[i]);

}

}

int StringCompare (char* p[], int i1, int i2)

{

char *p1 = p[i1], *p2 = p[i2];

int n1 = p[i1 + 1] - p1,

  n2 = p[i2 + 1] - p2,

  i = 0;

for ( ;  i<n1 && i<n2 && p1[i] == p2[i]; i++)

  ;

if (i < n1 && i<n2)

  return p1[i] < p2[i] ? -1 : p1[i] > p2[i] ? 1 : 0;

else

  return i < n1 ? 1 : i < n2 ? -1 : 0;

}

//========= Сортируем массив order, так, чтобы слова на которые указываю pointers оказались в алфавитном порядке

void SortOrderAlpha (char* pointers[], int order[], int count)

{

for (int i=0; i<count-1; i++) // Организуем цикл до предпоследнего слова

{

  int id1 = order[i],  // текущий индекс

   id2 = order[i+1];   // следующий индекс

  if (StringCompare (pointers, id1, id2) > 0) //Сравниваем слова...

  {

   order[i] = id2; //...и если надо упорядочиваем...

   order[i+1] = id1;

   i = -1; //...не забывая сбросить счетчик.

  }

}

}

void main ()

{

cout<<"Enter a text file name, please: "; // Запрашиваем имя файла

char filename[20]; // Организуем буфер для хранения

cin>>filename;    // Считываем имя файла

fstream* fs  = new fstream (filename, ios_base::in); // Открываем файловый поток

if (!*fs) // Если неудачно - пытаемся создать новый

{

  fs = new fstream (filename, ios_base::out);

  if (!*fs)

   return;

  ReadTextAndSave (*fs); // Вызываем функцию ввода и записи в файл. Ее пропускаем, если открыт существующий файл

  fs->close();

  fs->open (filename);

}

int length, nWords; // Переменные для хранения числа символов (длины буфера) и числа слов

GetLengthAndWords (*fs, length, nWords); // Определяем длину буфера и число слов

char* buffer = new char[length+1];

char** pointers = new char*[nWords+2]; // Создаем массив указателей на слова

int* order = new int[nWords]; // Создаем массив для упорядочивания слов

PopulateBuffer (*fs, buffer, pointers); // Заполянем буфер и массив указателей

ShowWords (pointers, nWords);

for (int i=0; i<nWords; i++) // Заполняем массив для упорядочивания слов

  order[i] = nWords - i - 1;

SortOrderAlpha (pointers, order, nWords); // Сортируем слова

PrintPointersByOrder (pointers, order, nWords); // Выводим слова на экран

fs->close(); //Закрываем файловый поток

delete [] buffer; // Очищаем память

delete [] pointers;

delete [] order;

delete fs;

cout<<"\n\n";

}

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