【掲示板ご利用上の注意】

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

 詳しくはこちら


本当はこんなに大きく書きたくはないのですが、なかなか守っていただけなくて…。
 守ってくださいね。お願いします。(by管理人)

C言語ソース⇒HTML形式ツール掲示板2こちら


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

No.22437

逆順処理プログラム
投稿者---らげ(2005/08/05 10:37:17)


全角半角、英数漢字、これらを同順表示した後逆順表示するプログラムを作成したいのですが、全角数字を処理した場合化けてしまいます。

(例:123春あいう123ABCabc → cbaCBA321ういあ春321)
プログラムを見てください。

----------------------------------------------------------
#include <stdio.h>
#include <ctype.h>

void shori( int i, char str[100] )
{
//同順処理
for( i=0; str[i] != '\0'; i++){
if( isalnum( str[i] ) != 0 ){
printf( "%c", str[i] );
}else{
printf( "%c%c", str[i], str[i+1] );
i++;
}
}

printf( "\n" );

//逆順処理
for(i-=1; i>=0; i--){
if( isalnum( str[i] ) != 0 ){
if(isalnum(str[i])!=0&&isalnum(str[i]==0)){
printf("%c%c",str[i-1],str[i]);
if(i==0){
printf("%c",str[i]);
break;
}
}
printf( "%c", str[i] );
}else{
printf( "%c%c", str[i-1], str[i] );
i--;
}
}
}

main(void)
{
int i=0;
char str[100];

printf( "input => " );
scanf( "%s", str );
shori( i, str );

return 0;
}

----------------------------------------------------------


この投稿にコメントする

削除パスワード

発言に関する情報 題名 投稿番号 投稿者名 投稿日時
<子記事> Re:逆順処理プログラム 22438 nop 2005/08/05 10:41:11
<子記事> Re:逆順処理プログラム 22439 まきじ 2005/08/05 10:42:20


No.22438

Re:逆順処理プログラム
投稿者---nop(2005/08/05 10:41:11)


>全角半角、英数漢字、これらを同順表示した後逆順表示するプログラムを作成したいのですが、全角数字を処理した場合化けてしまいます。

以下の手順ではどうでしょうか?

1. マルチバイト文字列をワイド文字列に変換
2. ワイド文字列を逆順処理
3. 逆順処理したワイド文字列をマルチバイト文字列に変換
4. 結果表示


この投稿にコメントする

削除パスワード

No.22439

Re:逆順処理プログラム
投稿者---まきじ(2005/08/05 10:42:20)


>全角半角、英数漢字、これらを同順表示した後逆順表示するプログラムを作成したいのですが、全角数字を処理した場合化けてしまいます。

マルチポストは駄目ですよ。
マルチポスト先で、既に解答がでています。
wchar_t 型にすればどうでしょうか?


この投稿にコメントする

削除パスワード

No.22440

Re:逆順処理プログラム
投稿者---らげ(2005/08/05 10:52:53)


>>全角半角、英数漢字、これらを同順表示した後逆順表示するプログラムを作成したいのですが、全角数字を処理した場合化けてしまいます。
>
>マルチポストは駄目ですよ。
>マルチポスト先で、既に解答がでています。
>wchar_t 型にすればどうでしょうか?

すみません。全角数字に対応していないことに気づいたので・・・
wchar_t型を使わずに修正して結果を得ることってできないのでしょうか?


この投稿にコメントする

削除パスワード

No.22445

Re:逆順処理プログラム
投稿者---YuO(2005/08/05 11:07:09)


>すみません。全角数字に対応していないことに気づいたので・・・

それはマルチポストの言い訳にもなっていませんよ。


>wchar_t型を使わずに修正して結果を得ることってできないのでしょうか?

特定の環境においてのみ動くプログラムなら可能かもしれません。
ただし,wchar_tを使う場合に比べて明らかに手間がかかるだけのものになります。
# wchar_tであれば,処理したいコードに対応しているコンパイラを使うだけでよい。



この投稿にコメントする

削除パスワード

No.22446

Re:逆順処理プログラム
投稿者---まきじ(2005/08/05 11:12:45)


>wchar_t型を使わずに修正して結果を得ることってできないのでしょうか?

