0

ユーザーの選択に応じて、右または左にいくつかの文字を埋め込む関数を作成しています。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() 関数は文字列パラメーターを取り、その文字列をファイルに書き込みます。

4

3 に答える 3

2

関数の終了時にスコープ外になる一時スタック変数へのポインターを返しています。そのメモリは、他の関数呼び出しによって再利用される可能性があります(今後再利用されます)。最も簡単な解決策は、メモリを動的に割り当てconcatfreeから、呼び出し元に割り当てることです。

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

concat関数を次のように簡略化することもできます

char* tmp = malloc(len1+len2+1);
strcpy(tmp, a);
strcat(tmp, b);
return tmp;
于 2013-01-29T11:15:56.040 に答える
2
  1. 独自のバージョンの strcat を作成しないでください。
  2. 自動 (ローカル) 配列を返すべきではありません。関数が返された後は範囲外であり、使用すると未定義の動作が呼び出されます。

一部のメモリを消費して、動的に割り当てられたチャンクまたはメモリを返すか、(呼び出し先ではなく)呼び出し元malloc()で宣言された配列である入出力引数を使用して関数を呼び出します。

于 2013-01-29T11:18:15.560 に答える
1

返す結果を、返す関数内のスタックに割り当てます。

char tmp[100]

これは実際に機能する場合もありますが(通常の「クラシック」スタックのコンテンツは戻りによって壊れません)、返された文字列を別の呼び出しを行わずにすぐに別の場所で使用またはコピーする場合に限ります。2番目の呼び出し(システムコールを含む)を行うとすぐに、スタックが再利用され、ガベージが発生します。

戻る前に別の変数に参照を割り当てても効果はありません。

strdupファミリ関数の1つを使用して、複製されたコピーを返します(不要になったときに解放することを忘れないでください)。

于 2013-01-29T11:16:09.443 に答える