回文判定

フォーラム(掲示板)ルール
フォーラム(掲示板)ルールはこちら  ※コードを貼り付ける場合は [code][/code] で囲って下さい。詳しくはこちら
keiji

回文判定

#1

投稿記事 by keiji » 14年前

質問失礼します。

今、文字列が回文になっているかどうか
判定するプログラムを作っています。
(回文なら1、違うなら0を返す。)

コード:

int kaibun(char *l, char *r){     //文字列中へのポインタlとrを与える//
if(l == r || r < l) return 1;
 
 if(l[0] == r[0]){
   l++; r--;
  return sym(l, r);
  } 
 else return 0;
}
こんな感じにしてみたのですが、
これをまた使って、
文字列strの中からn(整数)文字の回文が存在するか調べ、
存在すればその先頭位置へのポインタを返し、無ければNULL
を返す関数をつくっています。

コード:

char nkaibun(char *str, int n){

以降が、なかなか分かりません。
str[0],str[1],...,str[n],....を再帰で順に調べて行こうと思っているのですが、
関数kaibunの使い方が分からず困っております。

ご教授、よろしくお願いします。

beatle
記事: 1281
登録日時: 14年前
住所: 埼玉
連絡を取る:

Re: 回文判定

#2

投稿記事 by beatle » 14年前

関数symの動作が分からないと関数kaibunの動作が分かりません。
それから、kaibunの引数lとrには具体的に何を渡すのですか?

nkaibun、kaibunの使用例を示していただければ、答えやすくなると思います。

keiji

Re: 回文判定

#3

投稿記事 by keiji » 14年前

すみません。
symはkaibun のことです。 書き間違えです。

lとrは任意で、ある文字列の中で
*lと*rを両端とした文字列で判定するプログラムです。

よろしくお願いします。

keiji

Re: 回文判定

#4

投稿記事 by keiji » 14年前

例ですが、
(kaibun)
level -> return 1;

(nkaibun)
aiuleveldv    ->(n(5とする)文字の文字列の中に回文level(5文字))
が存在 ->その先頭位置へのポインタを返す。

といったかんじです。
分かりにくくてすみません。

keiji

Re: 回文判定

#5

投稿記事 by keiji » 14年前

例ですが、
(kaibun)
level -> return 1;

(nkaibun)
aiuleveldv    ->(n(5とする)文字の文字列の中に回文level(5文字))
が存在 ->その先頭位置へのポインタを返す。

といったかんじです。
分かりにくくてすみません。

beatle
記事: 1281
登録日時: 14年前
住所: 埼玉
連絡を取る:

Re: 回文判定

#6

投稿記事 by beatle » 14年前

symはkaibunのことなのですね。ということは関数kaibunは以下の定義となりますね。

コード:

int kaibun(char *l, char *r)     //文字列中へのポインタlとrを与える
{
  if(l == r || r < l) return 1;

  if(*l == *r)
  {
    l++;
    r--;
    return kaibun(l, r);
  }
  else
  {
    return 0;
  }
}
keiji さんが書きました:関数kaibunの使い方が分からず困っております。
というのは、
  • kaibunに具体的にどんな引数を渡せばいいのか、戻り値をどうやって使えばいいのかが分からない
    (lavelが回文かどうか調べるには、kaibunにはどんな引数を渡せばいいか分かりますか?)
  • kaibunに渡す引数や戻り値の使い方は分かるが、kaibunの使い所が分からない
のどちらでしょうか。

keiji

Re: 回文判定

#7

投稿記事 by keiji » 14年前

すみません。
関数自体は作ってみましたが、
どちらの方も、あいまいで理解していませんでした。
渡す引数、使いどころ、ifによる条件がよくわからない状態です。
よろしくお願いします。

beatle
記事: 1281
登録日時: 14年前
住所: 埼玉
連絡を取る:

Re: 回文判定

#8

投稿記事 by beatle » 14年前

渡す引数も分からないのによくあんな再帰関数が書けましたね。脱帽です。
関数を作った人じゃない人が関数の使い方を説明するというよく分からない状況ですが、僕が読み取ったkaibun関数の使い方を書きます。

kaibun関数
  • 引数 l 回文かどうかを判定したい文字列の左端文字へのポインタを渡す
  • 引数 r 回文かどうかを判定したい文字列の右端文字へのポインタを渡す
  • 戻り値 渡されたポインタl, rで表される範囲の文字列が回文ならば真、そうでなければ偽を返す
使用例

コード:

char *str; /* 回文判定したい文字列への先頭ポインタ */
size_t len; /* 回文判定したい文字列の長さ */

/* str, lenに適切な値を設定 */

if (kaibun(str, str + len))
{
    /* str, str + lenの範囲にある文字列は回文 */
}
これでkaibun関数の動作と使い方は分かったと思いますので、nkaibunの作り方をもう一度ご自分で考えてみてください。

keiji

Re: 回文判定

#9

投稿記事 by keiji » 14年前

すみません。
説明をよく理解してませんでした。

l,rが文字列の両端を指していることは大丈夫です。
それを実際にどう文字列strで使うのかを理解していませんでした。

beatleさんの解説を参考にもう一度考えてみたいと思います。
丁寧な対応ありがとうございます。

beatle
記事: 1281
登録日時: 14年前
住所: 埼玉
連絡を取る:

Re: 回文判定

#10

投稿記事 by beatle » 14年前

一つ訂正します。
strに判定したい文字列の先頭へのポインタ、lenに判定したい文字数が入っている場合、

コード:

kaibun(str, str + len - 1)
としてください。kaibunの第二引数には、右端文字へのポインタを渡さなければならないので、str + lenから1を引きます。
str + lenだと、右端文字を1文字超えた場所へのポインタになってしまいます。

keiji

Re: 回文判定

#11

投稿記事 by keiji » 14年前

コード:

int kaibun(char *l, char *r){
 if(l ==r || r<l) return 1;

 if(*l == *r) return kaibun(l+1, r+1);

else return 0;
}

dhar *nkaibun(char *str, int n){
 if(kaibun(str, str+n-1) == 0){
  str++;
  return nkaibun(str+1, n);
  }
  else if(kaibun(str, str+n-1) == 1){
  return str;
  }
   else return NULL;
}
まで自分で書いてみました。

これを更に使って、
与えられた文字列strから最長の回文を探して、文字列として切りだして返す関数を考えています。

コード:

char *mkaibun(char *str) {
 int m = strlen(str);
 int i;
     for(i=m;i>0,i--){
        nkaibun(str,i);
       if(nkaibun(str,i) != NULL){
         int k = i;
         break;
        }
     }
    char *c = (char *)malloc(k+1);
    c = nkaibun(str,k);
   printf("%s", c);
 }
とういう感じで考えてみたのですが、
根本的に上手くいかない気がします。

間違っている部分や考え方を指摘していただけないでしょうか?
よろしくお願いします。

keiji

Re: 回文判定

#12

投稿記事 by keiji » 14年前

すみません。
自分で考えてみます。

non
記事: 1097
登録日時: 15年前

Re: 回文判定

#13

投稿記事 by non » 14年前

keiji さんが書きました:

コード:

int kaibun(char *l, char *r){
 if(l ==r || r<l) return 1;

 if(*l == *r) return kaibun(l+1, r+1);

else return 0;
}

dhar *nkaibun(char *str, int n){
 if(kaibun(str, str+n-1) == 0){
  str++;
  return nkaibun(str+1, n);
  }
  else if(kaibun(str, str+n-1) == 1){
  return str;
  }
   else return NULL;
}
まで自分で書いてみました。
自分で作りたいというのですから、口出し無用なのでしょうけど・・・・
このプログラムさっぱりわかりません。
non

かずま

Re: 回文判定

#14

投稿記事 by かずま » 14年前

さっぱり分からないまま解決済みになってしまったので、もやもや感が取れません。
そこで、こういうものを作りたかったんだろうと予想して書いてみました。
kaibun() も nkaibun() も末尾再帰なので、簡単にループに変換できます。
なぜ、再帰呼び出しを使ったのか、最初の質問者に聞いてみたいですね。

コード:

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

int kaibun(char *l, char *r)
{
    if (l >= r ) return 1;
    if (*l != *r) return 0;
    return kaibun(l + 1, r - 1);
}

char *nkaibun(char *str, int n)
{
    if (strlen(str) < n) return NULL;
    if (kaibun(str, str + n - 1)) return str;
    return nkaibun(str + 1, n);
}

char *mkaibun(char *str)
{
    int n;
    for (n = strlen(str); n > 0; n--) {
        char *p = nkaibun(str, n);
        if (p) {
            char *q = malloc(n + 1);
            if (!q) return NULL;
            memcpy(q, p, n);
            q[n] = '\0';
            return q;
        }
    }
    return NULL;
}

int main(void)
{
    char *s = "aiuleveldv";
    char *t = mkaibun(s);
    puts(s);
    if (t) {
        puts(t);
        free(t);
    }
    return 0;
}

閉鎖

“C言語何でも質問掲示板” へ戻る