C++命令执行顺序混乱

6
我正在尝试制作一个简单的shell程序,查看了一些示例后发现大多数人使用getline()来获取输入,但是我一直在尝试使用read(),并注意到一个奇怪的bug,想知道其他人是否也看到或知道原因。
当我使用getline运行代码时,一切正常。运行程序后,我会看到终端名称,并准备接受输入。当我使用read时,在接受输入后似乎执行了shell的名称。无论我做什么都会出现这种情况。显示shell名称的行是:
cout << "SweetShell-> ";

然后在这行代码之后,我要么运行读取命令,要么调用另一个进程来运行读取命令,无论哪种方式,“SweetShell-> ”的打印都会在输入之后发生。

更奇怪的是,在测试期间,我有一段代码块如下:

cout << "SweetShell-> ";
int test = read(0,buf,MAX_ARGS);
//temp is a string that is set to the input
cout << temp << "    " << test;

输出结果大致如下:

    3SweetShell-> ls

这意味着它先打印了空格,然后是test,接着是第一个cout,最后是temp。有人知道这是怎么回事吗?


顺便说一下,除了我的回答之外:C ++保证这些命令将按顺序执行(因此您的标题应进行修订);它只是不保证输出会是您期望的。 - Seth Johnson
这个程序运行在哪个操作系统上?从你的问题可以推断出可能是Mac、Windows、Linux等。 - Nate Koppenhaver
实际上,我认为为了更好地理解其行为,您应该告诉我们temp具体是什么以及这个注释是否替换了任何内容。 - Seth Johnson
操作系统是Linux,至于temp到底是什么,它是一个字符串。那里被注释掉的是一个7-8行的代码块,将字符串分解成标记,检查某些标记是否等于特定字符,然后创建一个包含分解字符串的向量。我认为这些都不相关,因为没有任何操作实际上修改了temp或处理了输入/输出,所以我没有包括它们。 - SomeoneRandom
4个回答

11

你应该尝试"刷新"输出缓冲区以确保按顺序打印。尝试以下方法:

cout << "SweetShell-> " << std::flush;
int test = read(0,buf,MAX_ARGS);
//temp is a string that is set to the input
cout << temp << "    " << test << std::flush;

谢谢您的快速回复,这似乎完全解决了问题。我对C++还比较新,所以不知道需要像这样清除缓存。 - SomeoneRandom
@某人:这取决于情况。通常情况下是不必要的,但flush可以保证你发送到流中的内容(无论是通过cout在终端显示还是写入文件)将被打印/写入。如果一些中间函数在你刷新缓冲区的目标之前(例如在终端上打印)对其进行了更改,就像read似乎是这种情况,那么你可能会遇到问题。 - Seth Johnson
@Seth:“这取决于情况”并不准确(详见我的回答)。 - Tony Delroy
@Tony:我并不是说“魔术”定义了这种情况。我只是无法在一个评论帖子中列举所有的情况。例如,你的回答忽略了 system("echo hello there"); 的荒谬调用。 - Seth Johnson
@ Seth:system("echo hello there"); 和什么有关系?它无法清空 std::cout - Tony Delroy
@Tony:我并没有说它会这样。我是在谈论“需要”清除它,以便您的输出与C ++中的语句以相同的顺序显示,这是原始问题的主题。 - Seth Johnson

5
由于输出是缓冲的,所以在尝试读取输入之前,您需要flush输出。
顺便提一下,当组合原始的操作系统级read(2)write(2)操作与缓冲IO操作时,请小心;虽然您可以在同一程序中使用这两个操作,但在同一个文件套接字上同时使用它们会创建麻烦;因此,坚持一种形式或另一种形式将减少未来引入缺陷的可能性。

感谢未来的提示,将来会牢记在心。 - SomeoneRandom

4
关键的一点是,std::coutstd::cin绑定的(参见http://www.cplusplus.com/reference/iostream/ios/tie/),这意味着对std::cin进行的流操作将首先触发对std::cout的刷新。但是,您正在使用绕过C++流库的libC read(...)函数,因此没有机会调用刷新。您可以改为使用std::cin.read()

谢谢,从没这样想过。 - Jerry Asher

0

为什么不使用cin >> test?我总是使用<iostream>函数进行控制台I/O,它们非常好用。


虽然我通常更喜欢iostreams,但与C I/O函数相比,它们真的非常慢。因此,当有大量IO操作时,我会切换到printf、scanf等函数。 - Armen Tsirunyan

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