>if(isalnum( str[i] ) != 0 ){

としてる為

>if(isalnum(str[i])!=0&&isalnum(str[i]==0)){

の isalnum(str[i])==0 は常に偽になり、&& なので
if文も常に偽になります。


この投稿にコメントする

削除パスワード

No.22447

Re:逆順処理プログラム
投稿者---らげ(2005/08/05 11:29:08)


>>wchar_t型を使わずに修正して結果を得ることってできないのでしょうか?
>
>>if(isalnum( str[i] ) != 0 ){
>
>としてる為
>
>>if(isalnum(str[i])!=0&&isalnum(str[i]==0)){
>
>の isalnum(str[i])==0 は常に偽になり、&& なので
>if文も常に偽になります。

for(i-=1; i>=0; i--){
if( isprint( str[i] ) != 0 ){
printf("%c",str[i]);
}else{
printf( "%c%c", str[i-1], str[i] );
i--;
}
}
こうするとどこが悪いんでしょうか?


この投稿にコメントする

削除パスワード

No.22448

Re:逆順処理プログラム
投稿者---まきじ(2005/08/05 11:57:02)


>こうするとどこが悪いんでしょうか?

同順の方ではなくて、逆順の方。

>if( isalnum( str[i] ) != 0 ){

後ろからなので、2 バイト文字の、2 バイト目が
英数字かどうかを判定している。
で、0 〜 9 の 2 バイト目は、O から X と重なってるため
期待してる結果が得られない。

>if(isalnum(str[i])!=0&&isalnum(str[i])==0))

「str[i] が英数字で かつ 英数字でない。」という意味に
なる。

SJIS は、1 バイト目で、漢字か 1 バイト文字を区別できます。

同順も逆順も、str[i] が 2 バイト文字の 2 バイト目なのか
1 バイト文字の 1 バイトなのかなどの判断が必要かと。

# YuO さんが仰ってる通り、手間が掛かるし複雑になります。


この投稿にコメントする

削除パスワード

No.22449

Re:逆順処理プログラム
投稿者---らげ(2005/08/05 12:14:32)


>>こうするとどこが悪いんでしょうか?
>
>同順の方ではなくて、逆順の方。
>
>>if( isalnum( str[i] ) != 0 ){
>
>後ろからなので、2 バイト文字の、2 バイト目が
>英数字かどうかを判定している。
>で、0 〜 9 の 2 バイト目は、O から X と重なってるため
>期待してる結果が得られない。
>
>>if(isalnum(str[i])!=0&&isalnum(str[i])==0))
>
>「str[i] が英数字で かつ 英数字でない。」という意味に
>なる。
>
>SJIS は、1 バイト目で、漢字か 1 バイト文字を区別できます。
>
>同順も逆順も、str[i] が 2 バイト文字の 2 バイト目なのか
>1 バイト文字の 1 バイトなのかなどの判断が必要かと。
>
># YuO さんが仰ってる通り、手間が掛かるし複雑になります。

if( isalnum( str[i-1] ) != 0 ){
printf("%c",str[i]);
}
str[i-1]を判断してstr[i]を表示するようにしたのですが漢字と1バイト文字を同時に表示させるとダメでした。




この投稿にコメントする

削除パスワード

No.22450

Re:逆順処理プログラム
投稿者---まきじ(2005/08/05 12:30:23)


>str[i-1]を判断してstr[i]を表示するようにしたのですが漢字と1バイト文字を同時に表示させるとダメでした。

必要な部分を抜粋して引用してください。

だから、「str[i] が 2 バイト文字の 2 バイト目なのか
1 バイト文字の 1 バイトなのかなどの判断が必要かと。」
と言いました。

文字コード(Shift-JIS) について勉強する事をお勧めします。


この投稿にコメントする

削除パスワード

No.22452

Re:逆順処理プログラム
投稿者---らげ(2005/08/05 12:52:27)


>だから、「str[i] が 2 バイト文字の 2 バイト目なのか
>1 バイト文字の 1 バイトなのかなどの判断が必要かと。」
>と言いました。

IsDBCSLeadByteみたいなものでしょうか?


この投稿にコメントする

削除パスワード

No.22453

Re:逆順処理プログラム
投稿者---まきじ(2005/08/05 12:58:16)


>IsDBCSLeadByteみたいなものでしょうか?

API ですか? VB ですか?
IsDBCSLeadByte は知りません。

# wchar_t を素直に使った方が良いかと。


この投稿にコメントする

削除パスワード

No.22456

Re:逆順処理プログラム
投稿者---らげ(2005/08/05 13:07:55)


># wchar_t を素直に使った方が良いかと。

昨日まきじさんから投稿いただいたプログラムをコンパイルしてみると
外部シンボル '___isascii' が未解決エラーが出ました。
コンパイラのせいでしょうか?
コンパイラはBorland C++ 5.5.1です。


この投稿にコメントする

削除パスワード

No.22457

Re:逆順処理プログラム
投稿者---まきじ(2005/08/05 13:10:29)


>昨日まきじさんから投稿いただいたプログラムをコンパイルしてみると
>外部シンボル '___isascii' が未解決エラーが出ました。

私の方はバグがあるので、YuO さんの方はどうでしょうか?


この投稿にコメントする

削除パスワード

No.22458

Re:逆順処理プログラム
投稿者---らげ(2005/08/05 13:18:25)


>私の方はバグがあるので、YuO さんの方はどうでしょうか?

YoOさんのプログラムでreverse関数のなかのfor文でエラーが出たので修正して
int i = 0, j = wcslen(str) - 1;
    
        for ( i<j; ++i; --j)

としました。
あと wchar_t buf[256];がmain関数では宣言できないとエラーがでます。



この投稿にコメントする

削除パスワード

No.22459

Re:逆順処理プログラム
投稿者---まきじ(2005/08/05 13:30:27)


>YoOさんのプログラムでreverse関数のなかのfor文でエラーが出たので修正して

C++ になってるので、変数の宣言などを適切な位置にすれば
エラーはなくなります。


この投稿にコメントする

削除パスワード

No.22460

Re:逆順処理プログラム
投稿者---らげ(2005/08/05 13:35:24)


>C++ になってるので、変数の宣言などを適切な位置にすれば
>エラーはなくなります。

wchar_t buf[256];
    setlocale(LC_CTYPE, "");


wchar_tの宣言位置を変えました。
コンパイル時にエラーは出ませんでした。
ですが、実行時にエラーが出て強制終了されます。


この投稿にコメントする

削除パスワード

No.22461

Re:逆順処理プログラム
投稿者---YuO(2005/08/05 13:39:57)


>C++ になってるので、変数の宣言などを適切な位置にすれば
>エラーはなくなります。

C++ではないです。あくまでCです。
ISO/IEC 9899-1990には存在しない機能を使っているだけです。



この投稿にコメントする

削除パスワード

No.22462

Re:逆順処理プログラム
投稿者---らげ(2005/08/05 13:46:43)


>C++ではないです。あくまでCです。
>ISO/IEC 9899-1990には存在しない機能を使っているだけです。

reverse関数の
int i = 0, j = wcslen(str) - 1;
    
        for ( i<j; ++i; --j)

とmain関数の
wchar_t buf[256];
    setlocale(LC_CTYPE, "");

で宣言の位置を変えました。
コンパイルされるんですが、実行時にエラーがでます。


この投稿にコメントする

削除パスワード

No.22463

Re:逆順処理プログラム
投稿者---まきじ(2005/08/05 14:02:58)


#include<wchar.h>

#include<string.h>
にしてください。


この投稿にコメントする

削除パスワード

No.22464

Re:逆順処理プログラム
投稿者---らげ(2005/08/05 14:09:29)


#include<wchar.h>

#include<string.h>
に変更して実行しました。
結果は同じでした。
両方置いて実行しても同じでした。


この投稿にコメントする

削除パスワード

No.22471

Re:逆順処理プログラム
投稿者---まきじ(2005/08/05 15:48:09)


main() を以下の様にすると期待する動作になりました。
fgets() で文字列を入力して、mbstowcs() で wchar_t 型に変換。
bcc は fgetws() にバグでもあるのかな?
int main (void)
{

    char buf[256];
    wchar_t wbuf[256];
    
    setlocale(LC_CTYPE, "");
    
    if (fgets(buf, sizeof(buf) / sizeof(buf[0]), stdin) == 0) {
        return 0;
    }
    
    mbstowcs(wbuf,buf,sizeof(wbuf) / sizeof(wbuf[0]));
    if (wbuf[wcslen(wbuf) - 1] == L'\n') {
        wbuf[wcslen(wbuf) - 1] = L'\0';
    }

    output(wbuf);
    fputwc(L'\n', stdout);
    reverse(wbuf);
    output(wbuf);

    return 0;
}



この投稿にコメントする

削除パスワード

No.22472

Re:逆順処理プログラム
投稿者---らげ(2005/08/05 15:56:02)


メイン関数を変更してもやはり
<問題が発生したため、***.exeを終了します。ご不便をおかけして申し訳ありません。>と出て、マイクロソフトに報告してくださいと表示されます。
まきじさんとの環境の違いなんでしょうか?


この投稿にコメントする

削除パスワード

No.22473

Re:逆順処理プログラム
投稿者---まきじ(2005/08/05 16:02:44)


推測ですが、reverse() の j は宣言していますか?


この投稿にコメントする

削除パスワード

No.22474

Re:逆順処理プログラム
投稿者---らげ(2005/08/05 16:23:22)


>推測ですが、reverse() の j は宣言していますか?

はい。
int i = 0, j = wcslen(str) - 1;

この形で宣言しています。


この投稿にコメントする

削除パスワード

No.22475

Re:逆順処理プログラム
投稿者---まきじ(2005/08/05 16:28:27)


>for ( i<j; ++i; --j)

for (i = 0; i < j; ++i, --j) ですね。


この投稿にコメントする

削除パスワード

No.22476

Re:逆順処理プログラム
投稿者---らげ(2005/08/05 16:37:17)


きれいに表示されました。

まきじさん、お忙しいところありがとうございました。


この投稿にコメントする

削除パスワード

No.22468

Re:逆順処理プログラム
投稿者---YuO(2005/08/05 15:28:05)


>コンパイルされるんですが、実行時にエラーがでます。

エラーがでる,というのはプログラマがあげる報告ではないですよ。
どこで,どのようなエラーがでるのかを書いて下さい。



この投稿にコメントする

削除パスワード

No.22470

Re:逆順処理プログラム
投稿者---らげ(2005/08/05 15:39:51)


>エラーがでる,というのはプログラマがあげる報告ではないですよ。
>どこで,どのようなエラーがでるのかを書いて下さい。

実行時に
<問題が発生したため、***.exeを終了します。ご不便をおかけして申し訳ありません。>と出て、マイクロソフトに報告してくださいと表示されます。
同順の表示だけはされています。 


この投稿にコメントする

削除パスワード

No.22451

Re:逆順処理プログラム
投稿者---YuO(2005/08/05 12:45:32)


投稿欄の上にでかでかと書かれている,
> ※ソースの添付は「HTML変換ツール」で字下げ!
> ※返信の引用は最小限に!
> ※環境(OSとコンパイラ)や症状は具体的に詳しく!
をちゃんと守って下さい。


>str[i-1]を判断してstr[i]を表示するようにしたのですが漢字と1バイト文字を同時に表示させるとダメでした。

使っている文字コードは何ですか?
UTF-8のように,先導バイトが後続バイトと重ならない文字コードを使っていない限り,
前から順に見ていく,という方法を採らなければなりません。
# そもそも,漢字に何バイト使っているのか不明です。



この投稿にコメントする

削除パスワード

No.22454

Re:逆順処理プログラム
投稿者---らげ(2005/08/05 12:58:23)


コードはシフトJISです。
Borland C++ Compiler 5.5をXPで使っています。


この投稿にコメントする

削除パスワード

No.22481

Re:逆順処理プログラム
投稿者---かずま(2005/08/06 01:23:41)


> コードはシフトJISです。
#include <stdio.h>

int iskanji(unsigned char c) { return (c ^ 0x20) - 0xa0u < 60; }

void putr(const char *s)
{
    if (*s == '\0') return;
    if (!iskanji(s[0])) putr(s+1), putchar(s[0]);
    else putr(s+2), putchar(s[0]), putchar(s[1]);
}

int main(void)
{
    char str[256];
    printf("input => ");
    if (scanf("%255s", str) != 1) return 1;
    puts(str);
    putr(str), putchar('\n');
    return 0;
}

再帰呼び出しを使わない方法もあります。
リクエストがあればそれも披露しますが。


この投稿にコメントする

削除パスワード

No.22482

Re:逆順処理プログラム
投稿者---かずま(2005/08/06 02:53:50)


> int iskanji(unsigned char c) { return (c ^ 0x20) - 0xa0u < 60; }

訂正
int iskanji(unsigned char c) { return (c ^ 0x20) - 0xa1u < 60; }



この投稿にコメントする

削除パスワード

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