Назад | Начало урока | Вперед
Содержание

Глава 2 (продолжение 1)

Вверх

Поиск лексемы и вставка строки

Эта программа выполняет следующую задачу: построчно считывает из текстового файла, затем в строке ищет подстроку (лексему). Найдя лексему, программа вставляет перед каждой найденной лексемой новую строку. И разыскиваемая лексема и новая строка для вставки переданы программным способом (заданы программно до компиляции).

Здесь функция fun1 немного изменена в соответствии с новой задачей. Задачей этой программы было вставить в текстовый файл перед такими тегами как:"<IMG SRC=", "<A HREF=" и рядом других тегов тег "<br>".

Программа 02_02


// Example_02_02 Поиск лексемы и вставка строки
#include <fstream>
#include <string>
#include <iostream>

using namespace std;

void fun1 (string str, string str1, string &strOut, string &tmp) {

string s1;
string strOOut;
string tmpP;
int n = -2;

tmpP = tmp;

while(1 != tmpP.empty() ) {

s1 = tmpP;
n = tmpP.find(str); // найдем позицию вхождения

if(n==-1) // лексемы в строке нет {

strOOut += tmpP ;
tmpP = strOOut;
break;
}

if(n>=0) // лексема есть {

s1.erase(n, tmpP.length() ); //правее n все отсекаем
tmpP.erase(0, n ); //левее n (до лексемы) все отсекаем

strOOut += s1 ; //левая часть исходной строки(до лексемы)

strOOut += str1 ; //вставка <br>
strOOut += str ; //вставка лексемы

tmpP.erase(0, str.length() ); // отсекаем лексему

if( 1==tmpP.empty())
{

strOOut += "";
strOOut += '\n';
}

continue;

}

}//end while

tmp = tmpP;
strOut = strOOut;
}

int main( int argc,char* argv[])
{

string str = "<IMG SRC=";
string str1 = "<br>";
string str2 = "<A HREF=";
string str3 = "<BODY";
string str4 = "<FRAME SRC=";
string str5 = "<SCRIPT LANGUAGE=";
string str6 = "<MAP NAME=";
string str7 = "<AREA SHAPE";
string str8 = "</MAP";
string str9 = "<FRAMESET";
string str10 = "<H1";
string str11 = "<H2";
string str12 = "<DIV";
string str13 = "</DIV";

string tmp;
string strOut;

char fileTo[100] ="fileTo.txt";
char fileFrom[100] ="fileFrom1.txt";

ifstream from1("fileFrom.txt");//открываем файл для считывания

if(!from1)
{

cout<<"Vhodnoi fail ne naiden:" ;
return (1);
}

ofstream to1("fileTo.txt");//открываем файл для записи

if(!to1)
{

cout<<"Vyhodnoi fail ne otkryt:" ;
return (1);
}

while (!from1.eof())
{

getline(from1,tmp,'\n');//считываем построчно в строку tmp

fun1(str, str1, strOut, tmp) ;
fun1(str2, str1, strOut, tmp) ;
fun1(str3, str1, strOut, tmp) ;
fun1(str4, str1, strOut, tmp) ;
fun1(str5, str1, strOut, tmp) ;
fun1(str6, str1, strOut, tmp) ;
fun1(str7, str1, strOut, tmp) ;
fun1(str8, str1, strOut, tmp) ;
fun1(str9, str1, strOut, tmp) ;
fun1(str10, str1, strOut, tmp) ;
fun1(str11, str1, strOut, tmp) ;
fun1(str12, str1, strOut, tmp) ;
fun1(str13, str1, strOut, tmp) ;

to1 << strOut << endl;
strOut.erase(0, strOut.length());

} //end while

to1.close();
from1.close();


return 0;

}


Результат:

Эта программа откомпилирована и выполнена в 6-й версии
программы Microsoft Visual C++
Результат находится в файле fileTo.txt в рабочей директории программы.

Анализ:

Основную работу в этой программе выполняет функция fun1().

Функция имеет 4 параметра

void fun1(string str, string str1, string &strOut, string &tmp) {

Параметр str - это подстрока (лексема), которую надо отыскать в строке.
Параметр str1 - это новая строка, которую надо вставить в исходную строку.
Параметр strOut - результирующая строка, которая будет передана в результирующий файл.
Параметр tmp - исходная строка, которую надо обработать.

Объявим локальные переменные:

string s1;
string strOOut;
string tmpP;
int n = -2;

Передадим исходную строку локальной переменной:

tmpP = tmp;

while(1 != tmpP.empty() )
{

s1 = tmpP; // скопируем в s
n = tmpP.find(str); // найдем позицию вхождения

Далее если строка не пустая, и разыскиваемая лексема здесь есть,

if(n>=0) // лексема есть
{

s1.erase(n, tmpP.length() ); //правее n все отсекаем
tmpP.erase(0, n ); //левее n (до лексемы) все отсекаем

strOOut += s1 ; //левая часть исходной строки(до лексемы)
strOOut += str1 ; //вставка новой строки
strOOut += str ; //вставка лексемы

tmpP.erase(0, str.length() ); // отсекаем лексему

if( 1==tmpP.empty())
{

strOOut += "";
strOOut += '\n';
}

continue;

}

Теперь в переменной strOut записана вся левая часть исходной строки tmpP вместе с первой встретившейся лексемой, перед которой вставлена новая строка, переданная в str1.

После двух отсечений от исходной строки в tmpP остается только ее правая часть, то что было справа после первой встреченной в исходной строке лексемы. Естественно, в оставшейся части строки лексема может встретиться еще сколько угодно раз. Поэтому, благодаря continue возвращаемся на начало цикла while уже с остатком строки. И если в ней снова встречается лексема, вышерассмотренный блок if(n>=0) повторится вновь.

Наконец останется часть строки (она может быть и нулевой) без лексемы, которая будет обработана блоком:

if(n==-1) // лексемы в строке нет
{

strOOut += tmpP ;
tmpP = strOOut;
break;
}

В результирующую строку strOut копируется в режиме дополнения остаток строки.
Теперь результирующая строка содержит все вставки перед лексемами.
После этого в tmpP перезаписывается результат.

}//end while

Передаем результат в параметры, переданные по ссылке:

tmp = tmpP;
strOut = strOOut;

}

Поскольку в аргументе tmp у нас передается исходная строка, которую надо обработать,
то следующие две инструкции, скопировали в исходную строку результат работы функции.

tmpP = strOOut;
tmp = tmpP;

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

Примечание: Исполняемый exe-файл в данной программе получился примерно в два раза большего размера, чем у аналогичной программы, где использовались строки типа символьного массива в стиле С. Но зато данная программа с использованием строк типа string более удобна и безопасна при написании. Сохраняет объектный стиль в программировании.


Назад | Начало урока | Вверх | Вперед
Содержание

Hosted by uCoz