2011-05-24 60 views
6

我有一個程序叫abcstdout重定向改變輸出

當我運行下面的命令:

$ ./abc < infile 

我得到以下輸出:

ijklm 

然而,當我運行:

$ ./abc <infile> outfile 
$ cat outfile 

我給出這樣的輸出:

ijkoo 

現在,我假設這是我的程序錯誤。但是,無論我的程序在做什麼,我都不知道這是如何實現的。

編輯:

現在,我知道這是可能的,我很好奇,這是在我的計劃,是造成這算什麼。

有在我的程序一個循環,內部包含一個塊:

byte = ascii_to_byte(asciibyte); 
putchar(byte); 

字節char類型。

現在,如果我將putchar(byte)更改爲printf("%c", byte),所有輸出保持不變。

但是,如果我將其更改爲printf("%d", byte),然後$ ./abc < infile輸出:

105106107111111 

哪個是那些ASCII字符的十進制表示,因爲他們在outfile。但它不是字符的十進制表示,因爲它們剛剛發送到標準輸出時實際出現。我不明白爲什麼會有這種差異。

編輯#2:

如果我改變了印刷線printf("%c\n", byte),然後$ ./abc < infile輸出:

i 
j 
k 
o 
o 

這是什麼進入OUTFILE一致。再次,不知道有什麼區別。

編輯#3

我只是測試這32位機器上,且運行:outputfile包含ijklm。奇怪的。

編輯#4

這裏的主要功能是:

int main() 
{ 
    char asciibyte[8]; 
    char byte; 

    int c; //Using int to avoid the EOF pitfall. 
    long charcount = 0; 

    while((c = getchar()) != EOF){ 
     if(c != '0' && c != '1'){ 
      continue; 
     } 
     asciibyte[charcount % 8] = c; 
     if(charcount % 8 == 7){ 
      /*Testing revealed that at this point asciibyte does contain 
      what it should contain, eight ASCII ones and zeros representing 
      a byte read in from stdin*/ 
      byte = ascii_to_byte(asciibyte); 
      /*Print statements such as: 
       printf("%d", byte); 
       printf("%c\n", byte); 
      reveal that the ascii_to_byte function works incorrectly on my 
      64 bit machine. However these statements: 
       putchar(byte); 
       printf("%c", byte); 
      make it appear as though the function operates as it should. 
      EXCEPT if i redirect that output to a file.*/ 
      putchar(byte); 
     } 
     charcount++; 
    } 
    return 0; 
} 

這裏是ascii_to_byte功能:

char ascii_to_byte(char *asciibyte){ 
    char byte; 
    int i; 
    for(i = 0; i < 8; ++i){ 
     if(asciibyte[7-i] == '1'){ 
      byte = byte | (1 << i); 
     } 
    } 
    return byte; 
} 

最後編輯

我注意到我應該將字節初始化爲0x00。問題解決了。我爲什麼這麼遲鈍?我會給出答案,以便誰可以具體解釋這是如何引發問題的。

+0

是輸出總是一樣嗎?如果你運行./abc幾次,你會得到相同的結果嗎? – 2011-05-24 14:13:08

+0

是的,輸出在多次試驗中是一致的。 – oadams 2011-05-24 14:19:41

+0

'./abc pmg 2011-05-24 14:26:32

回答

1

這當然有可能 - 程序可以檢查它是否寫入終端,並寫入與寫入管道時寫入內容不同的內容。

0

尼爾巴特沃斯說什麼。該功能被稱爲isatty

if (isatty(STDOUT)) printf("I am printing to the terminal!\n"); 

此外,雖然測試的東西,你可能會做:

$ ./abc <infile> infile 

意外。因此,您可能需要快速檢查,即infile確實包含相同的數據。

+0

是的,我已經做了很多次,不同的測試輸入,我還是很奇怪。 – oadams 2011-05-24 14:11:41

3

這種奇怪的行爲,根據看似不相關的變化來來去去,可能表明你的程序從內存中讀取或寫入內存,它不應該這樣做,並且隨着代碼的其他部分的不同而改變行爲堆棧和/或堆。

我會仔細檢查代碼中的不良,如緩衝區溢出,它會返回指針變量在堆棧上功能等

單步調試代碼用調試器可能是生產(或它可能會改變如果你不幸,行爲會再次發生!)。

有幾個有趣的事情你已經看到了:

  1. 如何的stdout重定向可能有什麼影響?也許是因爲它會導致C庫的行爲有點不同:對於流使用不同的緩衝模式,具體取決於它是否連接到終端設備(請參閱GNU libc documentationC99§7.9.13第7段) 。

  2. 爲什麼改變putchar(byte)printf("%c", byte)不會改變任何東西,當兩個printf("%d", byte)printf("%c\n", byte)不改變行爲?也許是因爲編譯器會自動將printf("%c", byte)重寫爲效率更高的putchar(byte) - 即使未啓用優化,GCC的最近版本通常會執行此操作,而printf("%d", byte)printf("%c\n", byte)確實將編譯爲printf()的調用。

1

正如你所說,byte未初始化,所以任何可能發生。

可能發生的事情之一是,byte「從0開始」並保持其從函數調用到函數調用的值(就像它被聲明爲static一樣)。

 
in binary ... 

    byte | c (bin) | byte | c 
-----------+--------------+-------------- 
00000000 | i (01101001) | 01101001 (i) 
01101001 | j (01101010) | 01101011 (k) * strange you get 'j', but anything can happen :) 
01101011 | k (01101011) | 01101011 (k) 
01101011 | l (01101100) | 01101111 (o) 
01101111 | m (01101101) | 01101111 (o)