2011-04-05 41 views
1

我正在嘗試完成一個C編程主題的高校作業。Solaris編譯器使我的C代碼行爲怪異

我已經在我的MacBook上完成了我的任務,並且我的代碼完全按照它的設計工作。然而,我們的講師已經告訴我們,我們所有的代碼都將使用大學的Solaris 10 Server進行編譯,並且我們被告知如果您的代碼不能編譯和運行,將會扣除標記。

我們也接到指示,我們的應用程序將通過以下語法標記編譯:

gcc -ansi -Wall -pedantic assign1.c -lm -o assign1 

使用和執行:

./assign1 

我的代碼目前編譯沒有錯誤或警告並正確執行。但是,我的某個函數在此Solaris機器上無法正常工作。該函數應該是我們自己實現的基本字符串排序 - 用戶輸入一個長達40個字符的字符串,它應該被轉換爲小寫字母並按照字母順序排序,並刪除所有非字母字符。

我的Mac上,它輸出:

Enter a string (1-40 characters): asdfghjkl 
Output: adfghjkls 

在學院的Solaris系統,它輸出:

Enter a string (1-40 characters): asdfghjkl 
Output: aa#?dfghjkls 

我的函數,它(大多數)輸出的是:

void sortLine(int *optionStats, char* source) 
{ 
    char tempsort[MAX_SORT_LENGTH + 1]; 
    char comp_c; 
    int i,j,k; 
    char c = source[i++]; 
    i = j = k = 0; 
    optionStats[2]++; 
    while (c != '\n' && c != '\0' && c != EOF) { 
     /* convert uppercase characters to lowercase */ 
     if ((int)c >= (int)'A' && (int)c <= (int)'Z') 
     c = c + ((int)'a' - (int)'A'); 
     /* if the character is alphabeic then sort it else skip it */ 
     if ((int)c <= (int)'z' && (int)c >= (int)'a') { 
     for (j = 0; j <= MAX_SORT_LENGTH + 1; j++) { 
      comp_c = tempsort[j]; 
      if (comp_c == '\n' || comp_c == '\0' || comp_c == EOF) { 
       tempsort[j] = c; 
       break; 
      } 
      if ((int)c <= (int)comp_c) { 
       for (k = MAX_SORT_LENGTH + 1; k > j; k--) { 
        tempsort[k] = tempsort[k - 1]; 
       } 
       tempsort[j] = c; 
       break; 
      } 
     } 
     } 
     c = source[i++]; 
    } 
    /* copy the sorted temporary array into the source array */ 
    for (i = 0; i <= MAX_SORT_LENGTH + 1; i++) { 
     source[i] = tempsort[i]; 
    } 
} 

但是有一些注意事項:

  • 函數定義本身( 簽名)由 講師提供,因此名稱,返回類型, 參數等不能被改變。 ,我們必須使用它(但我們 可以做任何我們想要的內部)。

  • 的代碼必須是ANSI/C90兼容 (GRR!)

誰能幫我找出什麼被吐出了這個功能造成這些奇怪的額外的字符 - 它做我的頭?

+2

我的猜測是一個編譯器初始化了一些東西(用0),而其他的不用。例如變量'i' – Anycorn 2011-04-05 04:35:19

+1

此代碼可能會導致[鼻惡魔](http://www.catb.org/jargon/html/N/nasal-demons.html) – 2011-04-05 04:39:08

+0

感謝您的出色建議,但我解決了這個問題 - 但錯誤仍然發生。 :( – Ash 2011-04-05 04:44:26

回答

5
int i,j,k; 
char c = source[i++]; 
i = j = k = 0; 

在爲其分配值之前,您正在使用i。您不能認爲自動變量將被初始化爲0

while (c != '\n' && c != '\0' && c != EOF) { 

因爲cchar,它永遠不能等於EOF。無關,但有一天你會看到這個bug :)你必須使用一個int這個成語:它初始化之前以及

int c; 

while((c=getchar()) != EOF) { 
    /* process c */ 
} 

您使用tempsort[]

 comp_c = tempsort[j]; 

你是寫入數據的很多source[]數組:

for (i = 0; i <= MAX_SORT_LENGTH + 1; i++) { 
    source[i] = tempsort[i]; 
} 

我希望source[]數組是保證要足夠大以容納MAX_SORT_LENGTH數據,而不是僅僅足夠容納標準C字符串。由於這可能是一位友善的教授,這可能是好的,但這不是我會輕易做出的假設。

作爲最後一個暗示,這些(int)演員中的每一個都是無用的;編譯器知道如何對變量進行比較和算術運算。 :)

+0

WOOHOO你修好了!這是tempsort,我把第一行改成了char tempsort [MAX_SORT_LENGTH + 1] = {'\ 0'};'現在它也可以運行!很多!我想有時很難看到代碼的錯誤,呵呵?我一直在盯着這個功能,感覺像是幾個小時! – Ash 2011-04-05 04:48:46

+0

感謝您的其他建議,它們也非常好 - 儘管在演員陣容中'(int)'強制轉換,我意識到它們不是必需的,但我仍然只學習C,它們適合我,而不是編譯器!:P – Ash 2011-04-05 04:50:13

+1

@Ash,excellent!:)當然,我一直盯着一段代碼太久,發現缺陷可能會很困難。這就是爲什麼在開發軟件非常重要時進行良好的[代碼審查](http://en.wikipedia.org/wiki/Code_review)過程的原因之一 - 新鮮眼睛可以找到不同的錯誤。 :) 玩的開心! – sarnold 2011-04-05 04:58:37

3

不知道這是什麼原因,但我注意到,你用我它的正確初始化之前:

char c = source[i++]; 
i = j = k = 0; 

你要翻轉過來,這兩行。

2

也許錯誤是沒有初始化本地變量我爲零。

2

一對夫婦的提示:

  • 如果你有對不同的系統顯示不同結果的程序,它往往是一個跡象表明它使用未初始化的數據
  • 你傳遞的「-Wall」(打印所有警告)標誌爲gcc,這很好,但是你可能想知道,如果你還使用「-O」(優化)標誌,gcc可以更好地檢測(並警告)未初始化的變量

另外,請仔細觀察循環中的邊界條件。你確定你沒有訪問超出陣列末尾的內存嗎?請記住,如果您有像char x[10]這樣的數組,有效值爲x[0]x[9]; x[10]超出界限。

+0

這是偉大的建議。我剛剛使用-O,但gcc沒有輸出任何內容(像以前一樣),所以我認爲這意味着它的一切都好? – Ash 2011-04-05 04:43:08

+0

您需要同時使用-O和-Wall。當我從上面複製的代碼上執行'gcc -O -ansi -Wall -pedantic'時,我得到了「警告:'我在這個函數中未被初始化使用」(正如許多人指出的那樣) – 2011-04-05 04:45:56

+1

@Ash,我也像'-Wextra',但在這種情況下,它沒有添加任何新的警告。 'WALL'實際上並不是警告。 :( – sarnold 2011-04-05 05:00:11