2014-01-11 166 views
1

我正在做一個項目,我必須創建一個Black Jack模擬。所以我開始創建一個套牌和一個繪圖函數。由於C中沒有字符串,因此我創建了兩個指針數組,將它們用作自定義字符串數組。問題是,當我打印卡片來查看其價值和適合度時,只有第一次打印出預期的內容。第二次是一團糟。誰可以給我解釋一下這個 ?這裏是我的代碼C無法打印兩次字符串

#include <stdio.h> 
#include <stdlib.h> 
#include <stdbool.h> 
char* suit[] = {"Diamonds", "Hearts", "Spades", "Clubs"}; 
char* facevalue[] = { "Seven", "Eight", "Nine", "Ten", "Jack","Queen", "King", "Ace"}; 
char* drawCard() 
{ 
    char* card[50]; 
    int cardNumber=rand()%8; 
    int cardColor=rand()%4; 
    strcpy(card,facevalue[cardNumber]); 
    char of[]=" of "; 
    char* xrwma =suit[cardColor]; 
    strncat(card,of,5); 
    strncat(card,xrwma,8); 
    return card; 
} 
int main() 
{ 
    srand(time(NULL)); 
    char* c=drawCard(); 
    puts(c); 
    puts(c); 
    return 0; 
} 

回答

5

問題是你正在返回一個指向自動數組的指針。一旦函數返回,數組就會超出範圍。試圖取消引用返回的指針導致undefined behaviourputs()的第一個電話雖然在技術上沒有定義,但恰巧適用於您的情況。第二個不是。

查看Returning a pointer to an automatic variable的討論。

一種解決方法是分配main()內部的數組,將指向它的指針(及其大小)傳遞給drawCard(),並讓drawCard()填充它。

+0

Thx隊友,它的工作 –

+0

另外,哪種解決方案更受歡迎?傳遞一個指向'drawCard()'或使用f.e'malloc'的指針?爲了有一個更清潔的代碼。 Thx –

1

嚴格地說,問題是drawCard()返回的自動變量的生命週期。它只適用於一個函數調用實例。 C不會阻止你返回它,但它在以後總是無用。

而原因是:當地人(自動存儲類)被分配在堆棧上。這真的是快;一個算術操作 - 從堆棧指針減去 - 可以分配函數中的每個本地。

但是當通話返回時,堆棧被調回。此時下一個函數調用實例將重用相同的空間。如果你堅持到該空間的參考,它會被表面隨機和不斷變化的東西...

2

變量card是函數drawCard中的本地數組。

因此,當功能drawCard執行時,它被分配在堆棧中。

函數drawCard返回後,不能再依賴此數組的內容。

任何後續操作可能會隨時覆蓋該內存。

事實上,您的程序在第一次調用puts時成功打印出來,只不過是「一件幸運的事情」 - 正確的字符正好存在於變量c指向的內存中,第一次調用功能fputs

但由於功能fputs也使用堆棧,此後不久,這段內存被覆蓋,並且在您再次調用fputs時,先前的字符值不再存在。

順便說一句,看着你對變量card的使用,我覺得你的意思是宣佈它爲char card[50]而不是char* card[50]

+0

+1'char * card [50]'。這意味着編譯器的警告沒有充分參與。 OP應該修復的東西。 – chux

+0

如果我只是聲明它爲'char * card',可以嗎? –

+0

好吧,'char * card = malloc(50 * sizeof(char))'或'char card [50]',無論你喜歡什麼。請記住,如果您選擇第一個選項,那麼您必須稍後調用'free(...)',如果選擇第二個選項,則不能在函數外部使用它。 –