2011-09-22 79 views
0

我是C新手,所以我完全被以下行爲所困惑。使用pipe()fork()我閱讀下面的瑣碎Ruby程序的輸出:通過對讀函數的調用在read()緩衝區中存在亂碼?

puts "success" 

在C:

n = read(fd[0], readbuffer, sizeof(readbuffer)); 
printf("received: %s", readbuffer); 

然而,printf在打印一堆那些'無法識別的字符'符號(如鑽石中的問號)到控制檯。此外,做比較如:

if (strcmp(readbuffer, "success") == 0) 
    { 
     /* do something */ 
    } 

失敗。我究竟做錯了什麼?

編輯:聲明按要求。我不知道有關memsetting,我在C.

第一天
int fd[2], in; 
pid_t pid; 
char readbuffer[6]; 

編輯:

答案由「萬畝太短」也解決了這個問題。共識似乎是使用memset是矯枉過正。我是新手C程序員,所以我不得不相信評論家的意見。然而,這是一個論據和廣告,而且太短可能確實比較合適。無論如何,我建議閱讀這兩個答案,因爲任何「矯枉過正」可能仍然是微不足道的。

+0

在使用它之前,你是否使用'memset'緩衝區?如果你沒有,那麼緩衝區不是空終止,並會給你垃圾值。 –

+0

聲明readbuffer靜態或全局,它將被初始化爲零。 – DigitalRoss

+0

請顯示用聲明編輯的readbuffer和fd –

回答

2

正如其他人所指出的那樣,你的緩衝區是不是大到足以容納你正在閱讀的文本,而你不知道確保它是空的終止。

但是在每次讀取之前使用memset()來清零整個緩衝區是不必要的;你只需要確保在你讀過的數據的末尾有一個空值(並且當然使你的緩衝區更大)。

如果您readbuffer至少9個字符,並替換:

n = read(fd[0], readbuffer, sizeof(readbuffer)); 

..with ..

n = read(fd[0], readbuffer, sizeof(readbuffer) - 1); 
readbuffer[n] = '\0'; 

..then應該這樣做(雖然您應檢查n>> = 0以確保read()成功)。指定一個小於讀緩衝區的大小可以確保readbuffer[n]不會溢出(但如果read()失敗,則可能會導致溢出)。

然後,你只需要在最後處理換行。

這也假設整個字符串在一個讀取調用中被讀取。在這種情況下很可能,但通常在讀取足夠的數據之前,必須讀取必要的連接多個讀取。

1

作爲註釋說明,您不會在readbuffer上有空終止符,因此它不是一個真正的C字符串。你可以這樣做:

#include <string.h> 

/* ... */ 

memset(readbuffer, 0, sizeof(readbuffer)); 
n = read(fd[0], readbuffer, sizeof(readbuffer) - 1); 

這將給你一個適當的以null結尾的字符串。但是,如果你真的想長度爲6的字符串,然後更改的readbuffer的聲明:

char readbuffer[7]; 

如果你只需要你的readbuffer一次,你可以說:

char readbuffer[7] = { 0 }; 

它初始化全零。但是,如果您在循環中執行read,那麼您需要在每個read之前先要memset(readbuffer, 0, sizeof(readbuffer)),以確保不會因最後一步中的任何剩餘數據而結束。

C不會自動初始化一個局部變量,你必須自己動手。

+0

這確實擺脫了無意義的字符,但是現在輸出是空白的......我知道從ruby接收文本沒有錯誤,例如通過改變'success'來說'失敗'並忽略memset我可以得到各種廢話。 – providence

+1

'memset'太過分了。您可以在讀取數據後編寫單個終止符,也可以使用'「%。* s」'來輸出數據而不需要終止。 –

1

據我瞭解,你行:

puts "success" 

將輸出(在C組術語)

success\n\0 

我算作9個字符。

你宣佈readbuffer僅6以前的答案只有它調升爲7

+0

6是一個錯字。正如你所指出的,我原來有7個,但仍然太少。我已經提高了這個數字,謝謝。 – providence