Содержание
Содержание.. 2
1. Постановка задачи. 3
2. Список ключевых слов и текст программы для анализа. 3
3. Интерфейс программы.. 4
4. Алгоритм и результаты работы программы.. 5
5. Листинг программы.. 9
Список литературы... 13
1. Постановка задачи
Задача состоит в создании программы на С++ в среде Builder Borland 6.0.
Программа обрабатывает текст программы на С++, которая хранится в виде файла кода на диске и выполняет следующие действия:
1) подсчитывание ключевых слов Си и их количества, которые используются в коде;
2) составление перечня имен простых переменных, которые используются в левой части оператора присвоения;
3) составление перечня меток программы в алфавитном порядке.
2. Список ключевых слов и текст программы для анализа
Перед созданием программы была проведена подготовительная работа по созданию списка ключевых слов Си. Это было сделано с помощью справочной системы Borland C++ Builder.
Список ключевых слов хранится в файле keywords.txt.
Список организован как одна строка текста, отдельные ключевые слова разделены знаком табуляции.
Программа может быть расширена для поиска и других ключевых слов – например, не языка Си, а спецификации С++ в С++ Builder. Для этого нужно только обновить файл ключевых слов, т.е. поменять содержание файла keywords.txt с помощью справочной системы С++. Кроме того, этот файл может иметь другое название, лишь бы он был в текстовом формате, т.е. с расширением txt.
Текст программы для анализа содержится в текстовом файле alg1.txt. Файл для анализа может иметь и другое название, необходимо лишь, чтобы он был текстовым.
3. Интерфейс программы
Программа имеет одну главную форму, которая приведена на рисунке 1.
Главное меня предлагает три пункта:
- открытие файла ключевых слов – для этого необходимо в окне программы выбрать команду ФАЙЛ, затем в браузере выбрать файл keywords.txt; тем самым произойдет подключение списка ключевых слов;
- открытие файла с текстом кода – для этого необходимо в окне программы выбрать команду ФАЙЛ, затем в браузере выбрать файл alg1.txt; тем самым произойдет подключение файла для анализа;
- собственно работа программы;
- выход из программы.
Кнопка запуска анализа кода становится активной только тогда, когда оба файла успешно открыты.
При нажатии на эту кнопку происходит анализ кода в соответствии с поставленными задачами и файлом ключевых слов.
Полученные результаты выводятся в текстовом поле Memo.
Закрыть программу можно с системной кнопки выхода в правом верхнем углу окна и с помощью пункта меню.
При закрытии главной формы программы открытые файлы автоматически закрываются.
4. Алгоритм и результаты работы программы
Программа работает с использованием строковых переменных и контейнеров типа вектор, которые позволяют хранить последовательности.
Программа выполняет работу анализа в следующей последовательности:
1. составление списка ключевых слов как вектора в оперативной памяти;
2. в тексте программы ищутся и удаляются комментарии различных видов и ненужные строковые константы, заключенные в кавычки;
3. подсчет количества различных видов ключевых слов;
4. подсчет имен переменных;
5. подсчет меток;
6. вывод полученных данных.
Так, в контрольном примере содержится следующий код программы:
#include "stlexam.h"
#pragma hdrstop
#include <vector>
#include <list>
#include <algorithm>
#include <ctype.h>
#include <string>
#include <string.h>
#include <iostream>
goto Jane;
#ifndef _RWSTD_NO_NAMESPACE
using namespace std;
#endif
class iotaGen
{
public:
iotaGen (int iv) : current(iv) { }
int operator () () { return current++; }
private:
int current;
};
//
// Illustrate the use of the fill and fill_n functions.
//
void fill_example ()
{
cout << "Illustrate fill function" << endl;
//
// Example 1, fill an array with initial values
//
char buffer[100], *bufferp = buffer;
fill (bufferp,(bufferp + 100),'\0');
fill_n (bufferp, 10, 'x');
cout << buffer << endl;
//
// Example 2, use fill to initialize a list.
//
list<string,allocator<string> > aList;
fill_n (inserter(aList, aList.begin()), 10, "empty");
copy(aList.begin(), aList.end(), ostream_iterator<string,char,char_traits<char> >(cout, " "));
cout << endl;
//
// Example 3, use fill to overwrite values in a list.
//
fill (aList.begin(), aList.end(), "full");
copy(aList.begin(), aList.end(), ostream_iterator<string,char,char_traits<char> >(cout, " "));
cout << endl;
//
// Example 4, fill in a portion of a list.
//
vector<int,allocator<int> > iVec(10);
generate (iVec.begin(), iVec.end(), iotaGen(1));
vector<int,allocator<int> >::iterator seven = find(iVec.begin(), iVec.end(), 7);
#ifndef _RWSTD_FILL_NAME_CLASH
fill(iVec.begin(), seven, 0);
#else
std_fill(iVec.begin(), seven, 0);
#endif
copy(iVec.begin(), iVec.end(), ostream_iterator<int,char,char_traits<char> >(cout));
cout << endl;
}
//
// Illustrate the use of the copy function.
//
void copy_example ()
{
cout << "Illustrate copy function " << endl;
//
// Example 1, a simple copy.
//
char * source = "reprise";
char * surpass = "surpass";
char buffer[120], *bufferp = buffer;
copy(source, source + strlen(source) + 1, bufferp);
//
// Example 2, self copies.
//
*copy(bufferp + 2, bufferp+ strlen(buffer), bufferp) = '\0';
int buflen = strlen(buffer) + 1;
copy_backward(bufferp, bufferp + buflen, bufferp + buflen + 3);
copy(surpass, surpass + 3, bufferp);
//
// Example 3, copy to output.
//
copy(bufferp, bufferp + strlen(buffer), ostream_iterator<char,char,char_traits<char> >(cout));
cout << endl;
//
// Example 4, use copy to convert type.
//
list<char,allocator<char> > char_list;
copy(bufferp, bufferp + strlen(buffer),
inserter(char_list,char_list.end()));
char * big = "big ";
copy(big, big + 4, inserter(char_list, char_list.begin()));
char buffer2[200], *buffer2p = buffer2;
*copy(char_list.begin(), char_list.end(), buffer2p) = '\0';
cout << buffer2 << endl;
}
#include <sstream>
string generateLabel ()
{
//
// Generate a label string of the form L_ddd.
//
static int lastLabel = 0;
ostringstream ost;
ost << "L_" << lastLabel++ << '\0';
return ost.str();
}
//
// Illustrate the use of the generate and genrate_n functions.
//
void generate_example ()
{
cout << "Illustrate generate algorithm" << endl;
//
// Example 1, generate a list of label numbers.
//
list<string,allocator<string> > labelList;
generate_n (inserter(labelList, labelList.begin()), 4, generateLabel);
copy(labelList.begin(),labelList.end(),ostream_iterator<string,char,char_traits<char> >(cout," "));
cout << endl;
//
// Example 2, generate an arithmetic progression.
//
vector<int,allocator<int> > iVec(10);
generate (iVec.begin(), iVec.end(), iotaGen(2));
generate_n (iVec.begin(), 5, iotaGen(7));
copy (iVec.begin(), iVec.end(), ostream_iterator<int,char,char_traits<char> >(cout, " "));
cout << endl;
}
//
// Illustrate the use of the algorithm swap_ranges.
//
void swap_example ()
{
cout << "Illustrate swap_ranges algorithm" << endl;
//
// First make two parallel sequences.
//
int data[] = {12, 27, 14, 64}, *datap = data;
vector<int,allocator<int> > aVec(4);
generate (aVec.begin(), aVec.end(), iotaGen(1));
//
// Illustrate swap and swap_itr.
//
swap(data[0], data[2]);
copy (data, data+4, ostream_iterator<int,char,char_traits<char> >(cout, " "));
cout << endl;
vector<int,allocator<int> >::iterator last = aVec.end(); last--;
iter_swap(aVec.begin(), last);
copy (aVec.begin(), aVec.end(), ostream_iterator<int,char,char_traits<char> >(cout, " "));
cout << endl;
//
// Now swap the entire sequence.
//
swap_ranges (aVec.begin(), aVec.end(), datap);
copy (data, data+4, ostream_iterator<int,char,char_traits<char> >(cout, " ")), cout << endl;
copy (aVec.begin(), aVec.end(), ostream_iterator<int,char,char_traits<char> >(cout, " "));
cout << endl;
}
int main ()
{
cout << "STL generic algorithms -- initialization algorithms" << endl;
fill_example();
copy_example();
generate_example();
swap_example();
cout << "End of initialization tests" << endl;
return 0;
}
В результате работы программы получается следующий результат:
Ниже приведен листинг программы.
5. Листинг программы
#include <vcl.h>
#pragma hdrstop
#include "MainUnit.h"
#include "functions.h"
//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma resource "*.dfm"
TFrmMain *FrmMain;
AnsiString codefilename="";
AnsiString keywordsfilename="";
//---------------------------------------------------------------------------
__fastcall TFrmMain::TFrmMain(TComponent* Owner)
: TForm(Owner)
{
}
//---------------------------------------------------------------------------
void __fastcall TFrmMain::N2Click(TObject *Sender)
{
if(odKeywords->Execute()) keywordsfilename=odKeywords->FileName;
keyfile.open(keywordsfilename.c_str(),0x0);
if (codefile.is_open()) btnGo->Enabled=true;
}
//---------------------------------------------------------------------------
void __fastcall TFrmMain::N3Click(TObject *Sender)
{
if(odCode->Execute()) codefilename=odCode->FileName;
codefile.open(codefilename.c_str(),0x0);
if (keyfile.is_open()) btnGo->Enabled=true;
}
//---------------------------------------------------------------------------
void __fastcall TFrmMain::FormClose(TObject *Sender, TCloseAction &Action)
{
codefile.close();
keyfile.close();
}
//---------------------------------------------------------------------------
void __fastcall TFrmMain::btnGoClick(TObject *Sender)
{
//Составление массива ключевых слов
CreateKeysMas();
/*for (int i=0;i<keys.size();i++)
{
mResults->Lines->Add(keys.at(i));
}*/
//Создание массива количеств встречаемости ключевых слов в коде
char c;
AnsiString code="";
while (codefile.get(c)) code+=c;
//Исключение комментариев
while(code.Pos("/*"))
{
int firstpos=code.Pos("/*");
int lastpos=code.Pos("*/");
if (firstpos<=lastpos) code.Delete(firstpos,lastpos);
}
while(code.Pos("//"))
{
int firstpos=code.Pos("//");
int lastpos=code.SubString(code.Pos("//"),code.Length()).Pos("\n")+code.Pos("//");
if (firstpos<=lastpos) code.Delete(firstpos,lastpos-firstpos);
}
while(code.Pos("\""))
{
int firstpos=code.Pos("\"");
int lastpos=code.SubString(code.Pos("\""),code.Length()).Pos("\"")+code.Pos("\"");
if (firstpos<=lastpos) code.Delete(firstpos,lastpos-firstpos);
}
//Подсчет ключевых слов
AnsiString code1=code;
for (int i=0;i<keys.size();i++)
{
while (code1.Pos(keys.at(i)))
{
keyscount.at(i)++;
code1.Delete(code1.Pos(keys.at(i)),keys.at(i).Length());
}
}
vector<AnsiString> perems;
code1=code;
//Подсчет имен переменных
while (code1.Pos("="))
{
if (code1[code1.Pos("=")+1]!='=')
{
int lastpos=code1.Pos("=")-1;
int firstpos=0;
int temppos=lastpos;
while (code1[temppos]==' ')
{
code1.Delete(temppos,1);
}
while (firstpos==0)
{
temppos--;
int tmp=0;
if (code1[temppos]=='\n' || code1[temppos]==';' || code1[temppos]==' ' || code1[temppos]=='{') firstpos=temppos+1;
}
perems.push_back(code1.SubString(firstpos,lastpos-firstpos));
code1.Delete(firstpos,lastpos+1);
}
else code1.Delete(0,code1.Pos("=="));
}
//Подсчет меток
code1=code;
vector<AnsiString> metki;
while (code1.Pos("goto"))
{
int firstpos=code1.Pos("goto");
AnsiString tmp=code1.SubString(code1.Pos("goto"),code1.Length());
int lastpos=tmp.Pos(";")+firstpos;
metki.push_back(code1.SubString(firstpos+5,lastpos-firstpos-6));
code1.Delete(firstpos,lastpos);
}
mResults->Lines->Add("Использование ключевых слов:");
for (int i=0;i<keys.size();i++)
{
if (keyscount.at(i)!=0)
{
AnsiString tmp=keys.at(i)+" - "+AnsiString(keyscount.at(i));
mResults->Lines->Add(tmp);
}
}
mResults->Lines->Add("Использованные имена переменных при присвоении:");
for (int i=0;i<perems.size();i++)
{
mResults->Lines->Add(perems.at(i));
}
mResults->Lines->Add("Использованнные метки:");
for (int i=0;i<metki.size();i++)
{
mResults->Lines->Add(metki.at(i));
}
}
//---------------------------------------------------------------------------
void __fastcall TFrmMain::N5Click(TObject *Sender)
{
FrmMain->Close();
}
//---------------------------------------------------------------------------
ДОПОЛНИТЕЛЬНЫЕ ФУКЦИИ
#include <fstream>
#include <vector>
using namespace std;
ifstream codefile;
ifstream keyfile;
vector<AnsiString> keys;
vector<int> keyscount;
void CreateKeysMas()
{
char c=' ';
AnsiString oneword="";
while (keyfile.get(c))
{
if (c!='\t') oneword+=c;
else
{
keys.push_back(oneword);
oneword="";
}
}
keyscount.resize(keys.size());
}
Список литературы
1. Романов Е.Л. Практикум по программированию на C++, Спб: Питер, 2003 г, 123 с.
2. Справочная система C++ Builder 6.0
3. Страуструп Б. Язык программирования С++. Специальное издание, М: Издательство БИНОМ, 1104 стр. 2005 г.
4. Форум cplusplus.ru.