• ベストアンサー

ポインタ配列

"one","two","three","four","five","six","seven","eight","nine","ten" のポインタ配列の文字列を、ASCIIコード順に並べ変えようと思ったのですが、 もうどこが間違っているかさえわからないぐらいになってしまいました。 まだまだはじめたばかりなもので、わからないことだらけなんで、 できるだけわかりやすい説明おねがいします。 関数の引数に問題があるのじゃないかと思ったのですが、 何かいいアドバイスありましたら、お願いします。 #include <stdio.h> /* 関数のプロトタイプ宣言 */ int strmp(char *,char *); void cpy(char *,char *); int main (void) { /* ポインタ配列の定義 */ char *x[10]={"oneee","twooo","three","fourr","fivee","sixxx","seven","eight","ninee","tennn"}; /* ポインタのポインタの定義 */ char **pp=x; char k[100]; char *p=k; int i,t,a,b,c,d; a=0; /* ポインタ配列を自作関数を使って、ASCIIコードの大きいほうからに並び替える */ for(i=0;i<9;i++) { for(t=1;t<10;t++) { a=strmp(*(pp+i),*(pp+t)); if(a<0) { cpy(p,*(pp+i) ); cpy(*(pp+i),*(pp+t) ); cpy(*(pp+t),p); } } } for(i=0;i<10;i++) { printf("%s ,",x[i]); } printf("\n"); return 0; } /* 文字の比較をする関数 */ int strmp(char *x,char *y) { int i; for(i=0;*(x+i)==*(y+i);i++) { if( *(x+i)=='\0') { return 0; } } return *(x+i)-*(y+i); } /* 文字をコピーする関数 */ void cpy(char *a,char *b) { int i; for(i=0;*(b+i)!='\0';i++) { *(a+i)=*(b+i); } *(a+i)='\0'; }

質問者が選んだベストアンサー

  • ベストアンサー
  • Oh-Orange
  • ベストアンサー率63% (854/1345)
回答No.4

★ポインタを使いこなしていませんね。 ・あまり、ポインタを使いすぎるとわけが分からなくなりますよ。 >a = strmp( *(pp+i), *(pp+t) );  の『*(pp+i)』や『*(pp+t)』の部分は pp[i]、pp[t] でも同じにアクセスできますので  配列と同じように表記した方が私は見やすいと思います。もしも、ポインタを使うなら  『*(pp+i)』で参照するのがこだわりがあってのことなら pp[i] にしなくても良いが…。 ・あと並びを入れ替えるときに文字列の中身を入れ替えています。  文字列のポインタだけを、ポインタ同士で入れ替えれば簡単ですよ。  ●間違い  cpy( p,*(pp+i) );  cpy( *(pp+i), *(pp+t) );  cpy( *(pp+t), p );  ●正しい  char *tp[ 1 ]; ←これを宣言(temp の tp です)    tp[ 0 ] = pp[ i ];  pp[ i ] = pp[ t ];  pp[ t ] = tp[ 0 ];  となります。cpy() 関数は文字列の内容をコピーするようですが、ポインタ配列の中身を  書き換えたいのですか?文字列定数を書き換えようとするとエラーになりませんか?  もしも、文字列の内容をアルファベット順に書き換えたい場合は、  char s0[] = "oneee";  char s1[] = "twooo";  char s2[] = "three";  char s3[] = "fourr";  char s4[] = "fivee";  char s5[] = "sixxx";  char s6[] = "seven";  char s7[] = "eight";  char s8[] = "ninee";  char s9[] = "tennn";  char *x[10]={ s0, s1, s2, s3, s4, s5, s6, s7, s8, s9 };  と定義しないといけません。  この方法ならば、cpy() 関数で中身をコピーして入れ替えできます。そういう考えでしたら  上の『間違い』が間違いではなくて本当に正しくなります。どっち? 参考ソース: int main( void ) {  char *x[10]={"oneee","twooo","three","fourr","fivee","sixxx","seven","eight","ninee","tennn" };  char *p[1]; ←宣言  int i, t, cmp;    /* バブルソート(降順) */  for ( i = 0 ; i < (10 - 1) ; i++ ){   for ( t = i + 1 ; t < 10 ; t++ ){ ←t には i+1 を代入しないとマズイ!    cmp = strmp( x[i], x[t] );        if ( cmp < 0 ){     p[ 0 ] = x[ i ];     x[ i ] = x[ t ];     x[ t ] = p[ 0 ];    }   }  }  /* ソート結果表示 */  for ( i = 0 ; i < 10 ; i++ ){   printf( "%s, ", x[i] );  }  printf( "\n" );  return 0; } /* 文字列の比較 */ int strmp( const char *x, const char *y ) {  while ( *x == *y ){   if ( *x == '\0' ){    return 0;   }   x++;   y++;  }  return (*x - *y); } その他: ・http://www.codereading.com/algo_and_ds/algo/bubble_sort.html→『バブルソート』 ・http://oshiete1.goo.ne.jp/qa2577202.html→『ポインタで詰まりました;』 ・上記も参考に!

