• ベストアンサー

バブルソート:ポインタで並び替えについて。

今C言語の研修中で、バブルソートのプログラムをくんでいます。 それで、以下のように配列で入れ替えではなく、ポインタで入れ替えをしたいのですが、  dt+i = dt+i+1;  dt+i+1 = dt2; で、  invalid lvalue in assignment というエラーが出てしまいます。 書き方がまちがっているんでしょうか? 参考書やHPも探してみたのですが、探し方が悪いのかどうにもわかりません。 研修中なので、調べるのも勉強だとは思うのですが、お手上げで・・・・・・ 情けないですが、教えていただけると嬉しいです。 /** ソート処理 **/ static int SORT_PROC(void) {   int i,m;   syouhin_typ *dt2;   /** バブルソートでソート処理 **/   for(m=0; m<i_cnt-1; m++){     for(i=0; i<i_cnt-1;i++){       if(strncmp((dt+i)->code,(dt+i+1)->code,sizeof(dt->code)) >= 0){          dt2 = dt+i;          dt+i = dt+i+1;          dt+i+1 = dt2;       }     }   } } ちなみにdtはグローバル変数で、 typedef struct{   char code[5]; /** 商品コード **/   char uriage[5]; /** 売上数 **/ }syouhin_typ; /** グローバル変数 **/ syouhin_typ *dt; /** 商品 **/ としてあります。

noname#5848
noname#5848

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

  • ベストアンサー
  • ranx
  • ベストアンサー率24% (357/1463)
回答No.5

a-kuma> ANSI の規格が無かった頃ならいざ知らず、今どきの普通のコンパイラは構造体の a-kuma> 代入を許してくれますぜ。 どうも古い頭で済みません。 が、 sora8181> *dt2 = *(dt+i); sora8181> だとコンパイルの時にコアダンプしてしまうので、 sora8181> dt2 = (dt+i); sora8181> でコンパイルが通りました。 実行時ならいざしらず、コンパイル時にエラーとなるのは、sora8181さんのコンパイラが この記述を許していない証拠です。*を落としたのでは意味が変わってしまいますから、 これでコンパイルが通っても困ります。

noname#5848
質問者

お礼

確かにこれでコンパイルが通っても困ったようです。 結局 syouhin_typ dt2; ... dt2 = *(dt+i); *(dt+i) = *(dt+i+1); *(dt+i+1) = dt2; にしました。 実行してみたところ、データの最期まで比較をしてくれてなくて まだ悩み中なんですが、この問題に関してはこれでOKだと思います。 ありがとうございます。

その他の回答 (6)

  • yatokesa
  • ベストアンサー率40% (201/496)
回答No.7

>実体については、別ファイルでデータの制限をしない、と言われましてsyouhin_typ *dt[100]; >とできないのです。 えっと、よくわからないのですが、ではグローバル変数 dtはどう初期化されているのでしょうか?まずソコが知りたかったのですが...。 一応、*dt[100]というのも考え方の一つとして、です。 予めファイルサイズ等によりデータ数(n)が解るのでしたら、グローバル変数の宣言を syouhin_typ **dt; とし、 dt = (syouhin_typ*)malloc(sizeof(syouhin_typ*) * n); で可変の領域にすれば良いでしょう。 また、データ数が解らないのなら list形式のデータタイプにすることもできます。 typedef struct {  syouhin_typ *next;  char      code[5];  char      uriage[5]; } syouhin_typ; データの格納方法は割愛。

noname#5848
質問者

お礼

初期化はこれまた説明不足で・・・・・・mallocとreallocでエリアを確保しています。 ので、そこで初期化しているはずです。 見当違いな補足で申し訳ないです。 また次の機会にも是非教えていただけたら、と思います。 ではでは。

  • a-kuma
  • ベストアンサー率50% (1122/2211)
回答No.6

