15.4 解析输入

最后更新于:2022-04-01 06:25:03

在1.4节,我们把“解析”定义为分析自然语言句子或形式语言语句之结构的过程。比如,编译器在将代码翻译成机器语言程序之前必须先进行解析。 此外,当你从文件或键盘读取输入时,一般也需要进行解析,以提取想要的信息并发现错误。 例如,我有一个文件distances,其中包含了美国主要城市之间的距离信息。这些信息是我从一个随机选择的网页([http://www.jaring.my/usiskl/usa/distance.html](http://www.jaring.my/usiskl/usa/distance.html))中得到的,所以数据可能不是很准确,不过这也没什么关系。文件格式看起来是这样的: ~~~ "Atlanta" "Chicago" 700 "Atlanta" "Boston" 1100 "Atlanta" "Chicago" 700 "Atlanta" "Dallas" 800 "Atlanta" "Denver" 1450 "Atlanta" "Detroit" 750 "Atlanta" "Orlando" 400 ~~~ 文件中的每一行包含了两个城市的名字以及它们之间的距离,其中城市名用引号标记,距离以英里为单位。引号是有用的,因为它能让我们很容易地处理多于一个单词的城市名,如”San Francisco“(旧金山)。 通过搜索一行输入中的引号,我们能找到每个城市在该行的开始和结束位置。不过查找引号这样的特殊字符可能让人有点困惑,因为引号是C++中用于标识字符串的特殊字符。 要找到引号第一次出现的位置,应该这样写: ~~~ int index = line.find (’\"’); ~~~ 参数看起来有点乱,不过它就是表示双引号字符。最外层的单引号依然用于表示这是个字符值。反斜杠(\)说明我们想使用下一个字符的字面意义。 所以序列 \" 表示双引号,而序列 \’表示单引号。有趣的是, 序列\\表示一个反斜杠。第一个反斜杠指示我们要认真对待第二个反斜杠。 解析输入行由这几部分组成:找到每个城市名在该行中的开始和结束位置,使用substr函数提取城市和距离信息。substr是apstring的成员函数之一,它有两个参数,分别是子串的起始位置和长度。 ~~~ void processLine (const apstring& line) { // 我们要查找的字符是引号 char quote = ’\"’; // 将引号的索引保存在一个向量中 apvector<int> quoteIndex (4); // 使用内置的find函数查找到第一个引号 quoteIndex[0] = line.find (quote); // 使用第7章定义的find函数查找其他引号 for (int i=1; i<4; i++) { quoteIndex[i] = find (line, quote, quoteIndex[i-1]+1); } // 将一行的内容分割成子串 int len1 = quoteIndex[1] - quoteIndex[0] - 1; apstring city1 = line.substr (quoteIndex[0]+1, len1); int len2 = quoteIndex[3] - quoteIndex[2] - 1; apstring city2 = line.substr (quoteIndex[2]+1, len2); int len3 = line.length() - quoteIndex[2] - 1; apstring distString = line.substr (quoteIndex[3]+1, len3); // 输出提取的信息 cout << city1 << "\t" << city2 << "\t" << distString << endl; } ~~~ 当然,我们真正想要的并不仅仅是提取并显示信息,不过这是一个好的开始。
';