3

私はいくつかのプログラミングの問題を練習していて、人気のある「文字列内の逆の単語」の問題をコーディングしようとしました。

私はCで自分のコードを考え出そうとしました。部分的に正しくすることができます。つまり、「helloworld」は「worldolleh」になります。バグはここにあるのだろうかと思います。どこかで1つのバグを作成していると思います。

なるべくライブラリ関数を使わずにやりたかったのです。ここでこの問題を検索して多くの解決策を見つけましたが、なぜ私の解決策が機能しないのか知りたいです。

コードは次のとおりです。

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

void reverse(char*, int);

int main(int argc, char **argv)
{
    char st[]= "hello world";
    int len = strlen(st);
    int i=0,j=0;

    reverse(st,len-1); // Reverse the entire string. hello world => dlrow olleh

    while(st[j]){ //Loop till end of the string
        if ( *(st+j) == ' ' || *(st+j) == '\0' ) { //if you hit a blank space or the end of the string
            reverse(st+i,j-1); // reverse the string starting at position i till position before the blank space i.e j-1
            i=++j; //new i & j are 1 position to the right of old j
        }
        else {
            j++; //if a chacacter is found, move to next position
        }               
    }       

    printf("%s",st);
    return 0;
}

void reverse(char *s, int n)
{
    char *end = s+n; //end is a pointer to an address which is n addresses from the starting address
    char tmp;
    while (end>s)  //perform swap
    {
        tmp = *end;
        *end = *s;
        *s = tmp;
        end--;
        s++;
    }
}

ありがとうございました!

更新:@Daniel Fischerの回答に基づいて、正しい実装は次のとおりです:http: //ideone.com/TYw1k

4

4 に答える 4

3

問題はそれです

while(st[j]){ //Loop till end of the string
    if ( *(st+j) == ' ' || *(st+j) == '\0' )

このwhile条件により、文字列の最後にループが入ることが防止されるため、最後の単語が再び反転することはありません。

無限ループにして、追加することができます

if (st[j] == '\0') break;

逆にした後、またはwhileループが残った後の最後の単語を逆にします。

于 2012-07-01T00:35:36.387 に答える
3

あなたは確かに1つのエラーでオフになっています:呼び出し

reverse(st+i,j-1);

する必要があります

reverse(st+i,j-i-1);

j-1文字列の先頭から最後のスペースの位置までの長さであるコードが渡されます。これは最後の単語の長さである必要があるため、最初の文字のインデックスを引く必要があります(つまりi)。

また、最後の単語を逆にすることもありません(詳細については、他の回答を参照してください)。

于 2012-07-01T00:40:23.810 に答える
0

文字列全体を逆にしてから1つの単語を逆にするのではなく、文字列内の単語を逆にしたいと思います。したがって、最初にリバースを削除してから、上記の提案された変更を適用します。

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

void reverse(char*, int);

int main(int argc, char **argv)
{
  char st[]= "hello world";
  int i=0, j=0;

  while(st[j]){ //Loop till end of the string
    if ( st[j] == ' ') { //if you hit a blank space or the end of the string
      reverse(&st[i], j - i - 1); // reverse the string starting at position i till position before the blank space i.e j-1
      i = ++j; //new i & j are 1 position to the right of old j
    }
    else {
      j++; //if a chacacter is found, move to next position
    }               
  }
  reverse(&st[i], j - i - 1);


  printf("%s\n",st);
  return 0;
}

void reverse(char *s, int n)
{
  char *end = s + n; //end is a pointer to an address which is n addresses from the    starting address
  char tmp;

  while (end > s)  //perform swap
  {
    tmp = *end;
    *end = *s;
    *s = tmp;
    end--;
    s++;
  }
}

入力文字列が「\0」または「Helloworld」のようなものになる場合は注意してください。上記のコードは、この種の状況を管理していません。考えてみてください!

于 2012-07-01T01:07:54.277 に答える
0

@RBK:最初に文字列を取得して反転し、次に特定の単語に基づいて再度反転します。私はこれを行うために少し異なるアプローチに従いました。文字列を取得し、必要に応じて逆にします。それ以外の場合は、同じ単語をそのままコピーします。

int main(int argc, char*argv[])
{
    char *p,st[]= "hello world";
    char buf[12]={0};
    char fstr[12]={0};
    int i=0,j=0,k=0,l=0;

    for(p=st;*p!='\0';p++){

        //Get the Word
        buf[i++] = *p;

        //Parse the Word    
        if(*p == ' ' || *(p+1) == '\0'){

            buf[i]='\0';
            j=i-1;
            i=0;        //reset counter

            if(k){      //reverse word and copy

                while(j>=i){

                    fstr[l++]=buf[j--];

                }               

                k=0;        

            }
            else{       //copy same word

                while(i<=j){

                    fstr[l++]=buf[i++];                     

                }

                i=0;    //reset counter
                k=1;

            }

        }

    }   

    fstr[l]='\0';
    printf("%s\n",fstr);
    return 0;
}
于 2012-10-10T05:44:46.323 に答える