1

cでsubstr関数を記述しましたが、substr関数内で戻り値を取得できますが、main関数で戻り値を取得できません。以下はすべてのコードです:

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

char* substr(char *source, int start, int length)
{
    char result[10];
    char *r = result;
    strncpy(result, source+start, length);
    printf("substr: %s\n", r);
    return r;
}

int main()
{
    printf("main: %s\n", substr("HELLO", 1, 2));
}

出力は次のとおりです。

substr: EL
main: 

私はcに精通していません、事前のおかげで、誰もがこれを修正するためのアイデアを得ることができます。

4

4 に答える 4

4

resultへの呼び出し中にのみ存在しますsubstr。あなたmainは悪い記憶を参照しています。

あなたはそれを修正することができます:

  • substrで結果を静的にします。
  • 結果を動的に割り当てる(解放することを忘れないでください)
  • 結果をグローバルにする

cthulhu( "Ph'nglui mglw'nafh Cthulhu R'lyeh wgah'nagl fhtagn")が指摘しているように、私の修正の1つを適用したとしても、文字列はnulで終了しません。

また、固定サイズの結果バッファーがあるため、10より長い部分文字列を要求すると、問題が発生する可能性があります。引数を確認するか、固定サイズのバッファーを使用しないでください。

私はこれをテストしていないので、「1つずれた」問題または2つの問題が隅に潜んでいる可能性があります...

/* 
 * Caller must free the results if they are non null 
 */
char* substr(char *source, int start, int length)
{
    /* If the input is NULL, return NULL */
    if (source == NULL) return NULL;

    int len = strlen(source);

    /* If the requested start is off the end of the string, return NULL */
    if (start > len) return NULL;

    /* If the requested length is 0 or less, return NULL */ 
    if (length <= 0) return 0;

    char *r = (char*)malloc(length + 1); /* allow space for null terminator */
    if (r != NULL) {
        int i = 0;
        while(source[start] != '\0' && i < length) {
            r[i++] = source[start++];
        }
        r[i] = '\0';
        printf("substr: %s\n", r);
    }
    return r;
}
于 2013-02-25T05:15:27.833 に答える
0

呼び出し元に値を返すことを期待している場合は、文字列が格納される場所を関数に渡す必要があります。strcpy のような標準ライブラリ関数がこれを行います。これは非常に簡単な例です。dest が既に宣言されており、それを格納するのに十分な大きさであると想定しています。

char * substr(char * dest, char * src, int start, int length)
{
    //  Move substring into passed destination pointer
    strncpy(dest, src + start, length);

    //  Append null to the end to terminate string
    dest[length] = 0;

    //  Return string pointer that can be used in printf and other places
    return dest;
}

int main(int argc, char const *argv[])
{
    char * test = "This is a test.";
    char * dest = malloc(10);
    printf("%s", substr(dest, test, 5, 2));
    free(dest);
    return 0;
}

出力: is

編集:関数内でmallocされた値を返すすべての人に、printステートメントでメモリを使用するだけでメモリを解放することをどのように期待しますか? それらは free へのポインタを受け取らず、メモリはそこにぶら下がったままになります。

于 2013-02-25T05:42:17.037 に答える
0

以下のコードは、ヒープにメモリを割り当てます。free終わったときの思い出だけ。strlcpy は、他の人が指摘しているように、常にその文字列を NUL で終了します。

#include <string.h>


char *
substr(char *s, int start, int len)
{
    char *ss;

    if(strlen(s) < start + len)
        return NULL;
    if((ss = malloc(len + 1)) == NULL)
        return NULL;
    strlcpy(ss, s + start, len);
    return ss;
}

int
main(void)
{
    char *s = substr("Hello World!", 6, 5);
    printf("%s\n", s);
    free(s);
    return 0;
}

印刷する必要がありますWorld

strlcpyDebian Linux で使用するには:

gcc -lcext -o prog prog.c

お使いのオペレーティング システムで提供されていない場合strlcpyは、ソースに自分で含めてください。これは BSD ライセンスの下でライセンスされています。つまり、ライセンス自体を含める限り、自由に使用、販売などを行うことができます。

strlcpy の実装は、OpenBSD の CVS Webにあります。

于 2013-02-25T05:45:37.053 に答える
-1

C の動的変数と静的変数

変数宣言は、すべての関数の外側または関数の内側にある可能性があります すべての関数の外側の宣言はグローバルであり、固定メモリ位置にあります static 宣言は、関数の外側の変数を「ファイル グローバル」として宣言します (他のソース ファイルのコードで参照することはできません) 宣言ブロック ステートメント {} (関数本体または関数本体内にネストされたブロック ステートメント) 内: 静的に宣言されていない限り、動的に割り当てられます プログラムの実行がブロックに入るときにメモリが割り当てられます 実行がブロックを出るときにメモリが解放されます 関数がそれ自体を呼び出す場合 (直接または間接的に)、動的変数の新しいセットを取得します(スタックフレームと呼ばれます)。これは、関数への他の呼び出しと同じように処理されます

問題があります。変数は、関数の側に割り当てられた変数です。動的変数result[]を作成する必要があるため、その有効期間は関数の実行全体に渡って延長されます(スタックに割り当てられます!)。result

修正コード:

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

char* substr(char *source, int start, int length)
{
    char* result;
    char *r;
    result=(char*)malloc(sizeof(char)*10);
    r = result;
    strncpy(result, source+start, length);
    printf("substr: %s\n", r);
    return r;
}

int main()
{
    char* r=substr("HELLO", 1, 2);
    printf("main: %s\n",r );
    free(r)//Don't forget to free it!
}

result[]または、次のようにグローバル変数を作成できます。

#include <stdio.h>
#include <string.h>
char result[10];//<======Global
char* substr(char *source, int start, int length)
{
    char *r=result;
    r = result;
    strncpy(result, source+start, length);
    printf("substr: %s\n", r);
    return r;
}

int main()
{
    printf("main: %s\n",substr("HELLO", 1, 2));
}
于 2013-02-25T05:41:23.600 に答える