Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
МетодичкаФИН kosh.doc
Скачиваний:
29
Добавлен:
15.02.2016
Размер:
3.16 Mб
Скачать

Практическое занятие №6 Тема: «Диалоговое приложение для работы с файлами»

6.1. Приложение, которое считывает файл посимвольно и делает ширину текста равной заданному количеству символов в строке.

Создайте диалоговое приложение и спроектируйте его как показано на рисунке. Над нижним окном редактирования вставьте элемент Static Text, в свойствах этого элемента в поле ID задайте идентификатор IDC_STATIC1, в поле Caption уберите надпись.

Нижнее окно редактирования (большое) мы будем использовать для вы­вода текста прочитанного файла, поэтому окно должно быть многостроч­ным и с полосами прокрутки.

Установите следующие свойства для этого окна:

Auto HScroll | false

Autu VScroll | true

Horizontal Scroll | true

Vertical Scroll | true

Multiline | true

Свяжите переменные с окнами как показано ниже.

IDC_EDIT1

int width

IDC_STATIC1

CStatic statictext

IDC_EDIT2

CString text

В класс, описывающий диалоговое окно, добавьте объявления пере­мен­ных:

CStdioFile file; // объект для работы с файлом

char* Filter; // указатель на фильтр для окна типа CFileDialog

CString name1, name2; // имена исходного и результирующего файлов

Добавьте функцию для кнопки <Открыть файл> и вставьте в нее код, показанный ниже.

void CFileSymDlg::OnBnClickedButton1()

{

UpdateData();

char str[2]; str[1] = '\0'; // буфер для чтения символов из файла

text.Empty();

static char szFilter[] =

" Text Files (*.txt; *.dat)|*.txt; *.dat | \

Header Files (*.h) | *.h| Source Files (*.cpp) | *.cpp | \

All Files (*.*) |*.*||";

Filter = szFilter;

// Объект для окна, с помощью которого выбирают исходный файл:

CFileDialog dlgf(true, "", "*.txt; *.dat", OFN_EXPLORER, Filter);

if (dlgf.DoModal() == IDOK) // если файл выбран

{

name1 = dlgf.GetPathName();// считываемего имя

// Если уже есть открытый файл, закрываем его:

if (file.m_pStream) file.Close();

// Открываем файл:

if(file.Open(name1,CFile::modeRead))

{

while (file.Read(str, 1))

// пока файл не закончен, считываем один символ из него

{

if (str[0] == '\n') text += '\r';

// при выводе текста в окно Edit строки должны заканчиваться знаками “\r\n”

text += CString(str);

// собираем из символов текст файла

}

UpdateData(false);

statictext.SetWindowText("Текст файла");

}

else

statictext.SetWindowText("Файл не найден");

}

}

Добавьте функцию для кнопки <ОK> и вставьте в нее код, пока­зан­ный ниже.

void CFileSymDlg::OnBnClickedOk()

/* При нажатии на кнопку <OK> количество символов в строке становится не больше заданного числа width */

{

UpdateData();

if (file.m_pStream) // если файл открыт

{

CFileDialog dlgf(false, "txt", "new.txt", OFN_EXPLORER, Filter);

// Объект, который соответствует окну для выбора имени файла для записи

if (dlgf.DoModal() == IDOK) // если имя выбрано,

{

name2 = dlgf.GetPathName(); // считываем его из окна

CStdioFile rez; // файл для записи результата

unsigned char str[2]; str[1] = '\0';

// буфер для работы с символами

if (name1 != name2)

// имена исходного и результирующего файлов должны отличаться

{

rez.Open(name2,CFile::modeCreate|CFile::modeWrite);

// открываем результирующий файл

file.SeekToBegin(); // переходим в начало файла

int counter = 0;

// кол-во символов, записанных в очередную строку файла

CString slovo;

// текст в новый файл переписываем словами

int scount = 0; // счетчик слов в строке файла

bool endline = false;

// признак перехода через окончание строки

while(file.Read(str,1)) // считываем один символ из файла

{

if (isspace(str[0]))

// если это пробельный символ (или окончание строки)

{

int L = slovo.GetLength();

// определяем длину последнего прочитанного слова

if (counter + L > width)

// если текущее слово в строку уже не уместится, переходим на новую строку

{ rez.Write("\n",1); counter = 0; scount = 0;}

if (!slovo.IsEmpty()) // если слово - не пустое

{

if (endline && scount)

/* если в исходном файле происходит переход на новую строку и в реультирующей строке уже есть слово */

{ rez.Write(" ",1); counter++; endline = false;}

// записываем пробел

rez.WriteString(slovo); scount++; // записываем слово

counter += slovo.GetLength();

// увеличиваем соответственно счетчик символов

slovo.Empty();

}

if (str[0] != '\n') // если просто пробельный символ

{

rez.Write(str,1); counter++; //записываем его в файл

if (counter == width) // если достигли заданной длины строки

{ rez.Write("\n",1); counter = 0; scount = 0;}

//завершаем ее

else endline = true;

// отмечаем, что в исходном файле встретился признак конца строки

}

else // если прочитан не пробельный символ,

{

slovo += str[0]; // добавляем его к слову

/* нижеследующие строки обрабатывают ситуацию, когда длина слова больше заданной длины строки: */

if (slovo.GetLength() == width)

// если количество символов, записанных как слово, равно заданной длине

{

if (counter) rez.Write("\n",1);

// и в текущей строке уже есть символы, переходим на новую строку

rez.WriteString(slovo+="\n");

// записываем часть слова как строку файла

counter = 0; scount = 0; slovo.Empty();

}

} // окончание обработки непробельного символа

} // окночание цикла чтения файла

rez.Write("\n",1); //записываем признак окончания строки

rez.Close(); // новый файл нужно обязательно закрыть

statictext.SetWindowText("текст нового файла:");

text.Empty();

rez.Open(name2, CFile::modeRead);

while(rez.Read(str,1))

{

if (str[0] == '\n') text += '\r';

text += CString(str);

}

rez.Close();

UpdateData(false);

}

else MessageBox("Задайте другое имя");

}

else MessageBox("Задайте имя файла для записи результата");

}

else statictext.SetWindowTextA("Откройте файл");

}

В конструкторе задайте ширину текста по умолчанию (больше нуля):

C…Dlg::C…Dlg(CWnd* pParent /*=NULL*/)

: CDialog(CFileSymDlg::IDD, pParent)

, text(_T(""))

, width(1)

{

m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);

}

Запустите программу, откройте какой-нибудь текстовый файл и нажмите кнопку <OK>. Проверьте работу приложения для разных значений ширины текста. Количество пробелов и знаков табуляции, содержащихся в тексте, не изменяется, это может влиять на вид полученного текста. Следует иметь в виду, что ширина символов различна, поэтому визуально граница текста не будет ровной. Чтобы сделать границу ровной, следует выравнивать текст, создавая строки и определяя их ширину в точках. Кроме того, поскольку текст мы переписываем словами, длина строки зачастую меньше заданной; выровнять текст можно вставляя пробелы между словами.