如何将字符串返回给另一个函数?

时间:2013-01-29 11:12:01

标签: c

我正在制作一个根据用户的选择在右侧或左侧填充几个字符的功能。我使用strcat函数将字符连接到字符串,并且在正确填充的情况下它工作正常,但是在左边填充时我得到了垃圾字符,所以我编写了自己的concat函数。结果仍然相同,请参阅下面的代码。

char *concat(char a[], char b[])
{
    int len1=0, len2=0, i, j;
    char tmp[100], *tmp2;
    trace("concat(): Begin");
    len1 = strlen(a);
    len2 = strlen(b);
    for(i=0, j=0; i<(len1+len2); i++)
    {
        if(i<len1)
            tmp[i]=a[i];
        else
            tmp[i]=b[j++];
    }
    tmp[i]='\0';
    tmp2 = tmp;
    sprintf(str, "Concatenated String: %s", tmp2);
    trace(str);
    trace("concat(): End");
    return tmp2;
}

char *pad(char *field_name, char *field_val)
{
    char *temp_var=field_val, *temp_var2;
    int i=0;
    char pad_var[100];

    trace("pad(): Begin");
    sprintf(str, "field name to search for: %s and field value to be formatted: %s", field_name, field_val);
    trace(str);
    get_format_vars(field_name);
    sprintf(str, "strlen(field_val) = %d and len = %d", strlen(field_val), len);
    trace(str);
    if(strlen(field_val)<len)
    {   
        trace("Data should be Padded"); 
        trace(field_val);
        for(i=0; i<len-strlen(field_val); i++)
        {   
            pad_var[i] = pc;
        }
        pad_var[i]='\0';
        sprintf(str, "pad_var = %s", pad_var);
        trace(str);

        switch(pd)
        {
            case 'l':
            case 'L':
            sprintf(str, "length of field: ", strlen(field_val));
            temp_var = concat(pad_var, field_val);
            sprintf(str, "Value after left padding: (%.*s)", len, temp_var);
            trace(str);
            break;
        case 'r':
        case 'R':
            strcat(field_val, pad_var);
            temp_var = field_val;
            sprintf(str, "Value after right padding: (%s)", temp_var);
            trace(str);
            break;
        case 'n':
        case 'N':
        trace("No formatting to be done for this field");
        break;
        default:
            trace("Wrong value for padding type.");
    }
    trace("Data Padded");

}
else
{   
    trace("Field length already equal to format length");
}
temp_var2 = temp_var;
sprintf(str, "Data after/without formatting: (%s)", temp_var2);
trace(str);
trace("pad(): End");
return temp_var;
}

请注意,上述程序在正确填充的情况下完全正常。

请让我知道我做错了什么,因为当我做左边填充时,它会在最后显示垃圾字符。

注意:程序中没有引用的函数和变量在我的程序中全局声明,如函数“trace”和变量“pd”。 trace()函数接受一个字符串参数并将该字符串写入文件。

3 个答案:

答案 0 :(得分:2)

当函数退出时,您将返回指向超出范围的临时堆栈变量的指针。其内存可能(将)被其他函数调用重用。最简单的解决方法是在concat中动态分配内存,然后在调用方中free动态分配内存。

char* tmp = malloc(len1+len2+1);

您还可以将concat功能简化为

char* tmp = malloc(len1+len2+1);
strcpy(tmp, a);
strcat(tmp, b);
return tmp;

答案 1 :(得分:2)

  1. 您不应该编写自己的strcat版本。
  2. 你不应该返回一个自动(本地)数组 - 它在函数返回后超出范围,使用它调用未定义的行为。
  3. malloc()使用一些内存并返回动态分配的块或内存,或者使用输入/输出参数调用函数,该参数是在调用者中声明的数组(相反)到被叫者。)

答案 2 :(得分:1)

您在返回函数内的堆栈上分配返回的结果:

char tmp[100]

这实际上甚至可以工作(通常的“经典”堆栈的内容不会被返回打破),但只要你在其他地方使用或复制返回的字符串而不再创建另一个呼叫。一旦你进行第二次调用(包括系统调用),堆栈就会被重用,你会得到垃圾。

在返回之前将引用分配给另一个变量无效。

使用其中一个strdup系列函数返回克隆副本(不要忘记在不再需要时释放)。