1

関数を必要とするコードに取り組んでいます。この関数は、入力として文字列を取得し、文字列を返します。

これまでに計画したのは、を取得しstr[]、すべてのスペースとスペースを削除して$、後で返される別の文字列にこれを格納することです。

char *getstring(char str[])
{
    int i=0;
    char rtn[255];
    while (i<strlen(str))
    {
       if (str[i] != " " || str[i] != "$" )
             rtn[i] = str[i];
       else
             rtn[i] = '';
    } 
    return str;
}

私はこれがうまくいくとは思わない。何か案は??:-S

4

4 に答える 4

2

問題#1:
関数は、スタックに割り当てられている(一時的な)文字列へのポインタを返します。これは、関数が終了すると、のメモリrtnが解放され、関数が返すポインタが無効になるchar *ことを意味します。

あなたがむしろしたいことは:

void getstring(char str[], char rtn[])
{
    /* Some processing on rtn... */
}

の呼び出し元getstringは、として渡された文字列の割り当てと割り当て解除を処理する必要がありますrtn

問題#2
whileループは無期限に実行されます。これは、i決して増加しないためです。i++ループ内のどこかに置きます。

問題#3:ステートメント
の状態に問題ifがあります。文字列リテラル(最後にある)である、、または、str[i]と比較します。これは間違っています。 それらを(引用符ではなく)アポストロフィで示される文字と比較する必要があります。 また、テスト条件も間違っていることに注意してください。ORの代わりに論理AND演算子が必要です。-ステートメントを次のように変更します。char" ""$"'\0'


if

if (str[i] != ' ' && str[i] != '$')

問題#4
どういうrtn[i] = '';意味ですか?''空の文字定数であり、Cでは無効です。
で文字をスキップしたいstrですか?

問題#5
インデックス作成に問題があります。strとは明らかに長さが異なる可能性があるためrtn、文字列ごとに1つずつ、2つの実行中のインデックスを管理する必要があります。

問題#6
rtn関数が戻ったときに必ずしもnullで終了するわけではありません。関数が戻る前(つまり、-loopが終了した後)'\0'の終わりに割り当てます。rtnrtn[i] = '\0';while


上記のすべての問題が修正されたコードは次のとおりです。

void getstring(char str[], char rtn[])
{
    int i = 0, j = 0;
    while (i < strlen(str))
    {
       if (str[i] != ' ' && str[i] != '$')
             rtn[j++] = str[i];
       i++;
    }
    rtn[j] = '\0';
}

そして、これはインデックスの代わりにポインタを使用し、使用しないより効率的なバージョンですstrlen

void getstring(char *str, char *rtn)
{
    while (*str)
    {
       if (*str != ' ' && *str != '$')
             *rtn++ = *str;
       *str++;
    }
    *rtn = '\0';
}
于 2012-06-30T11:17:51.783 に答える
1

それは間違いなく機能しません。'i'カウンターをインクリメントしておらず、''の割り当てはシンボルをスキップしません。

インプレースバリアント(速度の点で最適ではありません)

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

void getstring(char* str)
{
    int j, i = 0, len = strlen(str);

    while(i < len)
    {
        char ch = str[i];

        if(ch == ' ' || ch == '$')
        {
            /// shift by one
            for(j = i ; j < len + 1; j++) { str[j] = str[j + 1]; }

            len--;
            i--;
        }

        i++;
    } 

    str[len] = 0;
 }

 int main()
 {
      char test_string[] = "Some string $with$ spaces";

      printf("Src = %s\n", test_string);
      getstring(test_string);
      printf("Res = %s\n", test_string);
      return 0;
 }

そして、再割り当てを伴うバリアント

char *getstring(const char* str)
{
    int i_src = 0;
    int i_dest = 0;
    int len = strlen(str);

    char* rtn = (char*)malloc(len + 1);

    while (i_src < len)
    {
       char ch = str[i_src];
       if ( (ch != ' ') && (ch != '$') )
       {
            rtn[i_dest] = ch;
            /// increment destination index here
            i_dest++;
       }
       /// increment the source index always
       i_src++;
    } 

    rtn[i_dest] = 0;

    return rtn;
}

後で結果をfree()することを忘れないでください。

于 2012-06-30T11:21:25.993 に答える
0
  1. 関数から新しい文字列を返したい場合は、文字列に動的にメモリを割り当てる必要があります。スタックにchar rtn[255];メモリを割り当てるコードでは、関数を終了した後にメモリが消去されます。rtnあなたは書くべきです:

    char * rtn =(char *)malloc(strlen(str));

    もちろん、メモリリークを防ぎ、メモリfree()を解放するために呼び出すために、メモリを追跡し続ける必要があります。

  2. ''の割り当てはシンボルをスキップしません。i望ましくないシンボルが表示された場合(そしてコードでインクリメントを見逃した場合)はインクリメントしないでください。

  3. 間違った値を返しています。rtn代わりに返す必要がありstrます。

正しいコードは次のようになります。

char *getstring(char str[])
{
    int i=0, rtn_pos = 0;
    size_t len = strlen(str);
    char *rtn = (char*) malloc(len + 1);
    for (i = 0; i < len; ++i)
       if (str[i] != ' ' && str[i] != '$' )
             rtn[rtn_pos++] = str[i];
    rtn[rtn_pos] = '\0';
    return rtn;
}
于 2012-06-30T11:28:17.023 に答える
0

呼び出し元に宛先文字列を提供させ(呼び出し元はおそらくその大きさを知っているはずです)、それがわからないもの、つまりrtn[]配列に書き込まれたバイト数を返す方がよいでしょう。

size_t mygetstring(char *rtn, char *str)
{
    size_t pos, done;

    for (pos=done=0; rtn[done] = str[pos]; pos++)
    {
       if (rtn[done] == ' ' || rtn[done] == '$' ) continue;
       done++;
    } 
    return done; /* number of characters written to rtn[], excluding the NUL byte */
}
于 2012-06-30T11:51:30.737 に答える