• 締切済み

ブールリストについて

以下のようなブールリストからall_list[list_count][M]からlist[N][M]を引いた結果をother_list[other_list_count][M]に格納したいのですが上手くいきません。どこがいけないのか答えていただければ幸いです。 #define N 4 //与えられたboolリストの数 #define M 4 //与えられたboolリストの長さ #define list_count M * M //全てのboolリストの数 #define other_list_count list_count - N //与えられたboolリスト以外のリストの数 //与えられたboolリスト char list[N][M] = { { 't' , 't' , 't' , 'f' }, { 't' , 't' , 't' , 't' }, { 't' , 'f' , 't' , 'f' }, { 'f' , 't' , 't' , 'f' } }; //boolリストの全てのパターン char all_list[list_count][M] = { { 't' , 't' , 't' , 't' }, { 't' , 't' , 't' , 'f' }, { 't' , 't' , 'f' , 't' }, { 't' , 't' , 'f' , 'f' }, { 't' , 'f' , 't' , 't' }, { 't' , 'f' , 't' , 'f' }, { 't' , 'f' , 'f' , 't' }, { 't' , 'f' , 'f' , 'f' }, { 'f' , 't' , 't' , 't' }, { 'f' , 't' , 't' , 'f' }, { 'f' , 't' , 'f' , 't' }, { 'f' , 't' , 'f' , 'f' }, { 'f' , 'f' , 't' , 't' }, { 'f' , 'f' , 't' , 'f' }, { 'f' , 'f' , 'f' , 't' }, { 'f' , 'f' , 'f' , 'f' } }; //与えられたboolリスト以外のリスト char other_list[other_list_count][M]; int i,j,k,s = 0; //与えられたboolリスト以外のリストの作成 for(i=0;i<list_count;i++){ k = 0; for(j=0;j<N;j++){ if((strcmp(all_list[i],list[j])) == 0) {k++;} } if(k==0){ strcpy(other_list[s],all_list[i]); s++; } }

みんなの回答

  • chie65535
  • ベストアンサー率43% (8547/19427)
回答No.2

