C++練習 判別token類型


題目

Token的種類:

    Case1:Identifier
           底線或英文字母開頭,之後跟著英文字母或底線或數字
           Ex:int, _abc, k9999, a, cc, kfn_0, a2b, return

    Case2:Number
           一般的數字,測資不會有包含小數點的浮點數出現。
           Ex:1, 23, 284, 295, 7729...

    Case3:Special Symbol ( 以下所列出來的33種特殊符號 )
           +   -   *   /   >   <   =   %   &   |   ^   "
           '    .   ,   (   )   [   ]   {   }   !   :   ;
           ++  --   +=   <=   >=   ==   !=   &&   ||

你的程式會根據以上三種case將讀入的input做分類,接著將會根據讀入的command執行以下動作:

  1. 結束程式
  2. 印出總共多少個token
  3. 印出所有的token
  4. 印出三種case各有多少token
    Input的方式採用螢幕輸入,會輸入一段長度不定的token,用換行作為token的分隔,也就是說一行只會有一個token,並會以END_OF_FILE 這個字做結尾。你要做的事情只有讀取這些資料,並且判斷它們屬於何種token。接著會輸入數個0~3的數字,來測試互動式功能選項。

The actual input and output for running your program is something that looks like the following:
例一:

例二:

完整程式碼

#include<iostream>
#include <string>
using namespace std;

//4.
int classifier (char token[]){
    char letter= token[0];
    //測試是否為Identifier
    if( (65<=letter && letter<=90) || (97<=letter && letter<=122) || letter==95 ) return 1;
    //測試是否為Number
    else if(48<=letter && letter<=57) return 2;
    //為SpecialSymbol
    return 3;
}

int main()
{   
    //1.設定輸入的儲存變數
    char token[30];            //儲存此次單行的token
    char inputAll[100][30];    //存下所有輸入的token

    int inputNum=0;
    int num_Identifier = 0;
    int num_Number = 0;
    int num_SpecialSymbol = 0; 

    //2.在cmd輸入多個token 並且存下來直到END_OF_FILE才停止
    while(cin >> token){

        //input為END_OF_FILE時中斷輸出
        string s;
        s=token;
        if (s.compare("END_OF_FILE") == 0)  break;

        //把token紀錄在inputAll當中
        std::copy(token, token+30, inputAll[inputNum++]);

        //4.判斷輸入token類別
        if(classifier(token)==1) num_Identifier++;
        else if(classifier(token)==2) num_Number++;
        else if(classifier(token)==3) num_SpecialSymbol++;

    }

    //3.處理完之後對街按下0 1 2 3的效果
    int cmdCode;
    while(cin >> cmdCode){
        if(cmdCode==0) break;
        switch (cmdCode)
        {
        case 1:
            printf("Total number of tokens: %d\n",inputNum);
            break;
        case 2:
            for(int i=0;i<inputNum;i++){
                printf("[%s]\n",inputAll[i]);
            }
            break;
        case 3:
            printf ("Identifier: %d,Number: %d,Special Symbol: %d\n",num_Identifier,num_Number,num_SpecialSymbol);                       
            break;

        default:
            break;
        }
    }
}

解題過程

基本語法:
https://www.csie.ntu.edu.tw/~b98902112/cpp_and_algo/cpp02/user_defined_function.html

儲存token和設定各變數

觀念: array

char token[30];            //儲存此次單行的token
char inputAll[100][30];    //存下所有輸入的token

int inputNum=0;
int num_Identifier = 0;
int num_Number = 0;
int num_SpecialSymbol = 0;

輸入階段

接下來我們知道會一直輸入token 直到token值為END_OF_FILE為止
觀念:while

while(cin >> token){
        ...
    }

1.先把輸入的token從char[] --> string , 再看看是不是END_OF_FILE
觀念:string, string比較

char[]-->string:
https://asd9616132.pixnet.net/blog/post/468832115-char%E8%BD%89string-%E5%92%8C-string%E8%BD%89char
string比較:
https://shengyu7697.github.io/cpp-string-compare/