ranx> 実行時ならいざしらず、コンパイル時にエラーとなるのは、sora8181さんのコンパイラが ranx> この記述を許していない証拠です。 ああ、本当だ。「コンパイルの時にコアダンプしてしまうので」とありますね。 質問が終息しそうですが、最後に使っている環境を教えてもらえるとうれしいなあ > sora8181さん

noname#5848
質問者

お礼

まだまだソートファイルの完成は遠そうですが、がんばってみます。 環境なんですが、UNIX OS:MS-Windows 95 MS-Windows NT 3.51, 4.0 です。 ちなみに今更すっとぼけたことをお伺いしますが、 環境は?って聞かれたらこんな感じの答えであってますか? コンパイラがどういうものなのか調べようとしたんですがどうすればいいのやら。 とにかくありがとうございました。 またお伺いすることがあるかと思いますので、そのときはよろしくお願いします。

  • a-kuma
  • ベストアンサー率50% (1122/2211)
回答No.4

ranx> 結局入れ替えるのは「中身」というのはa-kumaさんのおっしゃる通りなのですが、 ranx> 構造体なので、単純な代入はできません。 何をおっしゃる。 ANSI の規格が無かった頃ならいざ知らず、今どきの普通のコンパイラは構造体の 代入を許してくれますぜ。 で、私の回答に対するお礼については ranx さんの ranx> それと、dt2の実体領域も忘れないように。 が回答になります。 syouhin_typ dt2; ... dt2 = *(dt+i); *(dt+i) = *(dt+i+1); *(dt+i+1) = dt2;

  • ranx
  • ベストアンサー率24% (357/1463)
回答No.3

結局入れ替えるのは「中身」というのはa-kumaさんのおっしゃる通りなのですが、 構造体なので、単純な代入はできません。 > dt2 = dt+i; > dt+i = dt+i+1; > dt+i+1 = dt2; の部分を memcpy(dt2, dt+i, sizeof(syouhin_typ)); memcpy(dt+i, dt+i+1, sizeof(syouhin_typ)); memcpy(dt+i+1, dt2, sizeof(syouhin_typ)); としましょう。 yatokesaさんのおっしゃる実体領域の確保ですが、 私は syouhin_typ dt[100]; のような感じでいいと思います。 それと、dt2の実体領域も忘れないように。 あと、内側のループですが、これでも間違いとは言えませんが、 for(i=0;i<i_cnt-1-m;i++) で良いはずです。 不必要な比較をしています。

  • yatokesa
  • ベストアンサー率40% (201/496)
回答No.2