参考URL:
http://www.codereading.com/algo_and_ds/algo/bubble_sort.html
higyaaa
質問者

お礼

char s0[] = "oneee";  char s1[] = "twooo";  char s2[] = "three";  char s3[] = "fourr";  char s4[] = "fivee";  char s5[] = "sixxx";  char s6[] = "seven";  char s7[] = "eight";  char s8[] = "ninee";  char s9[] = "tennn";  char *x[10]={ s0, s1, s2, s3, s4, s5, s6, s7, s8, s9 }; とやった結果どうにかできました。 自分としてはどうにかポインタ配列とポインタのポインタでやってみようと思っていたので、こんなおかしな物になってしまいました。 私のそのあたりの説明が不足していたようで、申し訳ありませんでした。 とてもわかりやすい説明ありがとうございました。

その他の回答 (3)

  • DT200
  • ベストアンサー率38% (63/164)
回答No.3

複雑に考え過ぎのようです。違うやり方で処理してます。 #include <stdio.h> /* 関数のプロトタイプ宣言 */ int strmp(char *,char *); void cpy(char *,char *); int main (void) { /* ポインタ配列の定義 */ char *x[10]={"oneee","twooo","three","fourr","fivee","sixxx","seven","eight","ninee","tennn"}; // // このままだとセグメント違反になるので、この配列は固定にしてインデックス // のソートをする。オリジナル方式でやる場合、二次元配列に移し替えてから最初のfor分を実行する。 // // 以下の p[ 10 ]がインデックスの配列。 int p[ 10 ]; char k[100]; // これは不要 int i,t,a,b,c,d; a=0; // インデックスを初期化する for(i=0;i<10;i++){ p[ i ] = i; } /* ポインタ配列を自作関数を使って、ASCIIコードの大きいほうからに並び替える */ for(i=0;i<9;i++){ // 初期値は1固定だと期待した結果にはならない。 i+1 です。 for(t=i+1;t<10;t++){ // 大小の判定 a = strmp( x[ p[ i ] ], x[ p[ t ] ] ); if( a < 0 ){ // インデックスの入れ替え b = p[ i ]; p[ i ] = p[ t ]; p[ t ] = b; } } } for(i=0;i<10;i++){ // 並び替えられたインデックスで、元もとの文字列のポインタの // 配列を指す。 printf("%s ,", x[ p[i] ]); } printf("\n"); return 0; } /* 文字の比較をする関数 */ int strmp(char *x,char *y) { int i; // ポインタのみで実行するほうが処理は速い。 while( *x != '\0' ){ if( *x++ < *y++ ){ return -1; } else{ return 1; } } return 0; } /* 文字をコピーする関数 */ void cpy(char *a,char *b) { // ポインタのみで実行するほうが処理は速い。 while( *b != '\0' ){ *a++ = *b++; } *a ='\0'; }

higyaaa
質問者

お礼

わかりやすい説明ありがとうございました。 ポインタ配列とポインタのポインタだけでどうにかやろうと思ったんですが どうやら無理があったようですね。 もっと広い視野でみないとだめですね

  • asuncion
  • ベストアンサー率33% (2127/6289)
回答No.2

> "one","two","three","four","five","six","seven","eight","nine","ten" のポインタ配列 についてソートしたいのですから、 > char *x[10]={"oneee","twooo","three","fourr","fivee","sixxx","seven","eight","ninee","tennn"}; こうではなく char *x[10]={"one","two","three","four","five","six","seven","eight","nine","ten"}; と定義して、プログラムが正しく動くようにしなければなりませんね。

noname#30727
noname#30727
回答No.1

並び替える時に文字をコピーする必要はありません。 (二次元配列の時はコピーが必要です) char *x[2]={"one","twoooooooooo"}; char *t; /* x[0]とx[1]を交換する */ t = x[0]; x[0] = x[1]; x[1] = t; /* 交換終了 */ strmp関数は、ぱっと見うまく出来ているように見えます。 あとは、バブルソートで交換していく部分を作りこんでいけば動くと思います。

関連するQ&A