在C++中是否有将输入字符串转换为输入流的方法?

3

我想要做的是从终端获取用户输入,并在程序中的其他函数中使用此输入。由于我的函数只接受输入流作为参数,因此我想将输入字符串转换为输入流。

int main(int argc, char** argv)
{

    std::vector<std::string> args(argv, argv + argc);
    
    if(args.size() == 1){ //if no arguments are passed in the console
        std::string from_console;
        std::istringstream is;
        std::vector<std::string> input;
        while(!getline(std::cin,from_console).eof()){
            input.emplace_back(from_console);
        }
        for(std::string str : input){
            std::cout << "\n" << str;
        }
}

当我尝试这段代码时,出现了另一个问题,如果我以一堆字符而不是换行符(按下回车键然后按下Ctrl+D)结束控制台输入,那么这行会被忽略并没有被打印出来。 例如: 当我输入以下内容时:

aaa bbb
ccc ctrl+d

我只输出了第一行(aaa bbb),而没有输出ccc。
但是:
aaa bbb
ccc
ctrl+d 

print()函数也会输出ccc,但它会忽略换行符。那么为什么会出现这种情况呢?


你打算利用那个 is 字符串流做些有用的事情吗? - WhozCraig
@WhozCraig 是的,将它作为参数传递给我的其他函数。 - r3k0j
顺便提一下 - !getline(std::cin,from_console).eof() 应该是 getline(std::cin,from_console)。除此之外,将字符串转换为输入流的整个用法似乎与您实际询问的关于 Ctrl+D 的行为完全无关。要么这样,要么您已经把两个不同的问题合并成了一个。 - Fureeish
@Fureeish 是的,我确实问了两个不同的问题。我应该在另一个线程中问另一个问题吗?编辑:顺便说一下,从 while 循环中删除 ! 会在我输入回车后结束程序。我希望在键入 Ctrl+D 后结束程序。 - r3k0j
3个回答

5
有没有办法在C++中将输入字符串转换为输入流?
是的,这是可能的。这就是std::istringstream的作用。例如:
std::string input = some_input;
std::istringstream istream(input); // this is an input stream

1

当文件结束符(eof)与最后一行内容在同一行时,getline(std::cin,from_console)会读取到它并返回true,因此最后一行被读入字符串from_console但未被推入向量。

有两种方法:

  1. 通过手动将最后一行推入向量来修改代码:
while(!getline(std::cin,from_console).eof()){
    input.emplace_back(from_console);
}
input.emplace_back(from_console);  // add one line
for(std::string str : input){
  1. 迭代器可以是一种优雅的方式:
#include <iterator>
// ...
if (args.size() == 1) {  // if no arguments are passed in the console
    copy(std::istream_iterator<std::string>(std::cin), {}, 
         std::ostream_iterator<std::string>(std::cout, "\n"));
}

1
std::istringstream有一个构造函数,它以std::string作为参数,并使用传递的字符串的副本作为流的初始内容。

因此,不要使用std::vector来存储从控制台输入的所有行,只需将这些行添加到一个单独(不同)的std::string对象中,记得在每个行末尾添加换行符,然后从该对象构造您的std::istringstream

下面是一个微不足道的示例,演示了如何在std::cin和像这样创建的std::istringstream对象上同样使用std::getline(与您的函数一样,将输入流作为其第一个参数):

#include <iostream>
#include <sstream>

int main()
{
    std::string buffer; // Create an empty buffer to start with
    std::string input;
    // Fill buffer with input ...
    do {
        getline(std::cin, input);
        buffer += input;
        buffer += '\n';
    } while (!input.empty()); // ... until we enter a blank line

    // Create stringstream from buffer ...
    std::istringstream iss{ buffer };

    // Feed input back:
    do {
        getline(iss, input);
        std::cout << input << "\n";
    } while (!input.empty());

    return 0;
}

谢谢,那正是我在寻找的。唯一的问题是,我希望在明确输入Ctrl+D时结束输入。怎么做呢? - r3k0j
1
@r3k0j 嗯,假设你的平台控制台确实使用Ctrl+D作为EOF,那么也许这篇文章可以提供一些关于更改循环条件的建议:为什么在循环条件中使用iostream::eof(即while (!stream.eof()))被认为是错误的? - Adrian Mole
1
我只想集中回答你问题的第一(主要)部分。 - Adrian Mole

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接