简体   繁体   English

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

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

I would like to fill a vector array with some lines but I don't get the same back. 我想用一些行填充向量数组,但我没有得到相同的结果。 What is the problem with my code? 我的代码有什么问题?

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;
}

The input: 输入:

3
aaaa aaa aa
bb b bbbb
c cc ccc

The output: 输出:

aaaa aaa aa
bb b bbbb

You don't need std::cin.ignore() after getline() as the latter 'eats' the new line character from the stream. 您不需要在getline() std::cin.ignore()之后添加std::cin.ignore() ,因为后者会从流中“吃掉”换行符。 As per the getline() docs : 根据getline()docs

Extracts characters from input and appends them to str until one of the following occurs (checked in the order listed): (...) 从输入中提取字符并将它们附加到str,直到发生以下情况之一(按列出的顺序检查):(...)

b) the next available input character is delim, as tested by Traits::eq(c, delim), in which case the delimiter character is extracted from input, but is not appended to str. b)下一个可用的输入字符是delim,由Traits :: eq(c,delim)测试,在这种情况下,定界符字符是从输入中提取的,但未附加到str上。

You do need std::cin.ignore() after std::cin >> n though as by pressing enter you've put the newline character into the stream and it's going to get eaten by getline, which will return an empty string as a result. 您确实需要在std::cin >> n之后添加std::cin.ignore() ,尽管通过按Enter键,您已将换行符放入流中,并且它将被getline占用,它将返回一个空字符串,如下所示:结果。

@DimChtz answered your question, but I thought I'd show you how to use for loops since you seem to be fond of clunky while loops: @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;
}

It's a combination of a few factors. 这是几个因素的组合。

Reading the first number in the input, 3 , doesn't move the "cursor" to the next line; 读取输入3的第一个数字不会将“光标”移到下一行; it simply moves it past the number. 它只是将其移过数字。 When you next call getline , it returns a std::string of size 0, because it grabs the space between the end of the character and the end of the line, which is nothing. 下次调用getline ,它返回大小为0的std::string ,因为它抓住了字符末尾与行末尾之间的空格,什么也没有。

Then, because you're using that number as an explicit number of strings to read, you're reading exactly 3 lines: "" , "aaaa aaa aa" , and "bb b bbbb" . 然后,由于您使用该数字作为要读取的显式字符串,因此,您正好读取了3行: """aaaa aaa aa""bb b bbbb"

Hence your output missing the line of 'c' 's. 因此,您的输出缺少'c' '的行。

The simplest solution here is to force an extra call to getline before you call calling . 这里最简单的解决方案是在调用call之前强制对getline进行额外的calling (I've removed using namespace std; from your code because it's bad practice ) (我已经从您的代码中删除了using namespace std; ,因为这是不好的做法

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

Then, we can rewrite calling to not need an integer parameter: 然后,我们可以重写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;
}

(If you're testing in your console, and you need something to mark the end of the line, use Ctrl + Z on Windows or Ctrl + D on UNIX.) (如果要在控制台中进行测试,并且需要标记行尾,请在Windows上使用Ctrl + Z ,在UNIX上使用Ctrl + D 。)

Which changes the calling line to this: 哪个将呼叫线路更改为此:

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

Or this, if you're using C++11 (and don't mind the loss of explicitly visible type declaration): 或者,如果您使用的是C ++ 11(并且不介意丢失显式可见的类型声明),请执行以下操作:

auto hrml = calling();

And as long as we're here, we can write a better loop for printing the contents of our vector: 只要我们在这里,我们就可以编写一个更好的循环来打印矢量的内容:

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

Or, if we're using C++11: 或者,如果我们使用的是C ++ 11:

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

And, if you're allowed to change the format of your input file, we can ditch the reading of the number in the first place, yielding a much smaller and easier to debug program: 而且,如果允许您更改输入文件的格式,我们可以首先放弃数字的读取,从而产生更小,更容易调试的程序:

#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;
}

This statement 这个说法

cin >> n;

does not remove the new line character from the input buffer. 不会从输入缓冲区中删除换行符。 As result the following call of the function getline reads an empty string until the new line character is encountered. 结果,函数getline的以下调用将读取一个空字符串,直到遇到换行符为止。

This statement in the function 此语句在函数中

cin.ignore();

does not make sense. 没有道理。 You should place a similar statement after this statement 您应该在此声明之后放置类似的声明

cin >> n;

Also if you are dealing with an object of type int you should check that it is not less than zero. 另外,如果要处理int类型的对象,则应检查它是否大于零。

Taking this into account the program can look the following way. 考虑到这一点,程序可以采用以下方式。

#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.

相关问题 cin.getline()我在做什么错? - What am I doing wrong with cin.getline()? 我只是想将 getline function 作为初学者使用。 我仍然不知道这里出了什么问题 - I am just trying to use the getline function as an absolute beginner. I still dont know what went wrong here 数组有效,而矢量无效。 我究竟做错了什么? - Array works while vector doesn't. What am i doing wrong? 用getline循环填充数组 - Fill an array with getline loop 我正在尝试在 c++ 中创建一个日志记录框架,但信息没有传递给记录器的子组件,我做错了什么? - I am trying to make a logging framework in c++ but information is not being passed to the logger's subcomponents, what am i doing wrong? 在删除某些矢量元素时我做错了什么? - What i am doing wrong in erasing some vector elements? 这是getline()的错误,还是我做错了什么。 使用getline()的正确方法? - Is this a bug with getline(), or am I doing something wrong. Right way to use getline()? 尝试创建HIMAGELIST,我在这里做错了什么? - Trying to create HIMAGELIST, what am I doing wrong here? 尝试在类成员初始化中使用vector的fill构造函数失败。 怎么了? - Attempting to use vector's fill constructor in class member initialization fails. What is wrong? 我不了解getline +字符串是什么? - What am I not understanding about getline+strings?
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM