質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.50%
C

C言語は、1972年にAT&Tベル研究所の、デニス・リッチーが主体となって作成したプログラミング言語です。 B言語の後継言語として開発されたことからC言語と命名。そのため、表記法などはB言語やALGOLに近いとされています。 Cの拡張版であるC++言語とともに、現在世界中でもっとも普及されているプログラミング言語です。

アルゴリズム

アルゴリズムとは、定められた目的を達成するために、プログラムの理論的な動作を定義するものです。

ループ

ループとは、プログラミングにおいて、条件に合致している間、複数回繰り返し実行される箇所や、その制御構造を指します

Q&A

解決済

3回答

2414閲覧

N×Nの行列において指定した数値の行と列を取り除く

Jhon_McClane

総合スコア48

C

C言語は、1972年にAT&Tベル研究所の、デニス・リッチーが主体となって作成したプログラミング言語です。 B言語の後継言語として開発されたことからC言語と命名。そのため、表記法などはB言語やALGOLに近いとされています。 Cの拡張版であるC++言語とともに、現在世界中でもっとも普及されているプログラミング言語です。

アルゴリズム

アルゴリズムとは、定められた目的を達成するために、プログラムの理論的な動作を定義するものです。

ループ

ループとは、プログラミングにおいて、条件に合致している間、複数回繰り返し実行される箇所や、その制御構造を指します

0グッド

1クリップ

投稿2020/06/30 16:46

編集2020/07/01 06:23

前提・実現したいこと

既にある隣接行列において、特定の行と列を取り除いた後に、残った行列で省いた箇所を詰め直し、新しく隣接行列を作ろうと考えています。尚、既にある隣接行列はその後に使うためデータとして残し、新しく隣接行列を作ります。
例:8*8の隣接行列において、2、5のそれぞれの行と列を取り除く。2行目全体、2列目全体といった感じです。取り除かれなかった部分で詰め直して新しく隣接行列を作り直したいです。

発生している問題・エラーメッセージ

セグメントエラーと思われる箇所にて参照できないメモリを使ってしまっているのかと考えたのですが、どこが直接の原因なのか突き止めるこトができません。

セグメントエラーが発生しています

該当のソースコード

#include <stdio.h> #include <stdlib.h> #include <string.h> #define NAME_MAX 256 int main( int argc, char *argv[] ) { int i, j; int N = 0; int **adjacent; int **new_adjacent; int n1, n2; FILE *fp; char fn[NAME_MAX]; int delete1 = 2;//例:取り除く行と列 int delete2 = 5;//例:取り除く行と列 int a=0; int b=0; if ( argc != 2 ) { fprintf( stderr, "Usage: %s graph_file\n", argv[0] ); exit( 1 ); } strcpy( fn, argv[1] ); if (( fp = fopen( fn, "r" )) == NULL ) { fprintf( stderr, "File open error %s\n", fn ); exit( 1 ); } //ファイルの先頭を読み取り行列の大きさを取得する fscanf( fp, "%d", &N ); adjacent = (int **)malloc(sizeof(int *)*N); for(i=0;i<N;i++){ adjacent[i] = (int *)malloc(sizeof(int)*N); } for(i=0;i<N;i++) for(j=i;j<N;j++) adjacent[i][j] = adjacent[j][i] = 0; while( fscanf( fp, "%d %d", &n1, &n2 ) != EOF ) { adjacent[n1][n2]++; adjacent[n2][n1]++; } //display for ( i=0; i<N; i++ ) { for ( j=0; j<N; j++ ) printf( "%d ", adjacent[i][j] ); printf( "\n" ); } //ここでは予め省く要素数が既知であるため、N-2とする //6*6の新しい隣接行列を作り、該当するadjacentの値を入れていく new_adjacent = (int **)malloc(sizeof(int *)*(N-2)); for(i=0;i<N-2;i++){ new_adjacent[i] = (int *)malloc(sizeof(int)*(N-2)); } //該当する行またはラインを読まないようにする  //セグメントエラーが発生している箇所 for ( i=0; i<N; i++ ) { for ( j=0; j<N; j++ ){ if(!(i==delete1 || i==delete2 || j==delete1 || j==delete2)){ new_adjacent[a][b] = adjacent[i][j]; b++; } } b=0; a++; } printf("\n"); //display for ( i=0; i<N-2; i++ ) { for ( j=0; j<N-2; j++ ) printf( "%d ", new_adjacent[i][j] ); printf( "\n" ); } for(i=0;i<N-2;i++) free(new_adjacent[i]); free(new_adjacent); for(i=0;i<N;i++) free(adjacent[i]); free(adjacent); return 0; }

