2017-04-21 82 views
1

所以我目前正在做一个任务,并在我的笔记本电脑上工作正常,但在我的电脑上输出是乱码。从两个系统上的相同程序的C++不同的输出

输入一个命令:
一个
输入一个命令:接收
a'Zéÿ命令。

忽略我搞砸了输出为什么在输出中有'Zéÿ?
在我的笔记本电脑上,代码正常工作。

这里是一个小样本代码:

#include <sys/types.h> 
#include <sys/wait.h> 
#include <stdio.h> 
#include <stdlib.h> 
#include <unistd.h> 
#include <string.h> 
#include <iostream> 
using namespace std; 

int main(){ 
    int pipefd[2]; 
    pid_t cpid, ppid; 
    char buf[100]; 

    if (pipe(pipefd) == -1) { 
     perror("pipe"); 
     exit(EXIT_FAILURE); 
    } 

    cpid = fork(); 

    if (cpid == 0) { 
     read(pipefd[0], &buf, 1); 
     cout << buf << " command received." << endl; 
    } 
    else { 
     cout << "Enter a command: " << endl; 
     cin >> buf; 
     cout << "buf: " << buf << endl; 
     size_t len = strlen(buf); 
     write(pipefd[1], &buf, len); 
    } 

    return 0; 
} 

输出是略低不同的充虽然接受了它的刚
一个`命令。而不是
收到一个命令。

E:我用我的笔记本电脑在我的电脑和基本antergos,两个系统上的终端是urxvt

回答

1
read(pipefd[0], &buf, 1); 

读取一个字节。由于它是一个字节是不可能的程序读取

cout << buf << " command received." << endl; 

所以打印所需的空终止是不确定的行为; operator<<不知道在哪里停止阅读。它可能会立即停止,它可能会在有效内存结束时运行并导致程序崩溃。无法确定,每次结果都可能会有所不同。

由于问题中没有协议信息,我唯一的建议是建立一个通知协议,告知读者必须读取多少个字节。我希望发送一个已知大小的计数器在发送消息之前通知读者消息的大小。例如,

uint32_t len = strlen(buf); 
write(pipefd[1], &len, sizeof(len)); 
write(pipefd[1], &buf, len); 

,然后阅读

uint32_t len; 
read(pipefd[0], &len, sizeof(len)); 
read(pipefd[0], &buf, len); 

不要忘记检查读取成功,并得到了你所需要的字节数。您可能必须循环读取,直到您收到完整的消息。

+0

一个好的协议不是依赖于消息长度,因为接收者可能会收到少于您的位数发送开始。更好的方法是使用分隔符。 json是使用'{message}'的一个很好的例子。 – alvits

+0

@alvits完全取决于协议的需求。定界符方法需要getta-byte getta-byte getta字节,字节,字节的读取模式来查找分隔符,这可能不合适。您可以不小心超出输入缓冲区的一件事。前置长度允许接收机提前检查并确保它们具有足够的存储空间来处理该消息并且希望能够进行一次大的读取。 – user4581301

+0

我不同意。这就是为什么'read()'有第三个参数。这是缓冲区溢出的保障。允许发送者发送比缓冲区可容纳更长的时间。如果缓冲区较短,收件人负责通过循环读取所有内容。 – alvits

2

您必须初始化缓冲,否则它将包含任何以前在内存中那个位置,这是正在打印的内容。

+0

但为什么它的工作在我的笔记本罚款混淆我 – user273032

+0

这一切都归结到机会:在笔记本电脑上,必须不存在在该位置的内存中可以打印字符。 –

+0

@ user273032未定义的行为未定义。它甚至可能看起来像它的作品。 – user4581301

1

read()不会自动附加空字节。您有责任在收到的消息末尾添加空字节。

最简单的就是得到read()返回的值。该值是读取的字节数,如果遇到错误,则为-1。使用此返回值将字符串的末尾设置为空。

改变这一行:

read(pipefd[0], buf, 1); 

要:

int length=read(pipefd[0], buf, 99); 
if (length > 0) // length bytes was read 
    buf[length]='\0'; 
else // nothing was read or an error occured 
    buf[0]='\0'; 

或者,你可以零出整个缓冲区,所以你不会需要追加一个空字节。

更改此:

read(pipefd[0], buf, 1); 

要这样:

memset(buf,0,100); 
read(pipefd[0], buf, 99); 
相关问题