C++语言的getline在cl和g++中的不同语义

15 篇文章 0 订阅
13 篇文章 0 订阅

本文的cl指的是Visual studio 2010中的的C++语言编译器,g++指的是g++ 4.9编译器。getline在cl中指的是获取的一行中没带”\n”;而g++中的getline指的是获取的一行中带”\n”。下面详述我为什么注意到这个问题及测试不同平台的代码。

1 问题产生

我按照书《C++ Primer》1中11.3.6节中a word transformation map程序时发现运行结果不对,我采用的是g++ 4.9.2编译器。代码如下:

// A word transformation map
#include <map>
#include <string>
#include <fstream>
#include <sstream>
#include <iostream>

using namespace std;

map<string, string> buildMap(ifstream &map_file){
    map<string,string> trans_map; // holds the transformations
    string key;
    string value; //phrase to use instead
    // read the first word into key and the rest of the line into value
    while(map_file >> key && getline(map_file,value)) {
        if(value.size() >1) // check that there is a transformation
            trans_map[key] = value.substr(1); // skip leading space
        else
            throw runtime_error("no rule for" + key);
    }
    return trans_map;
}

const string& transform(const string &s, const map<string, string> &m) {
    // the actual map work; this part is the heart of the program
    auto map_it = m.find(s);
    //if this word is in the transformation map
    if(map_it != m.cend()) {
        return map_it->second;
    } else
        return s;
}

void word_transform(ifstream &map_file, ifstream &input) {
    auto trans_map = buildMap(map_file);
    string text;
    while(getline(input,text)){ // read a line of inpu
        istringstream stream(text);
        string word;
        bool firstword = true;
        while(stream >> word) {
            if(firstword)
                firstword = false;
            else 
                cout << " ";
            cout << transform(word,trans_map);
        }
        cout << endl;
    }
}

int main() {
    ifstream in("wordTrans.txt");
    ifstream inputfile("wordTransInput.txt");

    word_transform(in, inputfile);
    return 0;
}

使用g++ 4.9.2编译器编译运行后得到的结果如下:
这里写图片描述
而采用cl运行的结果如下:
这里写图片描述

我为g++不能得到正确的输出结果而着急。我以为cout在输出的时候没有flush缓冲区,于是flush命令用了,ends命令也用了,可就是解决不了问题。难道vc那么神吗,就能输出正确的结果。g++也是个优秀的编译器,为什么不能输出正确的结果呢。

2 分析代码

经过认真分析代码,我将问题的症结归结为函数buildMap()中的getline上面。我将函数word_transform()中的3个cout改为输出到文件,结果如下:
这里写图片描述
很容易我们可以看出,buildMap()中的getline在读入每行的时候在结尾处增加了一个”\n” (换行)。至此,找到问题所在,将上述代码trans_map[key] = value.substr(1);改为

trans_map[key] = value.substr(1, value.size()-2);

即可。也就是将最后一个换行符去掉。至此,程序可在g++中能得到正确运行结果。为什么代码没改动前输出到文件和输出到屏幕的结果不同,这就牵涉到缓冲区的问题了。我刚开始使用flush缓冲区的方法不成功的原因是getline在作怪,没找到病源。

可是问题又来了,改动后的代码在cl中的结果显示不正常了:
这里写图片描述
从上面可以清楚地看到,每一个翻译后的单词都少了最后一个字母。可以得出,getline在cl中不带”\n”符。

3 测试平台getline语义的小代码

如下:

//This program is used to test the 
//getline semantic for g++ or vc
#include <iostream>
#include <string>
#include <fstream>
using namespace std;

int main() {
    ifstream infile("getlinePtest.txt");
    string value;
    getline(infile,value);
    cout << value ;
    getline(infile,value);
    cout << value;
}

其中getlinePtest.txt文件中的内容为:

I love China!
I love Beijing!
[空行]

输出 “I love China!I love Beijing!”为cl编译器,输出”I love China!”为g++编译器,因为”I love Beijing!”被系统命令提示符冲掉了。

4 结束语

getline在cl和g++编译器上面具有不同的语义。如果不认识到这一点,将不能正确理解程序的输出结果。所以,使用getline函数时要小心。


  1. Stanley B. Lippman, Josee Lajoie, Barbara E. Moo. C++ Primer. 5th ed. Upper Saddle River NJ, Addison-Wesley, 2013.
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值