2013-04-24 137 views
0

我已經編寫了代碼,用於執行凱撒移位密碼,從一個名爲「input.txt」的文件獲取輸入並將輸出寫入名爲「output.txt」的文件。它技術上工作正常;輸出結果幾乎是完美的,但是當我運行它時,我得到關於Line 56Debug Assertion Failed消息,這是關閉輸出文件的行。該錯誤還表示:表達式:(unsigned)(c+1) <= 256。這裏是我的代碼:凱撒密碼;調試斷言失敗

void cipher(char input[], int key); 

int main() 
{ 

    int i, key=0; 
    char c, input[MAX]; 
    FILE *file1; 
    file1 = fopen("input.txt","r"); 

    printf("Enter the key: "); 
    scanf("%d", &key); 
    getchar(); 

    for(i=0;(c=getc(file1))!=EOF && i<MAX;i++) 
     input[i]=c; 
    fclose(file1); 
    cipher(input, key); 
    return 0; 
} 

void cipher(char input[], int key) 
{ 
    int length = strlen(input)-1; 
    int i; 
    char c; 
    FILE *file2; 
    file2 = fopen("output.txt","w"); 
    for (i=0;i<length;i++) 
    { 
     if (isalpha(input[i])) 
     { 
      c = (toupper(input[i]) - 'A'+key) % 26 + 'A'; 
      fprintf(file2, "%c", c); 
     } 
     else if (input[i]==' ') 
      fprintf(file2, "\n"); 
    } 

    fclose(file2); 
} 

哦,不太緊迫的問題,但是當代碼吐出輸入,如果輸入改變線路,如「輸入文字\ n這裏」,那麼當它的密碼爲「文本」和「這裏」,它把它們放在一起,而不是像它應該放在單獨的行上。如果有人知道這是爲什麼,可以幫助我,我會很感激,但主要的是這個錯誤。

+1

「我對這個網站還比較陌生,我還沒弄清楚如何正確格式化代碼而不會爆炸。」選擇您的代碼塊並點擊'{}'按鈕。請參閱http://stackoverflow.com/editing-help#code – Johnsyweb 2013-04-24 04:25:19

+0

如果輸入[i] =='\ n''那麼你什麼都不寫,因此「不太緊迫的問題」 – Keith 2013-04-24 04:30:38

+0

是否有更多的代碼,共享?是否有一些函數或進程正在測試你正在執行斷言的輸出? – Jason 2013-04-24 04:43:58

回答

0

這裏有兩個問題。

char c, /* ... */; 
for(i=0;(c=getc(file1))!=EOF && i<MAX;i++) 
    input[i]=c; 

這是錯誤的。 getc返回int,所以c應該也是int。其原因是,存在用於getc兩種類型的返回值:

  1. 正值,其可被表示爲無符號字符
  2. 負值,表示錯誤。

如果直接轉換爲char,則無法檢查錯誤。 char可能有符號或無符號。如果它是無符號的,那麼(c=getc(file1))將會是一個正數,它不可能等於EOF。因此,遇到EOF時,循環不會結束。如果您的char已簽名,那麼您的程序可能會以其他奇怪方式發生故障,例如終止循環太早或在某些機器上進行分段。

這適用於所有標準C函數!確保你在轉換它們之前檢查返回值!這包括scanf

<ctype.h>是你從哪裏得到你的isalphatoupper函數。

7.4字符處理

1所述的報頭聲明瞭 分類和映射characters.198)在所有情況下的參數是 一個INT,其值應是可表示的有用的若干功能作爲無符號字符 或等於宏EOF的值。如果參數有其他值 ,則行爲是未定義的。

在我看來,你可能會調用未定義的行爲,將可能的負值傳入isupper

+0

嗯,沒關係。這很有道理,但即使我將C更改爲int,仍然會出現錯誤。更改爲某個整數後,是否需要轉換c? – Vyreinos 2013-04-24 06:05:13

+0

'int c = getchar(); char d = c; if(isalpha((unsigned char)d)){...}' – Sebivor 2013-04-24 06:08:00

+0

在int變量中存儲'int'返回值。當期望'unsigned char'值時傳遞'unsigned char'值。 – Sebivor 2013-04-24 06:09:03

0

如果您使用的是MSVC,請注意調試CRT將檢查傳遞給isalpha的參數是否在EOF0..0xff(請參閱MSDN)範圍內。在你的代碼中,你打電話isalpha(input[i])input是一個char數組。由於isalpha需要int,因此最終可能會調用isalpha,其值超出允許的範圍。你應該改變你的電話isalpha((unsigned char)input[i])

我也會相應地將呼叫改爲toupper

正如undefined behaviour已經說過你必須在getc結果存儲在int變量,把它比作EOF,然後將其轉換爲char和存儲。在將其轉換爲char後,您無法再將其與EOF進行比較(EOFint的值,該值不能表示爲char)。