読み取るファイル

8 4 3 4 1 3 2 1 0 1 2 2 5 0 5 0 6 6 7 7 5 0 7 6 5 5 1 2 0 3 0 4 5

試したこと

省きたいラインをforループで回したときに読み込まないようにすることでnew_adjacentへ格納できると思いプログラムを書きました。しかし、要素数が順番にならないため別の変数(a,b)を用いて試したのですが、セグメントエラーが発生しました。このエラーが発生している箇所はプログラムに書きました。
この箇所の記述が上手くイメージできません。

補足情報(FW/ツールのバージョンなど)

Oracle VM VirtualBox

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

Penpen7

2020/06/30 19:46

まずはご自分で書いた分だけでもソースコードを提示することをお勧めいたします。
episteme

2020/06/30 23:19

"消す"とは如何なる意味ですか? - 0で埋める ですか? - 後続する成分をひとつづつ詰めて空席を埋める ですか? - ほかのなにか ですか?
Jhon_McClane

2020/07/01 01:06

後続する成分を一つづつ詰め、空席を埋めます。 例えば8×8の行列から2行目全体、5行目全体、2列目全体、5列目全体を取り除き、 該当しなかった部分で詰めて6×6の行列を新しく作ります
hope_mucci

2020/07/01 01:30

・「今発生している問題」を具体的に書きましょう。「うまくいかない」は具体的ではありません。 https://teratail.com/help/question-tips#questionTips3-4 ・自身で作成したソースコードをまず書きましょう。的確なアドバイスが得られやすくなります。 https://teratail.com/help/question-tips#questionTips3-5 質問は編集できます。上記の追記依頼を編集して対応してください。プレビューもちゃんと確認してね。
episteme

2020/07/01 01:49

できたけど、まずはあなたのコード呈示が先だな。
Jhon_McClane

2020/07/01 01:57

分かりました。今時間がとれないため夕方頃までには書き直します。
guest

回答3

0

epistemeさんのコードを参考に動的に作り替えました。

#include <stdio.h> #include <stdlib.h> #include <string.h> #define NAME_MAX 256 /* rows行×cols列の行列をプリントする */ void print(int **mtx, int rows, int cols) { int row, col; for ( row = 0; row < rows; ++row) { for ( col = 0; col < cols; ++col ) { printf("%d ", mtx[row][col]); } printf("\n"); } printf("\n"); } /* rows行×cols列の行列から target_row行を削除する */ void erase_row(int **mtx, int rows, int cols, int target_row) { int row, col; for ( row = target_row; row < rows-1; ++row ) { for ( col = 0; col < cols; ++col ) { mtx[row][col] = mtx[row+1][col]; } } } /* rows行×cols列の行列から target_col列を削除する */ void erase_col(int **mtx, int rows, int cols, int target_col) { int row, col; for (row = 0; row < rows; ++row) { for (col = target_col; col < cols-1; ++col) { mtx[row][col] = mtx[row][col+1]; } } } int main( int argc, char *argv[] ) { int i, j; int N = 0; int **org_adjacent; int **new_adjacent; int n1, n2; FILE *fp; char fn[NAME_MAX]; int delete1 = 2;//例:取り除く行と列 int delete2 = 5;//例:取り除く行と列 if ( argc != 2 ) { fprintf( stderr, "Usage: %s graph_file\n", argv[0] ); exit( 1 ); } strcpy( fn, argv[1] ); if (( fp = fopen( fn, "r" )) == NULL ) { fprintf( stderr, "File open error %s\n", fn ); exit( 1 ); } //ファイルの先頭を読み取り行列の大きさを取得する fscanf( fp, "%d", &N ); org_adjacent = (int **)malloc(sizeof(int *)*N); new_adjacent = (int **)malloc(sizeof(int *)*N); for(i=0;i<N;i++){ org_adjacent[i] = (int *)malloc(sizeof(int)*N); new_adjacent[i] = (int *)malloc(sizeof(int)*N); } for(i=0;i<N;i++) for(j=i;j<N;j++) org_adjacent[i][j] = org_adjacent[j][i] = 0; while( fscanf( fp, "%d %d", &n1, &n2 ) != EOF ) { org_adjacent[n1][n2]++; org_adjacent[n2][n1]++; } for(i=0;i<N;i++) for(j=0;j<N;j++) new_adjacent[i][j] = org_adjacent[i][j]; print(new_adjacent,N,N); int rows = N; int cols = N; erase_row(new_adjacent, rows, cols, 5); --rows; erase_row(new_adjacent, rows, cols, 2); --rows; erase_col(new_adjacent, rows, cols, 5); --cols; erase_col(new_adjacent, rows, cols, 2); --cols; print(new_adjacent, rows, cols); print(org_adjacent, N, N); for(i=0;i<N;i++){ free(org_adjacent[i]); free(new_adjacent[i]); } free(org_adjacent); free(new_adjacent); return 0; }

投稿2020/07/01 09:58

Jhon_McClane

総合スコア48

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

0

ベストアンサー

文字通り、行列の行/列を削除してみた:

C

1#include <stdio.h> 2 3#define R 8 4#define C 8 5 6/* rows行×cols列の行列をプリントする */ 7void print(int mtx[R][C], int rows, int cols) { 8 int row, col; 9 for ( row = 0; row < rows; ++row) { 10 for ( col = 0; col < cols; ++col ) { 11 printf("%02d ", mtx[row][col]); 12 } 13 printf("\n"); 14 } 15 printf("\n"); 16} 17 18/* rows行×cols列の行列から target_row行を削除する */ 19void erase_row(int mtx[R][C], int rows, int cols, int target_row) { 20 int row, col; 21 for ( row = target_row; row < rows-1; ++row ) { 22 for ( col = 0; col < cols; ++col ) { 23 mtx[row][col] = mtx[row+1][col]; 24 } 25 } 26} 27 28/* rows行×cols列の行列から target_col列を削除する */ 29void erase_col(int mtx[R][C], int rows, int cols, int target_col) { 30 int row, col; 31 for (row = 0; row < rows; ++row) { 32 for (col = target_col; col < cols-1; ++col) { 33 mtx[row][col] = mtx[row][col+1]; 34 } 35 } 36} 37 38int main() { 39 int mtx[R][C] = { 40 { 0, 1, 2, 3, 4, 5, 6, 7 }, 41 { 10, 11, 12, 13, 14, 15, 16, 17 }, 42 { 20, 21, 22, 23, 24, 25, 26, 27 }, 43 { 30, 31, 32, 33, 34, 35, 36, 37 }, 44 { 40, 41, 42, 43, 44, 45, 46, 47 }, 45 { 50, 51, 52, 53, 54, 55, 56, 57 }, 46 { 60, 61, 62, 63, 64, 65, 66, 67 }, 47 { 70, 71, 72, 73, 74, 75, 76, 77 }, 48 }; 49 int rows = R; 50 int cols = C; 51 print(mtx, rows, cols); 52 53 printf("erase row:5,2\n"); 54 erase_row(mtx, rows, cols, 5); --rows; 55 erase_row(mtx, rows, cols, 2); --rows; 56 print(mtx, rows, cols); 57 58 printf("erase col:5,2\n"); 59 erase_col(mtx, rows, cols, 5); --cols; 60 erase_col(mtx, rows, cols, 2); --cols; 61 print(mtx, rows, cols); 62 63 return 0; 64}

投稿2020/07/01 07:11

episteme

総合スコア16614

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

Jhon_McClane

2020/07/01 07:46

自分のコードと比べて大変読みやすくてわかりやすいです。参考に自分のコードを修正していきます。
guest

0

2行目と 5行目を飛ばしても、a++ しているからですね。

修正方法はいろいろありますが、continue; を使ってみました。

C++

1 for (i = 0; i < N; i++) { 2 if (i == delete1 || i == delete2) continue; 3 for (j = 0; j < N; j++) { 4 if (j == delete1 || j == delete2) continue; 5 new_adjacent[a][b] = adjacent[i][j]; 6 b++; 7 } 8 b = 0; 9 a++; 10 }

投稿2020/07/01 07:00

kazuma-s

総合スコア8224

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

Jhon_McClane

2020/07/01 07:41

ありがとうございます。 aの値が必要以上に増えていることに気がつきませんでした。 if( !(i==delete1 || i==delete2) a++;でもできました。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.50%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問