为什么从我的函数返回的字符串打印为垃圾?

时间:2012-02-25 04:09:13

标签: c string

我正在尝试将字符串转换为大写字母,例如将test.pdf转换为TEST.PDF。但是,当我尝试使用printf打印返回值时,它会打印一些垃圾值。我究竟做错了什么?

char *covertToUpper(char *str)
{
    int i = 0;
    int len = 0;

    len = strlen(str);
    char newstr[len+1];

    for(i = 0; str[i]; i++)
    {
       newstr[i] = toupper(str[i]);
    }
    //terminate string
    newstr[i]= '\0';
    return  newstr;
}

9 个答案:

答案 0 :(得分:11)

你得到垃圾的原因是因为你在堆栈上分配“newstr然后返回它的值。这是C中的一个大禁忌。之后你调用的每个函数,包括{{ 1}}函数本身,将践踏你刚刚分配的内容。

不幸的是,C是一种危险的语言。它不会阻止您将在堆栈上分配的字符串返回给调用函数,即使该函数在返回时声明的函数不再安全使用。

不是以这种方式分配字符串,而是需要使用printf()malloc()为堆分配新的内存,并设置calloc()指向它。例如,您可以声明:

newstr

当然,当它不再使用时,需要适当地char newstr = malloc(len);

答案 1 :(得分:10)

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

char *covertToUpper(char *str){
    char *newstr, *p;
    p = newstr = strdup(str);
    while(*p++=toupper(*p));

    return newstr;
}

int main (void){
    char *str = "test.pdf";
    char *upstr;

    printf("%s\n", str);
    upstr=covertToUpper(str);
    printf("%s\n", upstr);
    free(upstr);
    return 0;
}

答案 2 :(得分:3)

你正在返回newstr,但它在堆栈上声明,所以当函数结束时,它的未定义会发生什么。您需要将指针传递给新的str或malloc,或者只是转换到位的指针。

在这种情况下,最有用的是传入newstre的指针和newstr的长度(说明你可以在newstr中使用多少空间)。这种方式在转换为大写时你没有绑定malloc,你可以为src和dest传递相同的指针,它将在适当的位置执行)

如果你想要一个具有malloc功能的函数,写一个第二个函数(带有一个暗示其分配内存的名称),它分配内存并使用带有指针的那个

答案 3 :(得分:2)

newstr数组不存在于covertToUpper函数范围之外。你必须:

  • dinamically alocate the array(稍后必须free'),将char newstr[len+1];更改为char *newstr = malloc(len + 1)
  • 将字符串转换为
  • 将destinantion指针作为参数(以及安全性的maxlen):

    int covertToUpper(const char* src, char* dst, int maxlen) {
      int i, len, max;
      len = strlen(str);
      max = len < maxlen? len : maxlen;
    
      for(i = 0; i < max; ++i) {
        dst[i] = toupper(src[i]);
      }
      dst[i] = '\0';
    
      return i;
    }
    

答案 4 :(得分:2)

您可以在不使用库函数的情况下将字符串转换为大写。使用一些ASCII数学可以是更好的解决方案:

void toUpper(char *text, char *nText){
    for(int i=0; i<=strlen(text); i++){
        if( (text[i] > 96 ) && (text[i] < 123) ) // if the char is lower case
            nText[i] = text[i] - 'a' + 'A';   //make upper
        else
            nText[i] = text[i]; //do nothing
    }   
}

函数调用:

char stuff[] = "test.pdf";
char result[100];

toLower(stuff, result);
printf("toLower: %s", result);

答案 5 :(得分:1)

void strupper(char *s) {
    while (*s) {
        if ((*s >= 'a' ) && (*s <= 'z')) *s -= ('a'-'A');
        s++;
    }
}

答案 6 :(得分:1)

其他答案已经回答了为什么OP代码不起作用。现在这是一个非常简单的(在我看来)更好的方法:

#include <string.h>
#include <ctype.h>

int strupp(char *s) {
    int i;
    for (i = 0; i < strlen(s); i++)
        s[i] = toupper(s[i]);
    return i;
}

因为通常您希望将相同的字符串转换为大写,而不是使用新副本来使用更多内存。如果您确实需要新副本,则可以在调用转换为大写的函数之前始终执行此操作。无需混合任务并使其更复杂。

答案 7 :(得分:1)

稍作修正。 'Z'和'a'之间还有一些其他的符号:[] \ ^等。 您可以使用此限制从0到122

   /*A=63 Z=90 a=97 z=122*/
   while((i>= 0 && i<=64) || (c>=89 && c<=96)){

必须!对面。

这就是美:

 while(str[i])
   {
      putchar (toupper(str[i]));
      i++;
   }

答案 8 :(得分:0)

#include<stdio.h>
#include<conio.h>
#include<string.h>
void *TakeString(char*);
void main()
{
    char *name;
    clrscr();
    TakeString(name);
    puts(name);
    getch();
}
void *TakeString(char *v)
{
    int i;
    gets(v);
    for(i=0;i<strlen(v);i++)
    {
        v[i]=toupper(v[i]);
    }
}