string s;
s=token;
if (s.compare("END_OF_FILE") == 0)  break;

先把token轉成string s
再用function s.compare("END_OF_FILE")判斷是否s(token)為"END_OF_FILE"
是的話結束輸入階段

2.把這的token記錄起來,紀錄在inputAll裡面
觀念: 二維矩陣

 //把token紀錄在inputAll當中
 std::copy(token, token+30, inputAll[inputNum++]);

3.以classifier function判斷輸入token為甚麼種類
觀念:if/else

if(classifier(token)==1) num_Identifier++;
else if(classifier(token)==2) num_Number++;
else if(classifier(token)==3) num_SpecialSymbol++;

4.classifier function實作
程式碼:

int classifier (char token[]){
    char letter= token[0];
    //測試是否為Identifier
    if( (65<=letter && letter<=90) || (97<=letter && letter<=122) || letter==95 ) return 1;
    //測試是否為Number
    else if(48<=letter && letter<=57) return 2;
    //為SpecialSymbol
    return 3;
}

觀念:ASCII,char型別,邏輯判斷
ASCII表:
https://tool.oschina.net/commons?type=4
我們先取每個token的第一個字母,並以char型態資料用ASCII型態判斷 (e.g. "A"=97)屬於哪種類別

char letter= token[0];

Identifier的第一個字為ASCII 65~90、97~122、95
Number為ASCII 48~57
剩下的為SpecialSymbol

//測試是否為Identifier
    if( (65<=letter && letter<=90) || (97<=letter && letter<=122) || letter==95 ) return 1;
    //測試是否為Number
    else if(48<=letter && letter<=57) return 2;
    //為SpecialSymbol
    return 3;

cmd操作階段

我們處理完了按下1 2 3 會出現的數據之後,接下來我們要將按下的數字鍵和會出現的輸出做對應,這裡我們用到switch ,並且將輸入1,2,3,0訂為變數cmdCode:
觀念: switch, while, break
完整程式碼:

int cmdCode;
    while(cin >> cmdCode){
        if(cmdCode==0) break;
        switch (cmdCode)
        {
        case 1:
            printf("Total number of tokens: %d\n",inputNum);
            break;
        case 2:
            for(int i=0;i<inputNum;i++){
                printf("[%s]\n",inputAll[i]);
            }
            break;
        case 3:
            printf ("Identifier: %d,Number: %d,Special Symbol: %d\n",num_Identifier,num_Number,num_SpecialSymbol);                       
            break;

        default:
            break;
        }
    }

case1:

case 1:
   printf("Total number of tokens: %d\n",inputNum);
   break;

前面我們在輸入token時就有使用inputNum來計數,由於是從0開始因此之後還要+1
,但是因為END_OF_FILE也會算在inputNum裡面要-1,因此inputNum直接就可以代表token總數量

觀念:printf
一般來說printf是C語法中的cmd輸出,當輸出有變數又有字串時非常實用

printf("hello world!")  //hello world

int num = 100;
printf("the number is %d",num);  //the number is 100

case2:
觀念: for

case 2:
   for(int i=0;i<inputNum;i++){
          printf("[%s]\n",inputAll[i]);
   }
   break;

以for迴圈將inputAll當中所有token列印出來

case3:

case 3:
printf ("Identifier: %d,Number: %d,Special Symbol: %d\n",num_Identifier,num_Number,num_SpecialSymbol);                       break;

把所有剛剛計數過的數字用printf呈現出來

這樣我們就完成這題啦~








你可能感興趣的文章

[SQL]Summing a column while ignoring duplicate records(row_number())

[SQL]Summing a column while ignoring duplicate records(row_number())

[ week 2 ]  打造 JaveScript 的基礎 - 基本運算 &位元運算

[ week 2 ] 打造 JaveScript 的基礎 - 基本運算 &位元運算

元件介紹-Day04 #  Props 向內層元件傳遞資料狀態

元件介紹-Day04 # Props 向內層元件傳遞資料狀態






留言討論