2011-07-18 141 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