Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Visual_C_console.pdf
Скачиваний:
34
Добавлен:
16.05.2015
Размер:
954.14 Кб
Скачать

139

Чтение файла в матрицу

Ниже показан пример считывания текстового файла в матрицу с типом элементов char, а в файле качестве разграничителя строк используется признак конца строки ('\n'). Этот разграничитель используется по умолчанию Поскольку количество строк в текстовых файлах заранее обычно не

известно, то при вводе требуется организовать счетчик количества введенных строк. В примере в качестве такого счетчика использована переменная count.

string textline;// Для такого объявления вставить #include <string> char matr[ROW][COL];

int count = -1; // -1, поскольку сначала наращивание номера //строки, а затем запись по этому номеру, и 1-я //сторока имеет индекс 0

// Оператор цикла для чтения до конца файла записывают так: while (!inFil.eof())

{

getline(inFil, textline);

// Но этот же цикл можно оформить и так while (getline(inFil, textline)

{ // Тело цикла count++;

// Функция c_str() приписывает к строке символ конца строки strcpy (matr[count],textline.c_str());

}

Примечание: Когда в процессе записи кода программы после переменной textline записывают точку, то появляется список доступных элементов для этого класса (textline - это переменная класса string). Если такой список не появился, то возможно произошла ошибка при объявлении переменной. Иногда список не появляется из-за ошибки среды Visual С++. В последнем случае надо закрыть приложение, в папке приложения исключить файл с расшире-

140

нием .ncb. При последующем входе в среду разработки этот файл будет восстановлен.

Чтение файла в структуру

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

Когда файл содержит разнотипные данные, включая строки текста, содержащие пробелы, то становится проблематичным отделение данных относящихся к одному параметру, от данных являющимися другим полем.

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

Ниже приведен пример чтения из файла экземпляров глоссария в массив структур с использованием разграничителей. Каждый экземпляр глоссария состоит из ключевого слова (или фразы) и объяснения этого ключевого слова. Например, ключевое слово «Белый пробел», объяснение «Это клавиши ENTER, TAB и клавиша пробела, которые разделяют элементы при вводе с клавиатуры или из файла».

Обычно ключевое слово состоит из одной строки (в которую могут входить слова, разделенные пробелами), а объяснение может содержать произвольное количество строк. По этой причине желательно в каждом экземпляре глоссария сохранять количество строк объяснения (см. объявление в тексте прогораммы ниже).

В файле все элементы глоссария расположены последовательно, но количество строк объяснения переменное, поэтому требуется способ для отделения одного экземпляра глоссария от другого, а ключевого слова от объяснения. Это можно сделать, например, с помощью разграничителей, в качестве которых можно использовать символы, не применяющиеся для описания глоссария. Так в русском языке редко применяются символы: @, #, $, &, €, ¥ и т. д.

141

Выберем в качестве разграничителя экземпляров глоссария, например, символ ‘@’, а для отделения ключевого слова от объяснения символ ‘#’.

Полная программа считывания глоссария в массив структур и вывод этого массива на экран приведена ниже.

#include "stdafx.h" #include <string> #include "conio.h" #include <iostream> #include <fstream> using namespace std;

#define FNAME "Text.txt" // Файл размещен в папке проекта

#define SIZELST 100 #define SIZET 50 #define SIZEXP 20 #define COL 80 struct gloss

{

char term[SIZET];

// Строка ключевого слова

char explanation[SIZEXP][COL];

// Строки объяснения

int n;

// Фактическое количество строк объяснения

};

void remove_first_sym(char st[]); // Удаление первого символа int _tmain(int argc, _TCHAR* argv[])

{

gloss lst[SIZELST]; // Массив экземпляров глоссария

int counter = -1;// Счетчик количества экземпляров глоссария char ch; // Символ для считывания разграничителя string str; // Строка для считывания из файла ifstream incoming(FNAME, ios::in); // Открытие файла

if (!incoming) {

cout << "Нельзя открыть файл " << FNAME << endl; _getch();

return 1;

142

}

ch = incoming.rdbuf( )->sgetc( );

if (ch != '@') // Если первый символ не '@', это не глоссарий

{

cout << "\nНеправильный формат файла " << FNAME; _getch();

exit(1);

}

while (!incoming.eof ()) // Чтение глоссария до конца файла

{

//Получение и проверка первого символа файла ch = incoming.rdbuf( )->sgetc( );

if (ch == '@')

{

counter++;// Счетчик количества экземпляров глоссария lst[counter].n = -1; // Инициализация счетчика строк

//Чтение ключа до начала объяснения (начинается с '#') getline(incoming,str, '#');

//Преобразование и копирование ключа

strcpy_s(lst[counter].term,str.c_str());

// Удаление разграничителя экземпляров remove_first_sym(lst[counter].term);

}

else if (ch != '@')// После ключа первый символ не '@'

{

lst[counter].n++; // Нарастить счетчик строк объяснения getline(incoming,str, '\n'); // Читать строку объяснения

// Преобразование и копирование строки объяснения в матрицу strcpy(lst[counter].explanation[lst[counter].n],str.c_str());

}

}

// Вывод на экран глоссария for (int t = 0; t <= counter ; t++)

{

143 cout << endl << lst[t]. term ; for (int i = 0; i <= lst[t].n; i++)

cout << lst[t].explanation[i]<< endl;

}

_getch(); // Останов экрана return 0;

}

// Функция удаления первого символа (разграничителя) в строке void remove_first_sym(char st[ ])

{

char *ptr = st; while (*ptr)

{

*ptr = *(ptr + 1); ptr++;

}

}

В программе используется функция sgetc( ) для проверки символа в текущей позиции для считывания из файла. Эта функция проверяет символ в буфере считывания (rdbuf), не перемещая текущую позицию для считывания. Поэтому после считывания первой строки из нового экземпляра глоссария этот первый символ требуется из строки удалить.

Функция getline считывает строку до разграничителя (удаляя его из входного потока), но строки типа string не имеют признака конца строки, а поэтому не могут обрабатываться, как обычные строки языка С++. Для обеспечения этой совместимости применяется функция c_str, которая к прочитанной строке приписывает признак конца строки.

В языке С++ индексы массивов отсчитываются от 0. Поэтому инициализация счетчиков выполняется значением ‘-1’, и наращивание счетчиков выполняется перед записью массив. Это

Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]