2011-07-18 165 views
2

我的問題是基本上使用printf打印一個字符數組。C的printf不打印字符串(字符數組)出來

在一些情況下,將打印結果出來:

int main(int argc, char** argv) { 
    char* orig = "@reveals#?the treasure chest#$President Barack H. Obama#"; 
    printf("The input: %s\n", orig); 
    printf("The output: %s\n", reArrange(orig)); 

    return (EXIT_SUCCESS); 
} 

有時不:

int main(int argc, char** argv) { 
    char* orig = "@reveals#?the treasure chest#$President Barack H. Obama#"; 
    printf("%s\n", reArrange(orig)); 

    return (EXIT_SUCCESS); 
} 

下面是完整的代碼(包含的主要功能):

#include <stdio.h> 
#include <stdlib.h> 
#include <string.h> 

#define SUBJECT '$' 
#define ACTION '@' 
#define OBJECT '?' 
#define END '#' 

char* reArrange(char* orig) { 
    int origSize = strlen(orig); 

    char subject[origSize], action[origSize], object[origSize]; 

//int i; 
//for(i = 0; i < origSize; i++) { 
// subject[i] = ' '; 
// action[i] = ' '; 
// object[i] = ' '; 
//} 
    int subjectIndex = 0, actionIndex = 0, objectIndex = 0; 

    int timesEndCharShowUp = 0; 

    char state; 
    int i; 
    for(i = 0; i < origSize; i++) { 
    char ch = orig[i]; 

    if(ch == SUBJECT) { 
     state = SUBJECT; 
    } 
    else if(ch == ACTION) { 
     state = ACTION; 
    } 
    else if(ch == OBJECT) { 
     state = OBJECT; 
    } 
    else if(ch == END) { 
     if(timesEndCharShowUp == 3) { 
     break; 
     } 
     else { 
     timesEndCharShowUp++; 
     } 
    } 
    else { 
     if(state == SUBJECT) { 
     subject[subjectIndex++] = ch; 
     } 
     else if(state == ACTION) { 
     action[actionIndex++] = ch; 
     } 
     else if(state == OBJECT) { 
     object[objectIndex++] = ch; 
     } 
    } 
    } 

    subject[subjectIndex] = '\0'; 
    action[actionIndex] = '\0'; 
    object[objectIndex] = '\0'; 

    char rearranged[origSize]; 
    sprintf(rearranged, "%s %s %s.\0", subject, action, object); 
    //printf("%s\n", rearranged); 

    orig = rearranged; 
    return orig; 
} 

int main(int argc, char** argv) { 
    char* orig = "@reveals#?the treasure chest#$President Barack H. Obama#"; 
// printf("The input: %s\n", orig); 
// printf("The output: %s\n", reArrange(orig)); 
    printf("result: "); 
    printf("%s\n", reArrange(orig)); 
//fflush(stdout); 

    return (EXIT_SUCCESS); 
} 

回答

1

你的功能需要兩個參數:

char* reArrange(char* orig) 

應該是:

char* reArrange(char *rearragned, char* orig) { 

// make your magic here! 

} 

調用順序:

char input[SIZE]; 
char rearrange [SIZE]; 

// initialize everything! Don't forget to rearrange[0] ='\0\;!!! 

rearrange(rearranged, input); 

// do you printing.... 

你也應該學會如何正確使用指針,並查找「開關」。

+0

'重新排列[0]'在這種情況下不需要初始化,儘管您可能會選擇這樣做。 – Clifford

5

您正在返回一個指向駐留在堆棧上的內存的指針。封閉函數(reArrange)返回並可能包含垃圾後rearranged不可用。

您可能想要mallocrearranged或全球聲明。

+1

...或聲明它是靜態的# – Clifford

+0

@Clifford:'static'確實意味着全局但只在封閉函數中可見。 –

+0

我明白了,但爲什麼'printf(「輸入:%s \ n」,orig); printf(「輸出:%s \ n」,reArrange(orig));'工作? – draw

1

問題是您的函數reArrange返回一個指向不再控制的內存的指針。返回rearranged數組的地址。返回發生後,該數組實際上不再存在 - 內存可以並且將被重用。

解決您的錯誤的快速入門程序是聲明rearrangedstatic。長期的解決方法是學習C如何工作並使用malloc()或相當的代碼進行編碼。

+0

其實在一些聲明靜態的情況既充分又安全;不一定是「黑客」。如果你在'reArrange()'中動態地分配它,你讓調用者負責處理它,所以調用者必須知道它是如何分配的。一個更好的(也是最傳統的)解決方案如@Rudy Velthuis所詳述的那樣,然後呼叫者決定分配和處置,這可能是也可能不是動態的。 「靜態」聲明會使函數不可重入,因此不是線程安全的 - 正如我在「某些情況下......」所說的那樣。 – Clifford

+0

@Clifford - 「其實,」聲明它是靜態的,這個函數就是非線程安全的。因此,這是一個黑客 - 尤其是當向不知道發生了什麼事的OP推薦時。 –

+0

是的,它使它非線程安全;這正是我所說的,沒有論據 - 我在某些情況下強調了兩次。在很多情況下,線程安全並不是問題;例如當應用程序不是多線程時,或者該函數僅用於單個線程中時。在單線程和多線程應用程序中,存在內存泄漏的可能性。正如我所說的最好的解決方案既不是這些,但我會放置靜態分配前返回一個動態分配的塊。 – Clifford

1

使用char rearranged[origSize];您創建了一個新的字符數組,一旦reArrange終止,超出範圍。所以在reArrange的生命期內,rearranged是一個指向有意義的指針;因此,orig = rearranged是有道理的。

但是,一旦它超出範圍,reArrange(orig)返回指針rearranged這是一個懸掛指針,現在rearranged不再存在。

3

而不是隻返回一個char *,使reArrange()接受它可以寫入結果的緩衝區。現在,調用者必須爲您的函數提供一個合適的緩衝區,並且您不再需要內存管理。你只需將strncpy()排列到緩衝區。爲了確保緩衝區足夠大,用戶還應該提供緩衝區的大小,在第三個參數:

char *rArrange(char *orig, char *result, int resultSize) 
{ 
    if (!result || resultSize == 0) 
     return NULL; 

    /* your code here */ 

    strncpy(result, arranged, resultSize); 
    return result; 
} 

替代malloc()存儲結果不是很用戶fiendly(用戶必須freemem在( )緩衝區,但可能不知道這一點)。使用靜態/全局緩衝區不是非常安全的。

0

您確定代碼的以下部分有效嗎?

char* reArrange(char* orig) { 
    int origSize = strlen(orig); 

    char subject[origSize], action[origSize], object[origSize]; 

我的意思是origSize必須是一個const它不能是一個動態值。您應該使用malloc分配subject , action and object的空格。 此外,你可能會考慮一些指導原則:

1相反的:

for(i = 0; i < origSize; i++) { 
    char ch = orig[i];  
    if(ch == SUBJECT) { 
     state = SUBJECT; 
} 

您可以:

char ch;//declare char ch outside for loop 
for(i = 0; i < origSize; i++) { 
    ch = orig[i]; 

    if(ch == SUBJECT) { 
     state = SUBJECT; 
    } 

2,你可以像使用switch聲明,而不是if,即會讓你的代碼看起來很棒。

+0

是的,該部分的作品。我去年夏天學習了C語言,然後在一年後,我很快就忘記了大多數非直觀的語言。真的,開關更好~~ – draw

+0

我對第一條指南感興趣,背後的原因是什麼? – draw