2017-04-21 69 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); 
相關問題