---
# System prepended metadata

title: hw9-3

---

# 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;
}
```