C++抽象编程——面向对象(10)——token扫描器的实现

tokenscanner.h接口

界面中的许多方法用于启用更改扫描仪默认行为的选项。例如,我们可以通过初始化像这样的token扫描器忽略输入流中的所有空格:

TokenScanner scanner;
scanner.ignoreWhitespace();

接下来我们的目的是实现下面的一些功能:

方法作用
构造函数
TokenScanner() TokenScanner(str) TokenScanner(infile)初始化扫描仪对象。 token的源码从指定的字符串或输入文件初始化。如果没有提供token源,则必须在从扫描仪读取令牌之前调用setInput
读取token的方法
hasMoreTokens()返回true,如果还有其他更多的token未被读取
nextToken()从扫描仪返回下一个token。 如果在没有token可用的情况下调用nextToken,则返回空字符串。
saveToken(token)将指定的token保存为扫描仪内部状态的一部分,以便在下次调用nextToken时返回。
控制扫描器的方法
ignoreWhitespace()告诉扫描仪扫描的时候忽略空格字符

实现简单的token扫描器

TokenScanner.h

#ifndef _TokenScanner_h
#define _TokenScanner_h

#include <string>

/*
*这个类用来处理一些分割字符串
*/
class TokenScanner{
    public:
        /*
        *构造函数: TokenScanner scanner
        *用法:TokenScanner scanner()
               TokenScanner scanner(str)
        *---------------------------
        *用途:创建一个TokenScanner对象,当其为默认构造函数的时候
        *token为空字符串,否则,这token来自于用户定义的字符串
        */ 
        TokenScanner();
        TokenScanner(std::string str); 
        /*
        *方法:setInput()
        *用法:scanner.setInput(str)
        *--------------------------
        *用途:为扫描器提供指定的string输入
        */
        void setInput(std::string str); 
        /*
        *方法:hasMoreTokens
        *用法:if(scanner.hasMoreTokens)
        *------------------------------
        *用途:判断是否还有后续的tokens
        */
        bool hasMoreTokens();
        /*
        *方法:nextToken
        *用法:token = scanner.nextToken()
        *--------------------------------
        *用途:返回下一个token的值。如果没有后续的token,那么返回空字符串
        */
        std::string nextToken();
        /*
        *方法:ignoreWhitespace
        *用法:scanner.ignoreWhitespace()
        *-----------------------------
        *用途:告诉扫描仪忽略空格字符。 默认情况下,nextToken方法像任何其
        *它标点符号一样处理空格字符(通常为空格和制tab),并将其作为单字符
        *token返回。调用:
        * scanner.ignoreWhitespace();
        *以便我们可以这样操作
        */
        void ignoreWhitespace();

        #include "tokenscannerpriv.h"
}; 

#endif

TokenScannerpriv.h

/*
*这个文件为TokenScanner类的私有部分
*/
private:
    /*实例化变量*/
    std::string buffer; //包含token的输入字符串,buffer的意思为缓存
    int cp; //token在缓存中的正确位置,cp:current position 
    bool ignoreWhitespaceFlag;//设立一个忽略空格的标志,注意这是一个变量
    /*私有方法*/
    void skipWhitespace(); //跳过空格 

TokenScanner.cpp

/*
*这个文件用于实现我们前面写的TokenScanner的功能
*/
#include <cctype>
#include <string>
#include "TokenScanner.h"
using namespace std;
/*构造函数的实现*/
TokenScanner::TokenScanner(){
    /*空函数*/ 
} 
TokenScanner::TokenScanner(string str){
    setInput(str);
}

/*setInput函数的实现*/
void TokenScanner::setInput(string str){
    buffer = str;
    cp = 0;
} 
/*
*hasMoreTokens函数的实现
*当cp在buffer的里面的时候,意味着分割尚未完成,所以返回true
*当遇到空格时候,就跳过空格
*/ 
bool TokenScanner::hasMoreTokens() {
    if (ignoreWhitespaceFlag) skipWhitespace();
    return cp < buffer.length();
}
/*
*nextToken函数的实现
*该方法通过查看由cp指示的当前字符处的字符开始。 
*如果该位置超过了字符串的结尾,则nextToken将返回空字符串。 
*如果该字符是字母数字,则nextToken会继续向前扫描,直到找到该字的结尾; 
*如果没有,则nextToken将该字符作为单字符字符串返回 
*/
string TokenScanner::nextToken() {
    if (ignoreWhitespaceFlag) skipWhitespace();
    if (cp >= buffer.length()) {
        return "";
        } else if (isalnum(buffer[cp])) {//判断是否为字母数字 
            int start = cp; //将此时开始的cp的位置赋给start
            /*当cp处于buffer内,且cp中所指的都是字母数字的时候*/ 
            while (cp < buffer.length() && isalnum(buffer[cp])) {
                cp++;
            }
        return buffer.substr(start, cp - start);//返回截取的这一段字符 
        } else {
            return string(1, buffer[cp++]);
    }
} 


/*ignoreWhitespace()函数的实现 */
void TokenScanner::ignoreWhitespace() {
    ignoreWhitespaceFlag = true;
} 

/*
*此方法是一种私有方法,因此不会导出。 
*但是,它需要在类的私有部分中声明,该部分
*包含在tokenscannerpriv.h文件中。 
*这个方法从hasMoreTokens和nextToken都调用
*/
void TokenScanner::skipWhitespace() {
    while (cp < buffer.length() && isspace(buffer[cp])) {
    cp++;
    }
}

测试文件

#include <iostream>
#include <string>
#include "TokenScanner.h"
using namespace std;
int main(){
    string line;
    getline(cin,line);
    TokenScanner scanner(line);
    for(int i = 0;i <= line.length();i++){
        string str =  scanner.nextToken();
        cout << str << endl;
    }
    return 0;
} 

测试结果

自此,面向对象暂时告一段落,以后会提到虚函数之类的

  • 1
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值