Глава 3
Например последовательность //: в начале строки обозначает первую строку программы. За этим символом следует инф с именем файла, его местонахождением и флагом, который указывает, что программу необходимо только откомпилировать (без построения исполняемого файла).
Так первая строка предыдущей программы содержит строку IWCompare.cpp , означающую, что файл IWCompare.cpp извлекается из текстового файла в каталог C03.
Последняя строка фрагмента помечается последовательностью ///:~. Если в первой строке сразу же после двоеточия следует восклицательный знак, первая и последняя строки кода не выводятся в файл (для файлов, содержащих только данные).
Возможности программы Python не ограничиваются простым извлечением кода. Если за именем файла следует маркер {Q}, то запись в make-файле настраивается на компиляцию исхожного текста программы без его компоновки в исполняемый файл (в частности так строится текстовая система в главе 2). Чтобы скомпоновать такой файл с другим исходным файлом, включите в исходный код исполняемой программы директиву {L}:
//{L} ../TestSuite/Test
В этом разделе будет представлена утилита, которая извлекает из текста книги весь код (вы можете самостоятельно просмотреть и откомпилировать примеры программ). Сохраните документ в текстовом формате (допустим в файле TICV2.txt) и введите в командной строке следующую команду:
C:> extractCode TICV2.txt /TheCode
Команда читает текстовый файл TICV2.txt и сохраняет весь программный код в подкаталогах каталога /TheCode. Дерево каталогов будет выглядеть так:
TheCode/
C0B/
C01/
C02/
C03/
C04/
C05/
C06/
C07/
C08/
C09/
C10/
C11/
TestSuite/
Файлы с исходными текстами примеров каждой главы находятся в соответствующем каталоге.
А вот и сама программа:
Вверх
Извлечение программного кода из текста
// Чтобы проверить, существует ли каталог, мы пытаемся
int main(int argc, char* argv[]) {
Назад |
Начало урока |
Вверх |
Вперед
//: C03:ExtractCode.cpp
// Извлечение программного кода из текста
#include <cassert>
#include <cstddef>
#include <cstdio>
#include <cstdlib>
#include <fstream>
#include <iostream>
#include <string>
using namespace std;
// Унаследованный нестандартный заголовочных файл С для mkdir()
#if defined (__GNUC__) || defined(__MSWERKS__)
#include <sys/stat.h>
#elif defined(__BORLANDC__) || defined(_MSC_VER)
|| defined(__DMC__)
#include <direct.h>
#else
#error Compiler not supported
#endif
// открыть в нем новый файл для вывода.
bool exists(string fname) {
if(fname[len-1] != '/' && fname[len-1] != '\\')
fname.append("/");
fname.append("000.tmp");
ofstream outf(fname.c_str());
bool existFlag = outf;
if (outf) {
remove(fname.c_str());
return existFlag;
exit(EXIT_FAILURE);
// Проверяем,существует ли входной файл
ifstream inf(argv[1]);
if(!inf) {
exit(EXIT_FAILURE);
// Проверяем наличие необязательного входного каталога
string root("./"); // По умолчанию используется текущий каталог
if(argc == 3) {
root = argv[2];
if(!exists(root)) {
exit(EXIT_FAILURE);
size_t rootLen = root.length();
if(root[rootLen-1] != '/' && root[rootLen-1] != '\\')
root.append("/");
// Построчное чтение входного файла
// с проверкой маркеров начала и конца программных блоков
string line;
bool inCode = false;
bool printDelims = true;
ofstream outf;
while (getline(inf, line)) {
exit(EXIT_FAILURE);
assert(outf);
if (printDelims)
outf << line << endl;
outf.close();
inCode = false;
printDelims = true;
++findDelim; // Чтобы пропустить '!' при следующем поиске
// Извлечение имени подкаталога (если оно есть)
size_t startOfSubdir =
line.find_first_not_of(" \t", findDelim+3);
findDelim = line.find(':', startOfSubdir);
if (findDelim == string::npos) {
exit(EXIT_FAILURE);
string subdir;
if(findDelim > startOfSubdir)
subdir = line.substr(startOfSubdir,
findDelim - startOfSubdir);
// Извлечение обязательного имени файла
size_t startOfFile = findDelim + 1;
size_t endOfFile =
line.find_first_of(" \t", startOfFile);
if(endOfFile == startOfFile) {
exit(EXIT_FAILURE);
// Все компоненты присутствуют: построение имени в fullPath
string fullPath(root);
if(subdir.length() > 0)
fullPath.append(subdir).append("/");
assert(fullPath[fullPath.length()-1] == '/');
if (!exists(fullPath))
#ifdef __GNUC__
mkdir(fullPath.c_str(), 0); // Создание подкаталога
#else
mkdir(fullPath.c_str()); // Создание подкаталога
#endif
fullPath.append(line.substr(startOfFile,
endOfFile - startOfFile));
outf.open(fullPath.c_str());
if(!outf) {
<< " for output\n";
exit(EXIT_FAILURE);
inCode = true;
cout << "Processing " << fullPath << endl;
if(printDelims)
outf << line << endl;
exit(EXIT_SUCCESS);
Содержание