# hw9-3
{%hackmd BJrTq20hE %}
```cpp=
#include <iostream>
#include <fstream>
#include <vector>
using namespace::std;
// reads in a C++ program from a cpp file, and put it to the vector program
void load( vector< char * > &program );
// deletes the comment beginning with "//" from sourceLine if any
void delComment( char sourceLine[] );
// deletes all string constants from sourceLine
void delStrConsts( char sourceLine[] );
// deletes all character constants from sourceLine
void delCharConsts( char sourceLine[] );
// extracts all identifiers from sourceLine, and put them into the vector identifiers
void extractIdentifiers( char sourceLine[], vector< char * > &identifiers );
// stores all non-keyword strings in the vector identifiers into a text file
void store( vector< char * > &identifiers );
// returns true if and only if str is a C++ keyword
bool keyword( char str[] );
// returns true if and only if identifiers[ pos ] belongs to identifiers[ 0 .. pos-1 ]
bool duplicate( vector< char * > &identifiers, int pos );
const char keywords[][ 20 ] = { "auto", "break", "case", "char", "const",
"continue", "default", "define","do", "double",
"else", "enum", "extern", "float", "for",
"goto", "if", "int", "long", "register",
"return", "short", "signed", "sizeof",
"static", "struct", "switch", "typedef",
"union", "unsigned", "void", "volatile",
"while", "bool", "catch", "class",
"const_cast", "delete", "dynamic_cast",
"explicit", "false", "friend", "inline",
"mutable", "namespace", "new", "operator",
"private", "protected", "public",
"reinterpret_cast", "static_cast", "template",
"this", "throw", "true", "try", "typeid",
"typename", "using", "virtual", "include" };
int main()
{
vector< char * > program; //看成vector(陣列)的每一個元素都是字串,而字串的組成是由char指標往外指出來的 (二維)
//***********************用push_back來新增一格(一行程式碼)
// reads in a C++ program from a cpp file, and put it to the vector program
load( program );
vector< char * > identifiers;
for( size_t i = 0; i < program.size(); i++ )
{
delComment( program[ i ] ); // deletes the comment beginning with "//" from program[ i ]
delStrConsts( program[ i ] ); // deletes all string constants from program[ i ]
delCharConsts( program[ i ] ); // deletes all character constants from program[ i ]
if( strcmp( program[ i ], "" ) != 0 )
extractIdentifiers( program[ i ], identifiers );
// extracts all identifiers from program[ i ], and put them into the vector identifiers
}
// stores all non-keyword strings in the vector identifiers into a text file
store( identifiers );
system( "pause" );
}
void load( vector< char * > &program )
{
////////////////////
//開檔:
//ifstream inFile("C:\\Users\\mcpe9\\Desktop\\test1.cpp", ios::in);
ifstream inFile("test2.cpp", ios::in);
if (!inFile)
{
cerr << "File could not be opened" << endl;
system("pause");
exit(1);
}
else
{
//讀資料:
char* temp = new char[100]();
while (inFile.getline(temp, 100))
{
program.push_back(temp); //丟入temp存放的address,讓program也指向跟temp一樣的空間
temp = new char[100](); //指到新的空間
}
//刪最後一個空行的空間,前面累積的空間到extractIdentifiers再刪掉
delete[] temp;
}
//***關檔***
inFile.close();
////////////////////
}
void delComment( char sourceLine[] )
{
size_t length = strlen( sourceLine );
if( length > 1 )
for( size_t i = 0; i < length - 1; i++ )
if( sourceLine[ i ] == '/' && sourceLine[ i + 1 ] == '/' )
{
sourceLine[ i ] = '\0';
return;
}
}
void delStrConsts( char sourceLine[] )
{
////////////////////
size_t length = strlen(sourceLine);
if (length > 1)
{
for (size_t i = 0; i < length - 1; i++)
{
if (sourceLine[i] == '"')
{
sourceLine[i] = ' ';
i++;
while (true)
{
//發生 ex1: "Enter the string \"eat here\":"
// ex2: "\"\""
if (sourceLine[i] == '\\' && sourceLine[i + 1] == '"')
{
sourceLine[i] = ' ';
sourceLine[i + 1] = ' ';
i += 2; //***i+2***
}
else if (sourceLine[i] == '"')
{
sourceLine[i] = ' ';
i++;
break;
}
else
{
sourceLine[i] = ' ';
i++;
}
}
}
}
}
////////////////////
}
void delCharConsts( char sourceLine[] )
{
////////////////////
size_t length = strlen(sourceLine);
//刪掉字元常數 ex: 'a', '\n'
if (length > 1)
{
for (size_t i = 0; i < length - 1; i++)
{
if (sourceLine[i] == '\'')
{
sourceLine[i] = ' ';
i++;
while (true)
{
//發生 ex: s1[ 0 ] << '\'' << s1[ 1 ] => \'
if (sourceLine[i] == '\\' && sourceLine[i + 1] == '\'')
{
sourceLine[i] = ' '; //刪掉 '\'
sourceLine[i + 1] = ' '; //刪掉 '"'
i += 2;
}
else if (sourceLine[i] == '\'')
{
sourceLine[i] = ' ';
break;
}
else
{
sourceLine[i] = ' ';
i++;
}
}
}
}
}
////////////////////
}
void extractIdentifiers( char sourceLine[], vector< char * > &identifiers )
{
////////////////////////////////////////
size_t length = strlen(sourceLine);
//刪掉符號(用ASCII判斷):
if (length > 0)
{
for (size_t i = 0; i < length; i++)
{
//非數字and非英文字母
if (
!(sourceLine[i] >= '0' && sourceLine[i] <= '9') && //*** '0' ~ 9 ***
!(sourceLine[i] >= 'a' && sourceLine[i] <= 'z') &&
!(sourceLine[i] >= 'A' && sourceLine[i] <= 'Z') && //***英文大小寫***
sourceLine[i] != '_' //***為底線時不刪除***
)
{
sourceLine[i] = ' ';
}
}
}
//不為keyword則丟入identifiers空間
if (length > 1)
{
for (int i = 0; i < length; i++) //檢查一整行字元 i < 100
{
//有東西時進入 ex:cout int
if (sourceLine[i] != ' ' && sourceLine[i] != '\0') //*****每跑一次temp這個pointer會不見,所以主要透過temp把address傳給identifiers,讓它指到空間***
{ //所以主要透過temp把address傳給identifiers,讓它指到空間******
//***要寫在裡面***,以免出現空的空間,導致不會讓identifiers指向他
char* temp = new char[32](); //裡面全塞'\0'(空字元or結束字元),' '(空白字元)
int i_temp = 0;
//temp存一行的其中一個identifier
while (true)
{
temp[i_temp] = sourceLine[i];
i_temp++;
i++;
if (sourceLine[i] == ' ') //下一項
{
break;
}
}
//把剛存的temp丟入identifier
if ((!keyword(temp)) && (!(temp[0] >= '0' && temp[0] <= '9'))) //判斷不能為keyword,第一個字不能為數字
{
identifiers.push_back(temp);
//***不用補'\0'***
}
else //表示identifiers不會指向temp,到method store時會沒辦法刪掉
{
delete[] temp;
}
}
}
}
//from load:
delete[] sourceLine; //***刪掉Load的temp***
//***到了store再刪掉temp空間***
////////////////////////////////////////
}
void store( vector< char * > &identifiers )
{
////////////////////
//寫檔:
//ofstream outFile("C:\\Users\\mcpe9\\Desktop\\identifiers.txt", ios::out);
ofstream outFile("identifiers.txt", ios::out);
for (int i = 0; i < identifiers.size(); i++) //***VectorName.size()***
{
char temp[32]{};
if (!duplicate(identifiers, i)) //重複回傳true
{
outFile << identifiers[i];
outFile << endl;
}
}
//***刪空間***
//from extractIdentifiers:
for (int i = 0; i < identifiers.size(); i++)
{
delete[] identifiers[i];
}
//***關檔***
outFile.close();
////////////////////
}
bool keyword( char str[] )
{
size_t numKeywords = sizeof( keywords ) / 20;
for( size_t i = 0; i < numKeywords; i++ )
if( strcmp( keywords[ i ], str ) == 0 )
return true;
return false;
}
bool duplicate( vector< char * > &identifiers, int pos )
{
for( int i = 0; i < pos; i++ )
if( strcmp( identifiers[ i ], identifiers[ pos ] ) == 0 )
return true;
return false;
}
```