掲示板ランキング  インターネット・Web開発(Web開発)


掲示板利用宣言

 次のフォームをすべてチェックしてからご利用ください。

 私は

 題名と投稿者名は具体的に書きます。
 課題の丸投げはしません。
 ソースの添付は「HTML変換ツール」で字下げします。
 返信の引用は最小限にします。
 環境(OSとコンパイラ)や症状は具体的に詳しく書きます。
 返信の付いた投稿は削除しません。
 マルチポスト(多重投稿)はしません。

掲示板1

管理者用メニュー    ツリーに戻る    携帯用URL    ホームページ    記事検索    ログ    タグ一覧

No.6591

回文の判定について
投稿者---蒼1228(2006/10/06 23:30:22)


はじめまして。蒼と申します。
今回は「回文の判定」についてお伺いしたく書き込ませて頂きました。

入力された文字列について、回文(トマトのようにどちらから
読んでも同じ文)かどうか判定するにはどうしたらよいのでしょうか?

一応、

1.入力された文字数を数える
2.入力文字列Aを逆順にして、別の配列Bに代入する
3.Aのi番目とBのi番目を、iがヌル文字に達しない限り
 比較し続ける
4.結果、すべて等しければ回文、そうでなければ回文ではない

というように考えたのですが、実際にプログラムが書けません。
2までは自力で書けました。
どなたか3以降について教えて頂けないでしょうか。
Borland C++ Compilerを使用しています。

宜しくお願い致します。




この投稿にコメントする

削除パスワード

発言に関する情報 題名 投稿番号 投稿者名 投稿日時
<子記事> Re:回文の判定について 6592 nano 2006/10/06 23:52:00
<子記事> Re:回文の判定について 6593 Blue 2006/10/06 23:54:20
<子記事> Re:回文の判定について 6594 たかぎ 2006/10/07 00:17:27
<子記事> Re:回文の判定について 6596 shu 2006/10/07 14:04:31
<子記事> Re:回文の判定について 6597 かずま 2006/10/07 15:28:29
<子記事> Re:回文の判定について 6598 2006/10/07 16:22:21


No.6592

Re:回文の判定について
投稿者---nano(2006/10/06 23:52:00)


>2までは自力で書けました。

どんなコードですか?

ところで、回文かどうかを判定する文字列に2バイト文字を含んでいると、
回文判定を前提とした逆順にする処理がとたんにややこしくなりますが、
そのあたりはおわかりですか?

例えば、"トマト"という、2バイト文字3つからなる文字列を
単純に逆順にしても、"トマト"にはなりません。
"ト"の2バイト目
"ト"の1バイト目
"マ"の2バイト目
"マ"の1バイト目
"ト"の2バイト目
"ト"の1バイト目
の順になりますので、一部が文字化けしたように見えることでしょう。


この投稿にコメントする

削除パスワード

No.6593

Re:回文の判定について
投稿者---Blue(2006/10/06 23:54:20)


>2までは自力で書けました。
自力で?
2バイト文字を扱う以上、文字コードを意識してかかないといけませんが。

参考:http://c-chat.net/modules/newbb/viewtopic.php?topic_id=377&forum=2&post_id=2003#forumpost2003


この投稿にコメントする

削除パスワード

No.6594

Re:回文の判定について
投稿者---たかぎ(2006/10/07 00:17:27)
http://takagi.in/


>2までは自力で書けました。
>どなたか3以降について教えて頂けないでしょうか。
>Borland C++ Compilerを使用しています。

ヒントだけ。

まず、アルファベットだけで作ってみる。
それができたら、ワイド文字列を使って、同じように作ってみる。
次に、ワイド文字列中の文字が、仮名だけかどうかを判定する。
最後に、ワイド文字列中の文字を、ひらがなとカタカナの区別無しで比較できるようにする。

これで概ね何とかなるはずです。
後は、半角カナや拗音や撥音をどう扱うかですね。

もし、漢字の読みまで含めて回文かどうかを判定するのであれば、辞書を持たなければならないので大変です。



この投稿にコメントする

削除パスワード

No.6596

Re:回文の判定について
投稿者---shu(2006/10/07 14:04:31)


//
//	半角専用
//

#include <stdio.h>

