繁体   English   中英

我正在尝试用getline填充向量数组,这是怎么回事?

[英]I am trying to fill vector array with getline, what's wrong?

我想用一些行填充向量数组,但我没有得到相同的结果。 我的代码有什么问题?

using namespace std;

vector<string> calling(int n){
    vector<string> file(n);
    int a=0;

    while(n){
       getline(cin,file[a]);
       cin.ignore();
       a++;
       n--;
    }
    return file;
}

int main() {
    int n;
    cin >> n;
    vector<string> hrml = calling(n);
    int a=0;
    while(n){
        cout << hrml[a] <<endl;
        a++;
        n--;
     }
     return 0;
}

输入:

3
aaaa aaa aa
bb b bbbb
c cc ccc

输出:

aaaa aaa aa
bb b bbbb

您不需要在getline() std::cin.ignore()之后添加std::cin.ignore() ,因为后者会从流中“吃掉”换行符。 根据getline()docs

从输入中提取字符并将它们附加到str,直到发生以下情况之一(按列出的顺序检查):(...)

b)下一个可用的输入字符是delim,由Traits :: eq(c,delim)测试,在这种情况下,定界符字符是从输入中提取的,但未附加到str上。

您确实需要在std::cin >> n之后添加std::cin.ignore() ,尽管通过按Enter键,您已将换行符放入流中,并且它将被getline占用,它将返回一个空字符串,如下所示:结果。

@DimChtz回答了您的问题,但我想向您展示如何使用for循环,因为您似乎喜欢笨拙的while循环:

#include <vector>
#include <string>
#include <iostream>

using namespace std;

vector<string> calling(int n)
{
    vector<string> file(n);

    //for loop
    for (int i=0; i<n; i++) {
        getline(cin, file[i]);
    }

    return file;
}

int main() {
    int n;
    cin >> n;
    cin.ignore();

    vector<string> hrml = calling(n);

    //for each loop (C++11)
    for (auto & str : hrml) {
        cout << str << endl;
    }

    return 0;
}

这是几个因素的组合。

读取输入3的第一个数字不会将“光标”移到下一行; 它只是将其移过数字。 下次调用getline ,它返回大小为0的std::string ,因为它抓住了字符末尾与行末尾之间的空格,什么也没有。

然后,由于您使用该数字作为要读取的显式字符串,因此,您正好读取了3行: """aaaa aaa aa""bb b bbbb"

因此,您的输出缺少'c' '的行。

这里最简单的解决方案是在调用call之前强制对getline进行额外的calling (我已经从您的代码中删除了using namespace std; ,因为这是不好的做法

int main() {
    int n;
    std::cin >> n;
    std::string line;
    std::getline(std::cin, line);

然后,我们可以重写calling以不需要整数参数:

std::vector<std::string> calling(){
    std::vector<std::string> file;
    std::string line;
    while(std::getline(std::cin, line)){
        file.push_back(std::move(line));
    }
    return file;
}

(如果要在控制台中进行测试,并且需要标记行尾,请在Windows上使用Ctrl + Z ,在UNIX上使用Ctrl + D 。)

哪个将呼叫线路更改为此:

std::vector<std::string> hrml = calling();

或者,如果您使用的是C ++ 11(并且不介意丢失显式可见的类型声明),请执行以下操作:

auto hrml = calling();

只要我们在这里,我们就可以编写一个更好的循环来打印矢量的内容:

for(size_t i = 0; i < hrml.size(); i++) {
    std::cout << hrml[i] << std::endl;
}

或者,如果我们使用的是C ++ 11:

for(std::string const& line : hrml) {
    std::cout << line << std::endl;
}

而且,如果允许您更改输入文件的格式,我们可以首先放弃数字的读取,从而产生更小,更容易调试的程序:

#include<iostream>
#include<string>
#include<vector>

std::vector<std::string> calling(){
    std::vector<std::string> file;
    std::string line;
    while(std::getline(std::cin, line)) {
        file.push_back(std::move(line));
    }
    return file;
}

int main() {
    std::vector<std::string> hrml = calling();

    for(std::string const& line : hrml) {
        std::cout << line << std::endl;
    }
    return 0;
}

这个说法

cin >> n;

不会从输入缓冲区中删除换行符。 结果,函数getline的以下调用将读取一个空字符串,直到遇到换行符为止。

此语句在函数中

cin.ignore();

没有道理。 您应该在此声明之后放置类似的声明

cin >> n;

另外,如果要处理int类型的对象,则应检查它是否大于零。

考虑到这一点,程序可以采用以下方式。

#include <iostream>
#include <string>
#include <vector>
#include <limits>

using namespace std;

vector<string> calling( int n )
{
    vector<string> file;

    if ( n > 0 )
    {
        file.reserve( n );
        string s;

        while ( n-- && getline( cin, s ) ) file.push_back( s );
    }

    return file;
}

int main() 
{
    int n = 0;

    cin >> n;

    cin.ignore( numeric_limits<streamsize>::max(), '\n' );

    vector<string> hrml = calling(n);

    for ( const string &s : hrml ) cout << s << '\n';

    return 0;
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM