如何在 C++ 中的字符串之间使用 cin?

Posted

技术标签:

【中文标题】如何在 C++ 中的字符串之间使用 cin?【英文标题】:How do I use cin between strings in C++? 【发布时间】:2015-12-14 23:32:43 【问题描述】:

我对 C++ 还很陌生,并且一直在学习这样的东西:

cout << "My age is: ";
cin >> age;

与 cin 混在一起,我遇到了一个障碍。

假设我想写“我 x 岁!”。

"x" 是 cin >> 年龄;

我是这样写代码的。

cout << "I am ";
cin >> age;
cout << "years old!";

障碍在于这会产生换行符。

我不想换行。

我怎样才能让所有这些都留在一条线上?

【问题讨论】:

这对我来说没有多大意义。你不应该要求用户输入年龄,然后整体输出std::cout &lt;&lt; "I am " &lt;&lt; x &lt;&lt; " years old.\n"吗? 那么,您是否想提出一些类似空白的东西,用户可以在其中输入他们的年龄?如果是这样,不幸的是,这不是基于文本的系统通常的工作方式,但我确信这可以通过 ncurses 完成,尽管它会变得更加复杂。 在没有换行符的情况下输入内容的方法是关闭流上的缓冲。但这取决于您使用的操作系统,而不是 C++ 的一部分。例如,在 Windows 中,您可以获取字符而根本不将它们回显到屏幕上,然后再决定将哪些字符放在屏幕上。 ###有可能!如果您使用 Microsoft Visual Studio,因此可以使用标头 conio.h,那么有一个解决方案(但这可能有点棘手,因为您需要处理字符,而不是流)。看看this answer to similar question on Stack Overflow。 PS:得到你需要的字符后,你可以回去使用流从中读出一个整数值。 #Numeri 指出我想做什么。用 cin 填空。 #DietmarKuhl 解释说这是可能的,但需要一些工作。我意识到,据我所知,我仅限于使用 #Olipro 呈现的 cin 逻辑。 【参考方案1】:

我假设您实际上希望输入与最终输出一致。否则,解决方案是微不足道的:首先读取值然后打印它,例如:

std::cout << "how old are you? ";
std::cin >> x;
std::cout << "I am " << x << " years old\n";

处理与输出一致的输入有点棘手。这里的问题是控制台处理实际上是由系统完成的,而不是由语言完成的。因此,输入数据时需要等待换行符。换行符将由控制台处理并创建换行符。要禁用此行为,有必要依赖控制台行为来解决问题。没有标准的 C++ 方法可以这样做。

我不知道如何处理 Windows 上的控制台控件:我主要是 UNIX 程序员。在 UNIX 系统上,您可以使用 tcgetattr()tcsetattr() 将输入模式设置为非规范(即,清除 ICANON 位)。所需的文件描述符只是标准输入的一个,即0

一旦控制台使用非规范模式,所有按键都会立即转发到应用程序,并且不会完成屏幕回显。因此,读取函数实际上需要回显单个字符,然后转发到解析函数。最简单的方法是创建一个过滤流缓冲区,它在转发字符时为std::cinstd::cout 进行必要的回显。但是,将所有这些放在一起有点工作......

在制作演示时,我注意到我还需要处理回显(当用户使用回车键时避免换行)。重置控制台标志也很重要,因为即使在程序终止后它们中的一些实际上仍然保持更改。将这些位放在一起但仍然缺乏错误处理的实现可能如下所示:

#include <iostream>
#include <ctype.h>
#include <termios.h>

struct non_canon_buf
    : std::streambuf 
    char buffer;
    non_canon_buf() 
        termios flags = ;
        tcgetattr(0, &flags);
        flags.c_lflag &= ~(ICANON | ECHO);
        tcsetattr(0, TCSANOW, &flags);
    
    ~non_canon_buf() 
        termios flags = ;
        tcgetattr(0, &flags);
        flags.c_lflag |= ICANON | ECHO;
        tcsetattr(0, TCSANOW, &flags);
    
    int underflow() 
        if (std::cin.get(buffer)) 
            this->setg(&buffer, &buffer, &buffer + 1);
            if (!std::isspace(static_cast<unsigned char>(buffer))) 
                std::cout << buffer << std::flush;
            
            return std::char_traits<char>::to_int_type(buffer);
        
        return std::char_traits<char>::eof();
    
;

int main()

    non_canon_buf sbuf;
    std::istream  in(&sbuf);
    std::cout << "I am ";
    int age = 0;
    in >> age;
    std::cout << " years old\n";
    if (!in) 
        std::cout << "ERROR: failed to enter a valid age!\n";
    

【讨论】:

为了完整起见,Windows 等效项将是 SetConsoleMode 并禁用 ENABLE_LINE_INPUTENABLE_ECHO_INPUT。然后可以使用ReadConsole(或ReadFile with stdin)。 @Mawg 虽然这可能不是权威来源,但cppreference.com 有一个关于std::endl 的注释,上面写着“使用 std::endl 代替 '\n',一些消息来源鼓励,可能会显着降低输出性能。”所以\n 可能就是这样。 @Mawg: \n 是完全有效的 C++。您可能更喜欢std::endl,但您不应该向使用您不喜欢的编码约定的任何答案发送 Stack Overflow cmets 垃圾邮件。另外,请注意 \nstd::endl 在技术上甚至不做完全相同的事情,正如 Alex 的链接中所解释的那样。 同意;他们不做同样的事情。这就是为什么应该使用std::endl。在特定情况下,当您确切地知道自己想要做什么时,\n 是可以接受的,但在这里我们试图教新手良好的编码实践。 @Mawg:有趣的是你会说我应该使用std::endl。但是请注意,我对'\n' 的使用是经过深思熟虑的。出于某种原因,您可能想看看blog 我几年前写的一个恐惧。特别是,我强烈反对认为新来者应该使用std::endl 的观点:没有人应该使用std::endl 永远是正确的评估。【参考方案2】:

cin 在控制台输入换行符后读取输入。

因此,您可以连续执行此操作的唯一方法是提示用户他们的年龄,然后继续编写它。

例如:

std::cout << "Enter your age> ";
std::cin >> age;
std::cout << "I am " << age << " years old" << std::endl;

【讨论】:

你能参考一下换行之后的东西吗?【参考方案3】:
unsigned int age;
std::cin >> age;

std::cout << "I am " << age << " years old!" << std::endl;

【讨论】:

这只是避免这个问题的方法,不是解决方案。 加一个是唯一使用std::endl而不是\n的人 @Mawg This one 也使用 std::endl ...【参考方案4】:

你不能在纯 C++ 中做你想做的事。您可以按照其他人的建议进行并重新打印该行:

std::cout << "I am " << age << " years old!\n"

或者您可以使用特定于操作系统的功能来清除控制台输出。 Read about this here.

例如,对于 Windows,您可以使用 system("cls");,在询问用户年龄后清除控制台。

#include <stdlib.h>

int main(int argc, char* argv[]) 
    unsigned int age;
    std::cout << "My age is: "
    std::cin >> age;
    system("cls");
    std::cout << "I am " << age << " years old!\n"
    ...

产量:

C:>AgeProgram.exe I am 10 years old

【讨论】:

@Mawg std::endl 刷新cout 缓冲区。在极少数情况下,你真的想要这个。 "\n"endl 在其他方面都是相同的。 Read this.【参考方案5】:

你可以这样做

int user_age;

std:cout<<"Enter Your Age:"         //Ask user for age

std::cin >>user_age;                //Read user input
std::cout<<"I am"<<user_age<<"years old!"<< std::endl; //finlly display the value

【讨论】:

以上是关于如何在 C++ 中的字符串之间使用 cin?的主要内容,如果未能解决你的问题,请参考以下文章

c++中cin/cout如何输入输出字符串数组?

C++ 中的 Getline 和 cin.ignore

如何在 C++ 中打开 Nano 并从中获取字符串?

如何简单地比较 C++ 中的字符?

c++,cin/cout 如何输入输出字符串数组

如何在 C++ 程序中的 2 个特定字符之间比较 2 个文件中的文本行