C++:从 cin 读取整数行

Posted

技术标签:

【中文标题】C++:从 cin 读取整数行【英文标题】:C++: Reading lines of integers from cin 【发布时间】:2016-04-01 20:20:35 【问题描述】:

当我熟悉 C++ 的 I/O 方面时,我正在尝试编写一个程序来从 std::cin 读取一些整数行。假设输入如下所示:

1 2 3
4 5 6
7 8 9
10 11 12

如何将上述行读入二维向量?

vector<vector<int>> nums;
/* 
 ... some code here and nums will look like the following:
 nums = 
    1,2,3,
    4,5,6,
    7,8,9,
    10,11,12
  
*/

我还尝试将上述整数行读取为一维向量,但在处理 '\n' 字符时遇到了一些问题。我的代码是:

string rawInput;
vector<int> temp;
while(getline(cin, rawInput, ' ') )
  int num = atoi( rawInput.c_str() );
  temp.push_back(num);
 

我通过打印出“temp”向量中的所有元素得到的最终结果是:

1 2 3 5 6 8 9 11 12   // 4, 7, 10 went missing

感谢任何帮助。谢谢。

【问题讨论】:

你可以用atoi(x.c_str())代替stoi(x) 【参考方案1】:

首先使用 getline 抓取整行,然后您可以使用 istringstream 为该行创建 ints 流。

此时只需使用带有两个迭代器的向量构造函数来创建整数的每个子向量。您的istringstream 上的istream_iterator&lt;int&gt; 可以完成此操作:

std::vector<std::vector<int>> nums;
std::string line;
while (std::getline(std::cin, line)) 
    std::istringstream ss(line);
    nums.emplace_back(std::istream_iterator<int>ss, std::istream_iterator<int>);

【讨论】:

【参考方案2】:

发生的事情是因为你只使用''(空格)作为分隔符,输入恰好是

1
2
3\n4 //<------ Newline also comes with the input

...

所以,您将3\n46\n7 等传递给atoi,它会返回 3,6 等(atoi 解析输入直到第一个非数字输入)并且4,7 丢失。

要实现你想要的,你可以使用 getline 和 istringstream(将默认分隔符保留为换行符)

string rawInput;
vector<vector<int>> temp;
while(getline(cin, rawInput) )
  istringstream bufferInput(rawInput); 
  temp.push_back(vector<int>std::istream_iterator<int>bufferInput, std::istream_iterator<int>);

【讨论】:

很好地识别问题,而不是仅仅提出其他解决方案。【参考方案3】:

你可以使用字符串流

string rawInput;
vector<int> temp;
stringstream ss;

while(getline(cin,rawInput))
  ss<<rawInput;
  vector<int> temp;
  int x;
  
  while(ss>>x)
    temp.push_back(x);
  
  
  num.push_back(temp)

【讨论】:

【参考方案4】:

我最近写了另一个问题的答案,但经过一些修改,它完全符合您的要求(我希望):

#ifndef _iosTREAM_H
#include <iostream>
#endif
#ifndef _STRING_H
#include <string>
#endif
#ifndef _VECTOR_H
#include <vector>
#endif

using namespace std;

enum XYZ  X = 0, Y = 1, Z = 2 ;

struct Vector 
    float x, y, z;
    Vector(float _x=0, float _y=0, float _z=0) 
        x = _x;
        y = _y;
        z = _z;
    
    float& operator[](size_t index) 
        if (index == XYZ::X) return x;
        if (index == XYZ::Y) return y;
        if (index == XYZ::Z) return z;
        throw new exception;
    
;



#define min(a, b) (((a) < (b)) ? (a) : (b))

bool isCharNumeric(char c) 
    const char* numbers = "0123456789";
    for (size_t index = 0; index < strlen(numbers); index++)
        if (c == numbers[index]) return true; return false;


vector<Vector> parseNumbers(string str_in) 
    str_in += "  "; //safe, no out of bounds
    vector<Vector> results = ;
    char currentChar;
    char skipChar = ' ';
    bool found_period = false;
    size_t count_len = 0;
    Vector vector_buffer(0,0,0);
    XYZ current_axis = (XYZ)0;
    for (size_t index = 0; index < str_in.length(); index++) 
        currentChar = str_in[index];
        if (currentChar == skipChar || currentChar == '\n' || currentChar == '\t')
            continue;

        else if (isCharNumeric(currentChar)) 
            string word = ""; //word buffer
            size_t word_len = min(min(str_in.find_first_of(' ', index + 1) - (index), str_in.find_first_of('\n', index + 1) - (index)), str_in.find_first_of('\t', index + 1) - (index)); //whatever char comes first; newline, tab or space
                                                                                                                                                              //append chars of following word checking if it is still valid number char
            if (word_len > 0) 
                size_t count_word_len = 0;
                for (count_word_len = 0; count_word_len < word_len; count_word_len++)
                    if (isCharNumeric(str_in[index + count_word_len])) 
                        word += str_in[index + count_word_len];
                    
                    else if (str_in[index + count_word_len] == '.' && isCharNumeric(str_in[index + count_word_len + 1])) 
                        //Floating-point numbers
                        word += '.';
                        found_period = true;
                        continue;
                    
                    else 
                        word = "";
                        continue;
                    

                    vector_buffer[current_axis] = stof(word);


                    if (current_axis == XYZ::Z) 
                        current_axis = XYZ::X;
                        results.push_back(vector_buffer);
                    
                    else 
                        current_axis = (XYZ)(current_axis + 1);
                    


                    index += count_word_len;
                    word = "";
                    continue;
            

        
    
    return results;

示例实现:

int main(int argc, char** argv) 
    string user_input;
    cin >> user_input;
    vector<Vector> numbers = parseNumbers(user_input);
    for each (Vector v in numbers) 
        cout << "X=" << v.X << "\n";
        cout << "Y=" << v.Y << "\n";
        cout << "Z=" << v.Z << "\n\n";
    

【讨论】:

您可能应该添加一个链接到您之前回答的问题。【参考方案5】:

令人惊讶的是,没有一个答案使用 istream 流运算符: http://www.cplusplus.com/reference/istream/istream/operator%3E%3E/

当流为空时,设置了 eofbit,因此运行一个 while 循环。

适用于所有类型,并且可以为自定义类型(例如 2D 纹理)重载。

【讨论】:

以上是关于C++:从 cin 读取整数行的主要内容,如果未能解决你的问题,请参考以下文章

如何从 C++ 中的文本文件中逐行读取整数? [复制]

如何使用 cin 将整数从控制台读取到向量中

如何使用 cin 读取用户的完整行?

在 C++ 中的单个输入行中读取整数列表

C++输入cin详解

C++面向行输入:get()与getline()