>どこがいけないのか strcmpとstrcpyを使うのがいけない。 strcmpやstrcpyは「引数に与える文字列には、文字列の終端記号が必要」です。 char list[N][M] = { { 't' , 't' , 't' , 'f' }, { 't' , 't' , 't' , 't' }, { 't' , 'f' , 't' , 'f' }, { 'f' , 't' , 't' , 'f' } }; の配列や char all_list[list_count][M] = { { 't' , 't' , 't' , 't' }, { 't' , 't' , 't' , 'f' }, (略) の配列には「文字」は入っていますが「文字列」は入っていません。 「そんな筈は無い!」と疑問に思うなら、以下の文を試してみましょう。 printf("list[0]=%s\n",list[0]); printf("list[1]=%s\n",list[1]); printf("all_list[0]=%s\n",all_list[0]); printf("all_list[1]=%s\n",all_list[1]); もしlist[0]やlist[1]、all_list[0]やall_list[1]に「strcmpやstrcpyで使える、終端記号が付いた文字列」が入っているなら list[0]=tttf list[1]=tttt all_list[0]=tttt all_list[1]=tttf と言う表示になる筈です。 でも、そうはなりません。やってみると「なんじゃこりゃ!」って結果になります。 修正方法は、2つあります。 その1。配列の中身が「文字列」になるよう、文字列の終端記号を足す。 char list[N][M + 1] = { { 't' , 't' , 't' , 'f' ,0 }, { 't' , 't' , 't' , 't' ,0 }, { 't' , 'f' , 't' , 'f' ,0 }, { 'f' , 't' , 't' , 'f' ,0 } }; //boolリストの全てのパターン char all_list[list_count][M + 1] = { { 't' , 't' , 't' , 't' ,0 }, { 't' , 't' , 't' , 'f' ,0 }, (略) { 'f' , 'f' , 'f' , 't' ,0 }, { 'f' , 'f' , 'f' , 'f' ,0 } }; //与えられたboolリスト以外のリスト char other_list[other_list_count][M + 1]; (以下略) 配列の中身を上記のように直すと printf("list[0]=%s\n",list[0]); printf("list[1]=%s\n",list[1]); printf("all_list[0]=%s\n",all_list[0]); printf("all_list[1]=%s\n",all_list[1]); の結果が list[0]=tttf list[1]=tttt all_list[0]=tttt all_list[1]=tttf と言う表示になる筈です。 なお char list[N][M + 1] = { { 't' , 't' , 't' , 'f' ,0 }, { 't' , 't' , 't' , 't' ,0 }, { 't' , 'f' , 't' , 'f' ,0 }, { 'f' , 't' , 't' , 'f' ,0 } }; は char list[N][M + 1] = { { "tttf" }, { "tttt" }, { "tftf" }, { "fttf" } }; または char list[N][M + 1] = { "tttf" , "tttt" , "tftf" , "fttf" }; と書いても同じです。 つまり "tttf" と書くと、自動的に「文字列の終端記号」も付加され { 't' , 't' , 't' , 'f' ,0 } と書いたのと同じになるのです。 その2。strcmpやstrcpyを使わない。 if((strcmp(all_list[i],list[j])) == 0) {k++;} ↓ if((memcmp(all_list[i],list[j]),M) == 0) {k++;} strcpy(other_list[s],all_list[i]); ↓ memcpy(other_list[s],all_list[i],M); memcmp、memcpyは「文字列ではなくメモリの中身を、バイト単位で比較、コピー」します。 比較やコピーの長さを引数で指定するので「文字列の終端記号」は無関係です。「文字列の終端記号」は「あってもなくても関係ない」ので、今回のような「文字列の終端記号が入ってなくて文字列として扱う事が出来ない、文字のみが入った配列の中身を比較、コピーするのに使う」事ができます。 蛇足ですが #define list_count M * M //全てのboolリストの数 #define other_list_count list_count - N //与えられたboolリスト以外のリストの数 は間違い。 #define list_count (1 << M) //全てのboolリストの数 #define other_list_count (list_count - N) //与えられたboolリスト以外のリストの数 が正解。 「すべての組み合わせ」は「2通り×2通り×2通り×2通り」で「2の4乗通り」でなければならない。 今回、偶然に「Mが4で、2の4乗=16=4×4」だから問題が無かったけど、これが「Mが3」とか「Mが5」だったら、変な数値になる。 Mが3なら、「2通り×2通り×2通り」で「2の3乗通り」で「8通り」でなければならないが「M×M=9」で、数値が合わなくなる。 Mが5なら、「2通り×2通り×2通り×2通り×2通り」で「2の5乗通り」で「32通り」でなければならないが「M×M=25」で、数値が合わなくなる。 また「M * M」や「1 << M」や「list_count - N」のような演算子を含む式を定義する場合は、必ず、式の全体を括弧でくくる事。 括弧を付けないと、other_list_countの2倍の要素数の配列が欲しくて char other_list_x2[other_list_count * 2][M]; って書いた時に、とんでもない事になる。 なぜなら、括弧が無いと char other_list_x2[other_list_count * 2][M]; は char other_list_x2[list_count - N * 2][M]; になる。これは、*の方が先に計算されるから char other_list_x2[list_count - (N * 2)][M]; であって char other_list_x2[list_count - N - N][M]; と同じだから、2倍にはならない。 簡単に確かめるなら printf("other_list_count=%d\n",other_list_count); printf("other_list_count * 2=%d\n",other_list_count * 2); を実行してみよう。 other_list_count=12 other_list_count * 2=8 になってしまう。 ちゃんと括弧でくくれば other_list_count=12 other_list_count * 2=24 になる。

satoshi551
質問者

お礼

ありがとうございます。とても丁寧でわかりやすかったです。 '\0'がポイントですね^^

全文を見る
すると、全ての回答が全文表示されます。
  • asuncion
  • ベストアンサー率33% (2126/6288)
回答No.1

#include <stdio.h> #include <string.h> #define N 4 //与えられたboolリストの数 #define M 4 //与えられたboolリストの長さ #define list_count M * M //全てのboolリストの数 #define other_list_count list_count - N //与えられたboolリスト以外のリストの数 int main(void) { //与えられたboolリスト char list[N][M+1] = { "tttf", "tttt", "tftf", "fttf", }; //boolリストの全てのパターン char all_list[list_count][M+1] = { "tttt", "tttf", "ttft", "ttff", "tftt", "tftf", "tfft", "tfff", "fttt", "fttf", "ftft", "ftff", "fftt", "fftf", "ffft", "ffff", }; //与えられたboolリスト以外のリスト char other_list[other_list_count][M+1]; int i, j, s = 0; //与えられたboolリスト以外のリストの作成 for (i = 0; i < list_count; i++) { for (j = 0; j < N; j++) { if ((strcmp(all_list[i], list[j])) == 0) { break; } } if (j == N) { strcpy(other_list[s], all_list[i]); printf("%s\n", other_list[s]); s++; } } return 0; }

satoshi551
質問者

お礼

ありがとうございます。そういうやり方もあったんですね。

全文を見る
すると、全ての回答が全文表示されます。

関連するQ&A

  • C言語 構造体、関数 質問です。

    下のプログラムは、ファイルに書いてある、姓と名のデータを 構造体にもたせ、それぞれ出力させるというものです。 これの応用として、関数を使って構造体にデータをもたせる プログラムに改良したいのですが、よくわかりません。 根本的なものはあまり変わらないと思っているのですが、 どなたか、詳しくアドバイスお願いします。 #include<stdio.h> #define dFamilySize(32) #define dNameSize(32) #define dPersonSize(1024) #define dBufferSize(64) typedef struct _PROFILE PROFILE; struct _PROFILE { char family[dFamilySize]; char name[dNameSize]; }; main() { int i,j,k; char line[dBufferSize]; PROFILE list[dPersonSize]; for(i=0; i<dPersonSize; i++){ list[i].family[0]='\0'; list[i].name[0]='\0'; } i=0; while(fgets(line,dBufferSize,stdin)!=NULL){ for(j=0; line[j]!=' '; j++){ list[i].family[j]=line[j]; } list[i].family[j]='\0'; for(k=0,j++; line[j]!='\0'; j++,k++){ list[i].name[k]=line[j]; } list[i].name[k]='\0'; printf("%s\n",list[i].family); i++; } }

  • C アルファベットのカウント

    #include<stdio.h> #define N 97 #define M 122 int main(void) { char str[ ]="national university"; int i,h,count; char check; for(h=N-1;h<=M;h++){ h++; char check = (char)h; for(i=0;str[i] != '\0';i++){ if(str[i] = check){ count++; } } printf("%c:%d\n",check,count); } } というコードで、アルファベットをそれぞれ何文字使用しているか調べるつもりだったのですが、結果は次のようになってしまいました。解説お願いします。 a:28 c:56 e:84 g:112 i:140 k:168 m:196 o:224 q:252 s:280 u:308 w:336 y:364 {:392

  • リストのデータを重複なしでランダムに抽出する

    シート1に下記のように14種類の名前リストがあります     A 1   A 2   B 3   C 4   D 5   E 6   F 7   G 8   H 9   I 10  J  11  K 12  L 13  M 14  N 上記の名前を下記のように別シートの数列おきの列(行は同一)に重複なしに行毎にランダムに抽出する事が関数で出来るでしょうか?(エクセルは2010です) ちなみに下記は一列おきのセルに抽出した例です   A B C D E F G H I J K L M N O P Q R S T U V W X Y Z AA 1 D   L   K    I    A   M   N    B   H   J    C    F    E   G 2 K   J   M   H    I   G   F    E   D    A    B   N   C    L 3 E   J   A    L   B   M    K   C   N    G    F   D    H   I どなたか教えていただける方がおりましたらよろしくお願いします。

  • セグメントエラー

    #include <stdio.h> #define S 10.0 #define L 10.0 void solve(int m,double a[][10],double f[]); main() { double t,me[10][10],fe[10]; int i,x; t=(S*L)/420; me[0][0]=t*156;me[0][1]=t*22*L;me[0][2]=t*54;me[0][3]=t*(-13)*L; me[1][0]=me[0][1];me[1][1]=t*4*L*L;me[1][2]=t*13*L;me[1][3]=t*(-3)*L*L; me[2][0]=me[0][2];me[2][1]-me[1][2];me[2][2]=t*156;me[2][3]=t*(-22)*L; me[3][0]=me[0][3];me[3][1]=me[1][3];me[2][3]=me[3][2];me[3][3]=t*4*L*L; for(i=0;i<4;i++){ fe[i]=1.0; } x=4; solve(x,me,fe); } void solve(int m,double a[][10],double f[]) { /* m=number of unknowns */ int i,j,k; double aa; /* forward elimination */ for(i=0;i<m-1;i++){ for(j=i+1;j<m;j++){ aa=a[j][i]/a[i][i]; f[j]-=aa*f[i]; for(k=i+1;k<m;j++){ a[j][k]-=aa*a[i][k]; } } } /* backward substitution */ f[m-1]/=a[m-1][m-1]; for(i=m-2;i>=0;i--){ for(j=i+1;j<m;j++){ f[i]-=a[i][j]*f[j]; } f[i]/=a[i][i]; } } 以上のようなプログラムについて、コンパイルはできるのですが、実行時に「セグメントエラー」と出てしまいます。たぶん配列の引渡しに原因があるようなのですが、どなたか詳しい原因(対処法)をご教授願いたいと思います。

  • 至急お願いします!!

    CSVファイルを読み込んで構造体に格納し、格納したデータを標準出力、女性のデータだけを標準出力、その後データのナンバーを昇順にソートし標準出力しようとしていますが、下2つが上手く出力できません・・・ どなたか、間違いを指摘してもらえませんか? CSVファイルの内容 ***************************************************************** 022023,金沢聖悟,M,012-345-6789 022011,鈴木信也,M,123-456-7890 022025,佐々木小太郎,M,901-234-5678 032002,加田宮千代子,F,890-123-4567 032011,ラスコーニ・イワンチャコフ,M,789-012-3456 032020,渡辺真,M,678-901-2345 032050,加藤江美,F,567-890-1234 042007,萩原雄一,M,456-789-0123 042010,井上麻衣,F,345-678-9012 042014,カイ・ハンセン,M,234-567-8901 042035,近松門左衛門,M,111-222-3333 042044,セルビア・モンテネグロ,F,555-555-5555 ************************************************************** プログラム *************************************************************** #include <stdio.h> #include <stdlib.h> #include <string.h> #define MAX_NUMBER_LENGTH 30 #define MAX_NAME_LENGTH 20 #define MAX_SEX_LENGTH 2 #define MAX_TEL_LENGTH 20 #define MBF 256 struct NameCard{ char number[MAX_NUMBER_LENGTH]; // 番号 char name[MAX_NAME_LENGTH]; // 名前 char sex[MAX_SEX_LENGTH]; // 性別 char tel[MAX_TEL_LENGTH]; // 電話番号 }; void swap(struct NameCard * ,struct NameCard *); void sort(struct NameCard [], int ); int main(void) { FILE* fp; /* ファイルポインタ用 */ char *ret; /* ファイル名用 */ char *c,ch[MBF]; /* 文字入力用 */ int i = 0; int n,k; struct NameCard ncd[20]; if((fp = fopen("meibo.csv", "r")) == NULL) printf("ファイルをオープンできません\n"); //exit(1);/* 強制終了 */ else{ printf("読み込んだファイルを表示します\n"); while ( fgets(ch,MBF,fp) != NULL){ //printf("test\n"); strcpy(ncd[i].number,strtok(ch,",")); strcpy(ncd[i].name,strtok(NULL,",")); strcpy(ncd[i].sex,strtok(NULL,",")); strcpy(ncd[i].tel,strtok(NULL,",")); atoi(ncd[i].number); printf("%s,%s,%s,%s",ncd[i].number,ncd[i].name,ncd[i].sex,ncd[i].tel); i++; } //printf("%s\n",ncd[0].sex); //printf("%s\n",ncd[1].sex); //printf("%s\n",ncd[2].sex); //printf("%s\n",ncd[3].sex); printf("女性のリスト\n"); for(n=0;n<i;n++) { //printf("test\n"); if(ncd[n].sex==c){ //printf("test\n"); printf("%s,%s,%s,%s",ncd[n].number,ncd[n].name,ncd[n].sex,ncd[n].tel); }else; } } sort(ncd, i); printf("ソート後\n"); for(k=0;k < i;k++) { printf("%s,%s,%s,%s",ncd[k].number,ncd[k].name,ncd[k].sex,ncd[k].tel); } fclose(fp); /* ファイルクローズ */ return(0); } void swap(struct NameCard *x,struct NameCard *y) { struct NameCard temp = *x; *x = *y; *y = temp; } void sort(struct NameCard data[], int n) { int k = n - 1; while(k >= 0){ int i,j; for(i = 1,j = -1; i <= k; i++) if(data[i-1].number > data[i].number){ j = i - 1; swap(&data[i],&data[j]); } k = j; } }

  • 行列の計算

    #include<stdio.h> #define N 2 #define M 3 void hyoji(float[][M]); int main(){ int i,j,k; float a[N][M] = {{2.0,2.0,2.0},{2.0,2.0,2.0}}; float b[M][M] = {{1.0,1.0,1.0},{2.0,2.0,2.0},{1.0,1.0,1.0}}; float c[N][N]; for(i=0; i<N; i++){ for(j=0; j<M; j++){ c[i][j] = 0; for(k=0; k<M; k++){ c[i][j] += a[i][k] * b[k][j]; } } } hyoji(c); return(0); } void hyoji(float x[][M]){ int i,j; for(i=0; i<N; i++){ for(j=0; j<M; j++){ printf("%4.1f ",x[i][j]); } printf("\n"); } } 以上のプログラムで 行列aと行列bをかけ合せた行列cを求めるのですが コンパイルすると 8 8 8 8 8 1 となり、正しい結果がでません。 なにが間違っているのでしょうか?? よろしくお願いします。

  • 協力お願いします

    このような質問をして申し訳ないんですがプログラミングが苦手なのでどなたか答えた頂けるのならばありがたいです。 下記表を並び替えて、 1) 総点順に並び換えよ。 2) 各科目別成績順に並びかえよ。   国語 算数 理科 社会 英語 太郎80 90 75 70 70 次郎70 85 80 80 85 三郎75 95 65 90 95 四朗65 70 80 75 80 春子90 100 85 90 85 夏子100 95 80 85 80 秋子60 75 90 70 85 冬子85 80 85 90 95 このような問題なんですがヒントをすごいもらって #include"stdio.h" #include "math.h" #define n 9 #define m 7 void main() { char namae[n][5]={"名前","太郎","二郎","三郎","四郎","春子","夏子","秋子","冬子"}; char kamoku [7][5]={"科目","国語","算数","理科","社会","英語","合計"}; double seiseki[n][m]={{0,0,0,0,0},{80,90,75,70,70},{70,85,80,80,85},{75,95,65,90,95},{65,70,80,75,80},{90,100,85,90,85},{100,95,80,85,80},{60,75,90,70,85},{85,80,85,90,95}}; int i,j; double goukei[n]; for(i=0;i<m;++i){ printf(" %s ",kamoku[i]); } printf("\n"); for(i=1;i<n;++i){ goukei[i]=0; printf("%s",namae[i]); for(j=0;j<m-2;++j){ printf("%6.0f",seiseki[i][j]); goukei[i]+=seiseki[i][j]; } printf("%6.0f\n",goukei[i]); } } こんな感じにはなったんですがあとどうしたらいいのかさっぱりわからません。 どなたかお力を貸していただきたく思います。 長文、乱文失礼いたしました。

  • VB2008: リストメンバーの列数の求め方?

    Sub Main()   Dim I As Integer   Dim J As Integer   Dim K As Integer   Dim aDatas As New List(Of String())()   Dim N = CSVReadToArray("D:\Temp\付属一覧.csv", aDatas) - 1   K = aDatas(0).Count - 1   For I = 0 To N     For J = 0 To K       Debug.Print(aDatas(I)(J))     Next J   Next I End Sub 質問1、K = aDatas(0).Count - 1 の本当のやり方? 質問2、K の処理のされ方。 K が変数としてメモリに配置されることはないと推察しています。 多分、何がしかのスタック領域に一時的に置かれると・・・。 この辺りに関しても教えてもらえれば幸いです。

  • C言語についてなのですが、

    C言語についてなのですが、 #include<stdio.h> #include<stdlib.h> #include<time.h> #include<search.h> int main(void) { int i,j,k,temp,n,count,time,list[65537]; clock_t startTime, endTime; printf("取得する乱数の個数を入力してください\n"); scanf("%d",&n); srand((unsigned)time(NULL)); printf("Before sort\n"); startTime = clock(); for(i = 0; i < n; i++) { list[i] = rand(); /* printf("%d\n", list[i]);*/ } count = 0; for (i = 1; i < n; i++) { for (j = i; j < n-i-1; j++) { count++; if(list[j] < list[j+1]) { temp = list[j]; list[j] = list[j+1]; list[j+1] = temp; } } } endTime = clock(); printf("\nAfter sort\n"); for(k = 0; k < n; k++) { /* printf("%d\n", list[k]);*/ } printf("\n比較回数:%d\n", count); printf("実行時間:%.4f秒\n", (double)(endTime - startTime) / CLOCKS_PER_SEC); return 0; } 上記のソースコードをcygwinで gcc -Wall -o k5-1-2 k5-1-2.c でコンパイルしようとすると k5-1-2.c:関数'main'内 k5-1-2.c:14:error:called object is not a function と表示されます。 いろいろなサイトを参考にして乱数取得用に srand((unsigned)time(NULL));を使うように書かれていたので使っているのですが、何かだめなのでしょうか?自分ではお手上げ状態で。

  • 行列の行の入換え

    | -1 -1 -2 -1 10 | | -1 -2 -1 10 -1 | | -2 -1 10 -1 -1 | | -1 10 -1 -1 -2 | | 10 -1 -1 -2 -1 | この行列を次の順序で並び替えたいのですが 1.第1列にある要素の中で絶対値の最大値がある行を探し,その行と第1行を入れ換える. 2.第2列にある要素の中で絶対値の最大値がある行を第2行以下から探し,その行と第2行を入れ換える. 3.これを左上から右下へ順次移動して,行の入れ換えを行う. #include<stdio.h> #include<math.h> #define N 5 #define M 5 int main(){ float a[N][M]={{-1.0,-1.0,-2.0,-1.0,10.0},{-1.0,-2.0,-1.0,10.0,-1.0},{-2.0,-1.0,10.0,-1.0,-1.0}, {-1.0,10.0,-1.0,-1.0,-2.0},{10.0,-1.0,-1.0,-2.0,-1.0}}; float nmax; int i,j,k=0,s,imax; for(j=0; j<M; j++){ nmax = a[0][j]; imax = 0; for(i=1; i<N; i++){ if(fabs(nmax) < fabs(a[i][j])){ nmax = a[i][j]; imax = i; } } for(j=0; j<M; j++){ s=a[k][j]; a[k][j]=a[imax][j]; a[imax][j]=s; } k++; } for(i=0; i<N; i++){ for(j=0; j<M; j++){ printf("%5.1f ",a[i][j]); } printf("\n"); } return(0); } このように作成したのですが、1行目と5行目しかいれかわりません。 なぜでしょうか??