Thinkers'Studio
JavaとC言語の自習ツール
文字列を返す関数で注意すること

文字列の置き場所に注意しよう

 関数で処理した結果として文字列を返すとき、その置き場所に注意が必要です。
 整数を入力し、位取りのカンマを付加した文字列を返す関数c3str()を例にして説明します。

    int c3str( char* s, int n )

 この関数は、プログラミングTipsの9回で紹介したプログラムと似ていますが、処理の仕方が少し違っていて、別な処理方法の紹介も兼ねています。

【 位取りのカンマを付加した文字列を生成するプログラム 】
#include <stdio.h>

int c3str( char *s, int n )
//  changes n into a string with digit group separator comma
{
    char    buf[12];
    int     len, drp, i;

    if( n < 0 ) {
        *s++ = '-';
        n = -n;
    }
    sprintf( buf, "%d", n );
    len = strlen( buf );
    drp = len%3;
    *s++ = buf[0];
    for( i = 1; i < len; i++ ) {
        if( i%3 == drp ) *s++ = ',';
        *s++ = buf[i];
    }
    *s = '\0';
    return strlen( s );
}

 このプログラムは、生成した文字列を受け取るための器を呼び出し側で用意しています。しかし次のように、関数内で用意したら引数を減らすことができます。

#include <stdio.h>

char* c3str( int n )
//  changes n into a string with digit group separator comma
{
    static char result[16];
    char    *s = result, buf[12];
    int     len, drp, i;

    if( n < 0 ) {
        *s++ = '-';
        n = -n;
    }
    sprintf( buf, "%d", n );
    len = strlen( buf );
    drp = len%3;
    *s++ = buf[0];
    for( i = 1; i < len; i++ ) {
        if( i%3 == drp ) *s++ = ',';
        *s++ = buf[i];
    }
    *s = '\0';
    return result;
}

 この場合は、結果の文字列はその場で使ってしまうか、別な場所にコピーしておかないと、次の関数呼び出しで壊されてしまいます。たとえば、次のような使い方をすると問題を生じます。

main()
{
    int     n, i;
    char*   a[10];

    n = 1234567890;
    for( i = 0; i < 10; i++ ) {
        a[i] = c3str( n );
        n /= 10;
    }
    for( i = 0; i < 10; i++ ) {
        printf( "%15s\n", a[i] );
    }
}

【クイズ】
 上のmainを実行すると、どんな結果が得られるでしょう?    (答えは、次回のTips で ・・・)