int main(void)
{
    char s[BUF_SIZ] = "", *p, *p2;
    const char *mess[] = {"kaibun", "hikaibun"};
    
    while (fgets(s, sizeof(s), stdin)) {
    
        for (p2 = s; *p2; p2++) {
            if (*p2 == '\n') {
                break;
            }
        }
        
        for (p = s, --p2; p < p2; p++, p2--) {
            if (*p != *p2) {
                break;
            }
        }
        
        printf("%s: %s", mess[p < p2], s);
    }
    
    return 0;
}



この投稿にコメントする

削除パスワード

No.6597

Re:回文の判定について
投稿者---かずま(2006/10/07 15:28:29)


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

int main(void)
{
    char s[201], *k = "あ";  int i, j;

    puts("平仮名のみ入力してください (「がゃっ」などは「かやつ」で)");
    while (scanf("%200s", s) == 1 && *s == *k) {
        for (i = 0, j = strlen(s) - 2; i < j; i += 2, j -= 2)
            if (s[i] != s[j] || s[i+1] != s[j+1]) break;
        puts(i < j ? "回文ではない" : "回文");
    }
    return 0;
}



この投稿にコメントする

削除パスワード

No.6598

Re:回文の判定について
投稿者---蒼(2006/10/07 16:22:21)


皆さんお答えいただき有難うございます。
指定されていたのは、英数字です。
言葉が足りず申し訳ありません。
あと、ポインタとstrlen()は使用しないという条件がありました。

自力で書け、部分的に動いたソースは以下です。

++++++++

