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;
}
测试结果
自此,面向对象暂时告一段落,以后会提到虚函数之类的