>/** グローバル変数 **/ >syouhin_typ *dt; /** 商品 **/ この実体はどのように確保しているのですか? 私がコーディングするならば、 syouhin_typ *dt[100]; : for(int i = 0; i<100; i++) {  dt[i] = malloc(sizeof(syouhin_typ));  sprintf(dt[i]->code, "%d", i); //データ格納 } というような感じにします。これならばご質問のコーディングが生かされると思います。 まずはどのようなデータ構造になっているのか教えてください。

noname#5848
質問者

補足

説明不足で申し訳ありません。 実体については、別ファイルでデータの制限をしない、と言われましてsyouhin_typ *dt[100]; とできないのです。

  • a-kuma
  • ベストアンサー率50% (1122/2211)
回答No.1

ポインタを使っていますが、結局入れ替えるのは「中身」ですよね。 > dt2 = dt+i; > dt+i = dt+i+1; > dt+i+1 = dt2; *dt2 = *(dt+i); *(dt+i) = *(dt+i+1); *(dt+i+1) = *dt2; です。

noname#5848
質問者

お礼

早速のお返事ありがとうございます! *dt2 = *(dt+i); だとコンパイルの時にコアダンプしてしまうので、 dt2 = (dt+i); でコンパイルが通りました。 これはポインタだから*をつけろよってことでいいんですかね? あと、ついでに時間があったらでいいんですが、更に問題だでてきまして・・・・・・ 時間があったら教えてください。 先ほどのプログラムだと、 *(dt+i) = *(dt+i+1); の時点でdt2の値も*(dt+i+1)の値に変わってしまうんです。 これはポインタだからだと思うんですが、 どうしたものかとおもいまして・・・・・・厚かましくてすみません。

関連するQ&A

  • 「ポインタのポインタ」を使った文字列のソート方法?

    初めて質問を投稿させていただきます。 どうぞよろしくお願いします。 現在、C言語の勉強として、 「ポインタのポインタ」を使って「コマンドラインから入力された複数の文字列を昇順にソートして表示するプログラム」 を作っているのですが、 (main関数とソート用関数は分け、出力処理はmainの中でやります) 引数として何を渡せばいいのか、またソートで何を比較して、何を入れ替えれば良いのか、考えれば考えるほど混乱してしまいます。 (過去の質問も一通り調べてみたつもりですが、解決の手がかりとなるものが見つかりませんでした) それで、どうコーディングすればいいのかを解説して頂きたいのですが、 投稿できる文字数が限られているという事なので、私が未熟なりに作ったプログラムを、見て頂くに必要と思われる部分のみ載せさせて頂きます。 int main(int argc , char** argv) { int i = 0; /* カウンタ */ sort(argc-1,argv+1);/* sort関数 */ for(i = 1 ; i < argc ; i++) /* 出力ループ */ { printf("%s\n",*(argv+i)); /* ソート後文字列出力 */ } return 0; } /* main関数ここまで */ void sort(int sargc,char** sargv) { int i1 = 0; /* ソート用カウンタ・一時領域 */ int i2 = 0; char* temp = NULL; for(i1 = 0 ; i1 < sargc - 1 ; i1++) { for(i2 = i1 + 1 ; i2 < sargc ; i2++) { if(*(sargv + i1) < *(sargv + i2)) { temp = *(sargv + i1); /* 入れ替え */ *(sargv + i1) = *(sargv + i2); *(sargv + i2) = temp; } } } return; } } なお、実行結果は、例えば、 「実行ファイル名 suzuki tanaka satou」 と入力すれば、 satou suzuki tanaka と出力されるようにしたいと考えています。 どうぞよろしくお願いします。

  • C言語の構造体にてバブルソートが上手くいきません‥

    C言語の構造体にてバブルソートが上手くいきません‥ 初めて質問致します。 以下は、構造体で、身長順にバブルソートを行うソース文ですが、 結果表示が、最下部に示したように、 5つのレコードのうち1つが消えてしまい、 残った4つのレコードのうちの1つが重複されて表示されてしまいます。 これが、なかなか解決できません‥。 既に結構調べており、また、早く解決できないといけないこともあり、 すみませんが、回答の形式でお願いできますと大変幸いです。 何卒よろしくお願い致します。 #include<stdio.h> #include<string.h> typedef struct kojin { char name[21]; int length; int weight; }KOJIN; int main(void) { int i, c, j; char buf[4]; KOJIN data[10]; KOJIN *d; printf(

  • Ruby バブルソート

    バブルソートのプログラムでわからないところがあるため、 質問させていただきます。 Rubyは1.9.3を使用しています。 <プログラム> --------------------------------------------------- def bsort(data)   while true     # swapped変数は数値の入れ替えを記憶     swapped = false     for i in 0..data.size-2       if data[i] > data[i+1]         temp = data[i]         data[i] = data[i+1]         data[i+1] = temp         swapped = true       end     end     return if !swapped   end end data = [10, 9, 8, 7, 6] bsort(data) puts "ソート結果#{data}" --------------------------------------------------- return if !swapped のところで、 なぜwhileのループから抜けられるのかがよくわかりません。 return if swapped == false と書き換えて実行しても同じ結果が得られたのですが、 数値の入れ替えがなければ swapped = false であるため、 !swappedはtrueとはならないのでしょうか。

  • バブルソートを入れたいのですが

    こんにちは、Perlを始めたばかりの初心者です。 さっそく質問の方失礼します。 乱数1~100までの数字のうち20個をとりだし配列にいれ、数字を昇順に入れ替えして昇順前と昇順後の数字を表示する問題なのですが。 @a[100]=(1..100); srand(time()); for($i=0 ; $i<20 ; $i++){ $a=int(rand(@a)); print"$a\n"; } と上記の乱数20個を取り出すことができたのですが、 そのあとの昇順させようとしてバブルソートを利用したいのですが、どのように組み込めばいいかわかりません。 どのように組み込めばいいのでしょうか? お答えの方ヨロシクお願いします。

    • ベストアンサー
    • Perl
  • Java バブルソート

    テキストファイルに文字が書き込まれていて、その文をASCIIコード順に並び替えるのですがStringからintに変換してバブルソートを行えばよろしいのでしょうか 詳しくお願いいたします 1行は10文字  50行までです 別ファイルに書き込みます sample1.txt cfd cad fa sample2.txt ・・・ ・・・

  • C++ ソートのやり方

    僕が作ったプログラムで、これはバブルソートなのかわからないので教えてください。 また、ほかのソートの仕方も教えてください。 よろしくお願いします。 汎用関数を使っているのでわかりにくいかもしれないですがお願いします。 #include <iostream> using namespace std; template <class X>void Sort(X *data, int size) { X temp; for (int i = 0; i < size; i++){ for (int j = i + 1; j < size; j++){ if (data[i]>data[j]){ temp = data[i]; data[i] = data[j]; data[j] = temp; } } } } int main() { int i[10]{1, 4, 3, 5, 2, 10, 2, 7, 6, 8}; char c[10]{'c', 'b', 'z', 'a', 'x', 'y', 'j', 'n', 'm', 'r'}; Sort(c, 10); Sort(i, 10); for (int j = 0; j < 10; j++){ cout << i[j] << ' '; } cout << endl; for (int j = 0; j < 10; j++){ cout << c[j] << ' '; } cout << endl; getchar(); return 0; }

  • java(バブルソート/単純挿入ソート)

    以下のプログラムを「バブルソートもしくは単純挿入ソートのプログラムに変更しなさい」という課題が出ました。 どのようにすればよろしいでしょうか? import java.util.*; public class SelectSort { //プログラムクラス名 //整列プログラム public static void main(String[] args){ //整列用 int 型配列 int[] target; int elems = KeyboardInput.askInt("要素数? "); //配列を乱数で初期化する target = setArray(elems); //初期状態を表示 display(target); //整列メソッドの呼び出し sortArray(target); //整列結果の表示 display(target); } //配列を乱数で初期化するメソッド static int[] setArray(int elems){ // 要素数個の int 型変数の確保 int[] array = new int[elems]; //乱数利用ための宣言 Random generator = new Random(); //乱数の最大値・最小値 int max = 100; int min = 0; //generator.nextDouble() で 0から1までのdouble型乱数発生 for(int i=0 ; i<array.length ; i++) { array[i] = (int)((max-min)*(generator.nextDouble())+min); } return array; } //配列の状態を表示 static void display(int[] array){ for(int i=0 ; i<array.length ; i++) { System.out.print(array[i]+" "); } System.out.println(""); } static void sortArray(int[] array){ //配列のはじめから最後まで繰り返す for( int i = 0; i < array.length-1 ; i++){ int min_id = i; int min = array[i]; //範囲中でもっとも小さい要素を探す for( int j=i+1 ; j< array.length ; j++ ) { if( array[j] < min ){ min = array[j]; min_id = j ; } } //範囲の始めと置き換える int tmp = array[i]; array[i] = array[min_id]; array[min_id] = tmp; //display(array); } } }

  • ポインタと構造体の利用について

    samplefile.txtの中身 c03888 工大八郎 90 a03111 工大一郎 100 a03222 工大二郎 30 b03666 工大六郎 70 b03555 工大五郎 60 a03333 工大三郎 80 c03777 工大七郎 40 c03999 工大九郎 20 b03444 工大四郎 50 このデータをfscanfで取り込んで構造体に代入 typedef struct { char code[7]; char name[21]; int score; }REC; そしてこのデータを昇順にソートして結果を出力したいのですが 問題はここから work52.cというファイルとbubble.cというファイルとmy_sort.hというファイルがあり、work52.cからmy_sortという関数(バブルソート)を使いたい。 work52.cの中身 #include <stdio.h> #include "my_sort.h" #define MAX_NUM 500 int main(int argc, char *argv[]){ FILE *fp; REC rec[MAX_NUM]; int i, sum , min, max , n; if (argc != 2) { printf("ファイル名を指定してください\n"); return(-1); } if ((fp = fopen(argv[1], "r")) == NULL) { printf("ファイルを開けませんでした\n"); return(-1); } i = 0; while (fscanf(fp, "%s %s %d", rec[i].code, rec[i].name, &rec[i].score) != EOF){ i++; } fclose(fp); n = i; /* 初期値の設定 */ min = rec[0].score; max = rec[0].score; sum = rec[0].score; for (i = 1; i < n; i++){ sum += rec[i].score; if (rec[i].score < min) { min = rec[i].score; } if (rec[i].score > max) { max = rec[i].score; } } my_sort(rec, n); printf("最高点:%3d\n", max); printf("最低点:%3d\n", min); printf("平均点:%5.1f\n", (double) sum / n); for (i = 0; i < n; i++){ printf("%3d\t%s\t%s\n", rec[i].score, rec[i].code, rec[i].name); } return(0); } my_sort.hの中身 typedef struct { char code[7]; char name[21]; int score; }REC; void my_sort(REC *rec,int n); バブルソートで整列 #include <stdio.h> #include "my_sort.h" #define MAX 50 void my_sort(REC *rec, int n){ for(i = 0;i < n - 1; i++){ for(j = n - 1;j > i;j--){ /*この中身が問題----1*/ } } } 1の部分でchar codeとchar nameとint scoreの値を交換するときにどうすればいけるでしょうか?ご教授ください。

  • void型ポインタについて

    -------------------------------- #include<stdio.h> void uni_disp(void *p,int typ); int main() { int idt=123456; double ddt=56.789; char ss[]="abcdef"; uni_disp(&idt,'I'); uni_disp(&ddt,'D'); uni_disp(ss,'S'); uni_disp("STRING",'S'); return 0; } void uni_disp(void *p,int typ) { if(typ=='I'){ printf("%d\n",*(int *)p); } else if(typ=='D'){ printf("%f\n",*(double *)p); } else if(typ=='S'){ printf("%s\n",(char *)p); } } ----------------------------------- 以上のプログラム等で、void型ポインタをint型ポインタ、double型ポインタとみなす場合の、「*(int *)p」や「*(double *)p」の表記がどういう仕組みになっているか分かりません。 「*(int)p」などはエラーが出るのですが、やはり表記の意味を理解していないため何故か分かりません。 「*(int *)p」などの表記を分解して教えていただけると嬉しいです。

  • ポインタ勉強中です。しかも実行するとおかしいです。

    <本に載ってたソース> #include<stdio.h> #include<string.h> int main() { char msg[20]; char *str=NULL; int i; int cnt; str=&msg[0]; printf("文字を入力してください"); scanf("%s",&str); cnt=strlen(msg); str=msg+cnt; for(i=cnt;i>=0;i--){ printf("%c",*(str--)); } printf("\n"); return 0; } char *str=NULL;は、ポインタstrを空にするということでしょうか? いつもながらstrlenとsizeofが混じります。 sizeofがバイトの大きさで、strlenが、文字数でしたっけ?