/* この前にchar s[21]とchark[21]とint i, z, fを宣言しています*/
  /* 項目1 入力された文字列の長さを計算して表示します */

   printf("4〜20文字の間で好きな文字列(英数字で)を入力して
       下さい: ");
scanf("%s", &s);
for (i = 0; s[i] != '\0'; i++) {
f = i;
}
if ((f < 4) || (f > 20)) {
printf("貴方が入力した文字列の長さは%dですので、
指定された長さではありません", f);
} else {
printf("O.K!");
}

/* 項目2入力された文字列を逆順にします */

for(z = f; z >= 0; z = z - 1) {
k[z] = s[z];
printf("%c", k[z]);
}

+++++++++++++
終了
+++++++++++++

ここまでは、項目1、項目2と分けて実行したところ、ちゃんと
動作しました。


この投稿にコメントする

削除パスワード

No.6599

Re:回文の判定について
投稿者---nano(2006/10/07 18:38:35)


>指定されていたのは、英数字です。
>あと、ポインタとstrlen()は使用しないという条件がありました。

「トマト」という、2バイト文字を含む例題が
混乱の元でした。
また、プログラム作成時の制約条件は、作成前に網羅すべきです。

逆順にした内容を別の変数に格納しなくてもできます。
#include <stdio.h>

#define MAXLEN (20)

int main(void)
{
    char s[MAXLEN+2];
    int len, i, j;
    
    printf("4〜%d文字の半角英数字を入力してください。\n", MAXLEN);
    while (fgets(s, sizeof(s), stdin)) {
        for (len = 0; s[len] != '\0'; len++)
            ;
        if (len > 4) {
            for (i = 0, j = len - 2; i <= len / 2; i++, j--)
                if (s[i] != s[j])
                    break;
            printf("回文で%s\n", (i <= len / 2) ? "はありません。" : "す。");
            printf("4〜%d文字の半角英数字を入力してください。\n", MAXLEN);
        }
        else
            printf("再入力してください。\n");
    }
    return 0;
}




この投稿にコメントする

削除パスワード

No.6600

Re:回文の判定について
投稿者---shu(2006/10/07 20:21:56)


>また、プログラム作成時の制約条件は、作成前に網羅すべきです。

まずは、「回文の判定」という主題からで良いと思います。
それから「制約条件1の下での「回文の判定」」、
それから「制約条件2の下での「制約条件1の下での「回文の判定」」」
それから「制約条件3の下での「制約条件2の下での「制約条件1の下での「回文の判定」」」」……

回文の判定 > 制約条件1 > 制約条件2 > 制約条件3 ……


この投稿にコメントする

削除パスワード

No.6602

Re:回文の判定について
投稿者---蒼(2006/10/07 22:03:42)


混乱させてしまい申し訳ありません。

これまで頂きました助言をもとに、
一応動くようになりました。

お礼申し上げます。
有難うございました。


この投稿にコメントする

削除パスワード

No.6612

Re:回文の判定について
投稿者---shu(2006/10/07 23:22:52)


>	scanf("%s", &s);	//	間違い

>	for (i = 0; s[i] != '\0'; i++) {
>		f = i;	//	;だけでいい
>	}

	//	ループを抜けた時点でのiを使えば良いのでfはいらない
>		if ((f < 4) || (f > 20)) {
>		printf("貴方が入力した文字列の長さは%dですので、
>                          指定された長さではありません", f);
>		} else {
>			printf("O.K!");
>		}
>		
>	/* 項目2入力された文字列を逆順にします */
>	//	全く逆順になっていない。
>	for(z = f; z >= 0; z = z - 1) {
>		k[z] = s[z];
>	         printf("%c", k[z]);
>	}



この投稿にコメントする

削除パスワード

No.6624

Re:回文の判定について
投稿者---蒼(2006/10/08 18:52:50)


皆さん教えていただいて有難うございます。
今まで頂いた助言をもとに直しましたところ、
最終的に以下のようになりました。

++++++++++++
プログラム
++++++++++++

#include <stdio.h>

main() {
    char s[21];
    int len, i, j, z;
    
    printf("4〜20文字の間で好きな文字列(英数字)を入力して下さい: ");
    while (fgets(s, sizeof(s), stdin)) {           
        for (len = 0; s[len] != '\0'; len++) 
            z = len;
        if ((len < 4) || (len > 20)) {
            printf("貴方が入力した文字列の長さは%dですので、指定された長さではありません\n", z);
            break;
        } else 
            printf("貴方が入力した文字列の長さは%dですので、条件に適しています。\n", z);
        for (i = 0, j = len - 2; i <= len / 2; i++, j--)
            if (s[i] != s[j])
                    break;
                    printf("回文で%s\n", (i <= len / 2) ? "はありません。" : "す。");
                    break;
    }
}



+++++++++++
終了
+++++++++++

これで一応動いたのですが、
回文かどうかの結果を、変数に代入するには
どこに追加すればよいのでしょうか?

宜しければ、お時間のあるときにでもご教授お願い致します。


この投稿にコメントする

削除パスワード

No.6625

Re:回文の判定について
投稿者---επιστημη(2006/10/08 19:07:08)


#include <stdio.h>

int is_palindrome(const char* str) {
  int first = 0;
  int last = 0;
  while ( str[last] != '\0' ) ++last;
  while ( first < last ) {
    if ( str[first++] != str[--last] ) return 0;
  }
  return 1;
}

int main() {
  const char* str;
  int result;
  str = "abcba";
  result = is_palindrome(str);
  printf("[%s] は回文%s\n", str, result ? "です":"ではありません");
  str = "abccba";
  result = is_palindrome(str);
  printf("[%s] は回文%s\n", str, result ? "です":"ではありません");
  str = "abcca";
  result = is_palindrome(str);
  printf("[%s] は回文%s\n", str, result ? "です":"ではありません");
  return 0;
}




この投稿にコメントする

削除パスワード

No.6637

Re:回文の判定について
投稿者---shu(2006/10/09 16:54:36)


>これで一応動いたのですが、
>回文かどうかの結果を、変数に代入するには
>どこに追加すればよいのでしょうか?

ループの継続条件i <= len / 2の部分に注目。
ループを抜けたときのi <= len / 2が回文がどうかの結果になります。

ループを抜けたとき、i <= len / 2が真なら、
ループを途中で抜けたことになり、すなわち回文ではありません。
ループを抜けたとき、i <= len / 2が偽なら、
ループが最後まで回ったことになり、すなわち回文です。

i <= len / 2は、i < jと書いてもいい。
fgets()は、改行も読み込むので、
char s[21];では一文字分足らない。


この投稿にコメントする

削除パスワード

No.6638

Re:回文の判定について
投稿者---蒼(2006/10/09 21:47:10)


何度もご助言頂いて、本当に有難うございます。
ループを抜けた後、
  if (i <= len / 2) {
z = 0;
}
else {
z = 1;
}

と付け加えたら、回文かどうかを
変数に代入することができるようになりました。

大変お世話になりました。


この投稿にコメントする

削除パスワード

管理者用メニュー    ツリーに戻る    携帯用URL    ホームページ    記事検索    ログ    タグ一覧





掲示板提供:(有)リアル・インテグリティ