整行读入的简单应用举例

整行读入的简单应用举例

为什么gets会编译不通过?

简单地说,C++14 的标准规范已经删除了这个函数。

所以只要编译器是按照 C++14 的标准编译的,这个函数就是不存在的。

删除的原因是它函数设计上的安全缺陷。

C++的高版本会逐渐普及,很多 oj 都可能会有默认 14 及以上的编译标准。

大多数目前的比赛还是以 C++11 为标准的。

getline

最好是看手册,但如果你不是一个硬核的语法粉丝,可能看手册会比较吃力。下面我具一些例子,只针对算法竞赛实用的情况。

一般我们说到 getline,是指下面两个之一:

std::getline()

std::cin.getline()


std::getline()只能读给std::string类型(函数签名很长,这里不给出了,可以看手册)

{
     
    string s;
    getline(cin, s);
    cout << s << endl;
}

但是我不推荐这样做,因为 string 的后续处理比较慢。

std::cin.getline()的参数列表是:getline(char_type *__s, streamsize __n)也就是说它可以读给字符串数组,第二个参数指定读入缓冲的大小。

考一个 C 语言基础题,s[25]这个数组,最多可以存几个字符?

答:24 个,数组范围是 0-24,其中第 24 个位置是字符串结束符'\0',0-23 的位置存储了 24 个有效字符。

{
     
    char s[25];
    cin.getline(s, 25);
    cout << s << endl;
}

总而言之,如果要用getline不可避免地要面对cin。我的建议是不要把scanfcin混用。

特别做法

如果你对cin有偏见可以这样写:

{
     
    char s[25];

    scanf("%[^\n]s",s);
    getchar();
    puts(s);

    scanf("%[^\n]s",s);
    getchar();
    puts(s);
}

matches a non-empty sequence of character from set of characters.

If the first character of the set is ^, then all characters not in the set are matched.

参考文献

简单地说,[^\n]这里的意思是,把缓冲区内除了换行符以外的所有符号都读下来。这个设置还有很多有趣的特性,可以自行研究。

注意缓冲中的换行符是没有被读入的,所以,和gets用法类似,你要取掉换行符。

至于到底谁的效率高,这个的测过猜知道。(我没测)

某个朋友的经验是,getline 可能更快。

花边操作

getline的重载函数有第三个参数,是分隔符delimeter,你可以理解为,它可以指定换行符之外的分隔符。

这样就可以做一些比较不可思议的事情:

{
     
    string s;
    while (getline(cin, s, '$')) {
     
        cout << s << " ";
    }
}

/*
input:ababac$shiahia$shaishi
output:ababac shiahia shaishi
*/

这里的每一个s都是按照'$'分割的结果。

由此我可以写出下面一个简单的split函数。(偷懒的我没有把分隔符作为参数放进去)

vector<string> split(const string &raw) {
     
    vector<string> vec;
    stringstream ss(raw);
    static string si;
    while (getline(ss, si, '$')) {
     
        vec.emplace_back(si);
    }
    return vec;
}

结果会是下面这样的:

s := ababac$shiahia$shaishi
[split(s)] := {
     "ababac", "shiahia", "shaishi"}
s := aba$shia$shais
[split(s)] := {
     "aba", "shia", "shais"}

你可能感兴趣的:(c++)