Этот пример иллюстрирует использование матрицы, размеры которой определяются в процессе выполнения программы. Размеры матрицы считываются из файла, хотя это необязательно. Размеры матрицы можно определить, подсчитав количество чисел в первой строке и количество строк (если каждая строка матрицы записана как одна строка файла).
#include<iostream>
#include<iomanip>
#include<math.h>
#include<conio.h>
#include<String.h>
#include<ctype.h>
#include <stdlib.h>
#include<windows.h>
#include <fstream> // Этот файл обеспечивает работу с файлами
using namespace std; //!!! Используем стандартное пространство имён
// функция перестановки значений двух величин
void swap(float& a, float& b)
{
float tmp;
tmp=a; a=b; b=tmp;
}
int main()
{
if(SetConsoleCP(1251)==0)
{
cerr<<"Fialed to set codepage!"<<endl;
}
if(SetConsoleOutputCP(1251)==0)
{
cerr<<"Failed to set OUTPUT page!"<<endl;
}
// Объявляем файлы:
ifstream inf("test.txt");
ofstream outf("sort.txt");
int m,n; // Количество строк и столбцов
register int i,j;
// счетчики (пример использования регистровых переменных)
inf >> m >> n;
/* считываем из файла размеры матрицы, которые должны быть записаны в начале файла */
float *vek, **mat;
/* Указатель на матрицу как на линейный массив и указатель на массив указателей для обращения к элементам массива как к элементам матрицы. Элементы массива объявлены как числа, которые могут иметь дробную часть */
vek=new float[m*n]; // выделяем место под элементы матрицы
mat=new float*[m];
// выделяем место под массив указателей на строки матрицы
for (i=0; i<m; i++) // заполняем массив указателями
mat[i]= &vek[i*n]; // деление на строки матрицы
printf("Исходная матрица:\r\n");
// чтение элементов из файла
for (i=0; i<m; i++)
{
for(j=0; j<n; j++)
{
inf>>mat[i][j];
// считываем элемент как слово и записываем в матрицу
if (inf.eof())
// если достигнут конец файла, а матрица еще не заполнена
{
printf("Не хватает данных\r\n");
_getch();
exit(0);
}
printf("%10.2f",mat[i][j]); // вывод элемента на экран
}
printf("\r\n"); // перевод курсора в начало следующей строки
}
// Сортировка по столбцам методом пузырька:
for (j=0; j<n; j++) // проходим по столбцам
for (int p=1; p<m; p++) // отсчитываем проходы по столбцу
for (i=0; i<m-p; i++)
// сравниваем соседние элементы в столбце
if (mat[i][j]>mat[i+1][j])
swap (mat[i][j],mat[i+1][j]);
// и, если нужно, переставляем их
// Запись в файл и вывод на экран полученной матрицы:
cout << "Отсортированная по столбцам: \n";
for (i=0; i<m; i++)
{
for(j=0; j<n; j++)
{
// запись элемента в файл:
outf <<setiosflags(ios::showpoint)<< setprecision(2)<<setw(10)<<mat[i][j];
// вывод на экран:
cout <<setiosflags(ios::showpoint) << setprecision(2)<< setw(10)<<mat[i][j];
// каждый элемент записывается с двумя цифрами после точки в поле из 8 позиций
}
outf<<endl;
// в конце строки матрицы выводим признак конца строки
cout << endl;
}
outf.close();
delete []mat;
delete []vek;
_getch();
return 0;
}
6. Программа, сортирующая файл по длине строки методом быстрой сортировки.
Программа запоминает в массиве длины строк, считанных из файла, и их позиции в файле (использование такого массива позволит не переписывать весь файл в оперативную память), затем массив сортируется по возрастанию длины строк. В результате мы получим начальные позиции строк в такой последовательности, какая нам нужна. Используя позиционирование, прочитаем строки в нужном порядке и запишем их в результирующий файл.
#include<iostream>
#include<iomanip>
#include<math.h>
#include<conio.h>
#include<String.h>
#include<ctype.h>
#include <stdlib.h>
#include<fstream>
#include<windows.h>
using namespace std;
// структура, соответствующая одной строке файла:
struct stroka
{
long pos; // позиция, с которой начинается строка в файле
int len; // длина строки
};
// пример оформления шаблонной функции:
template <class Type> void swapq(Type &a, Type &b)
/* в данной программе эта функция будет переставлять структуры (записи о каждой строке файла)*/
{
Type tmp;
tmp=a; a=b; b=tmp;
}
// функция быстрой сортировки:
void qusort(stroka *mas, int left, int right)
{
/*параметры: указатель на массив и индексы, определяющие ту часть массива, в которой в данный момент выполняется сортировка */
register int i,j; // индексы элементов
int x;
i=left; j=right;
x=mas[(left+right) / 2].len; // Берем средний элемент в массиве
do // этот цикл будет сравнивать длины строк
{
while(mas[i].len < x && i < right) i++;
// Находим элемент, который должен стоять правее X
while(mas[j].len > x && j > left) j--;
// Находим элемент, который должен стоять левее X
if (i <= j)
{
// и меняем их местами:
swapq<stroka>(mas[i], mas [j]);
i++; j--;
}
} while (i <= j);
/*В результате получили 2 части массива: в одной все элементы меньше X, в другой – больше */
/* Рекурсивный вызов функции сортировки для двух полученных частей массива: */
if (left < j) qusort(mas, left, j);
if (i < right) qusort(mas, i, right);
}
int main()
{
if(SetConsoleCP(1251)==0)
{
cerr<<"Fialed to set codepage!"<<endl;
}
if(SetConsoleOutputCP(1251)==0)
{
cerr<<"Failed to set OUTPUT page!"<<endl;
}
// Объявляем файлы:
ifstream inf;
char *name=new char[81]; // имя файла
do // повторение ввода имени файла
{
cout<<"Введите имя файла или нажмите <Esc>";
cout<<" для прекращения работы программы ";
name[0]=_getche(); // считываем первый символ
if (name[0]==27) exit(0);
// Если нажата клавиша <Esc>, прерываем выполнение программы
cin.getline(&name[1],80);
// считываем остальные символы имени
inf.open(name); // открываем файл
if (!inf)
cout<<"Файл не найден! \n";
} while(!inf); /* повторяем ввод, пока имя файла не будет введено правильно */
/* этот цикл стоит рассматривать не как руководство к действию, а скорее как пример возможных вариантов манипуляций со строками */
fstream outf("rez.txt",ios::out);
// файл для записи отсортированного текста
char *str=new char[102]; // строка для чтения файла
char *beg=str; // указатель на начало строки
// Определяем количество строк в файле:
int kol=0;
while (!inf.eof())
{
inf.getline(str,102);
kol++;
}
// Создаем массив записей о строках:
stroka *mas = new stroka[kol];
inf.clear();
inf.seekg(0l,ios::beg);
mas[0].pos=0; // позиция первой строки
int l; // длина очередной считываемой строки
// считываем текст построчно:
for (int i = 0; i < kol; i++)
{
str = beg;
/* мы будем изменять значение str, но для каждой новой строки указатель str опять будет хранить адрес начала области памяти, выделенной для строки */
inf.getline(str,102); // считываем строку
l=strlen(str);
if (i < kol-1) // если мы считываем не последнюю строку
{
mas[i+1].pos=inf.tellg();
// запоминаем текущую позицию как начало следующей строки
while (*str == ' ' || *str == 9)
{
str++;
mas[i].pos++;
} // обрезали пробелы и знаки табуляции в начале строки
}
mas[i].len = strlen(str);
// запомнили длину получившейся строки
}
// Сортируем массив по длине строк:
qusort(mas,0,kol-1);
// считываем текст, используя позиции, хранящиеся в массиве:
inf.clear();
for (int i = 0; i < kol; i++)
{
if (inf.eof()) inf.clear();
// если считана последняя строка в файле
inf.seekg(mas[i].pos, ios::beg);
inf.getline(str,102); // считываем нужную строку
if (*str) outf<<str<<endl;
// и записываем ее в результирующий файл
}
outf.close();
cout<<"Смотрите результат работы программы в файле \"rez.txt\"";
_getch();
return 0;
}