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

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

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

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

解決済

C言語にてprintf文が反映されない問題

tk-watch
tk-watch

総合スコア1

C

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

1回答

0グッド

0クリップ

342閲覧

投稿2022/12/01 02:52

前提

このサイトで初めて質問させていただきます。
C言語で簡易的なNussinovのアルゴリズムのプログラムを作成しています。
文字列中にある文字の組み合わせが発見された回数を出力する機能を実装する際に問題が発生しました。

実現したいこと

  • 最初にC,G,A,Uで構成された文字列(RNAとする)を入力する。
  • 入力された文字列RNAの字数をカウントする。その字数をcount1として、count1×count1の配列gammaを作成する。
  • 配列に数値を代入する手順は、「gamma[i+1][i]に0を代入する(0≦i<count1)」「gamma[i][i]に0を代入する(0≦i≦count1)」「gamma[i][j]にgamma[i][j-1],gamma[i+1][j],gamma[i+1][j+1]+deltaのうち一番大きい数値を代入する(0≦i≦count1)。繰り返し条件は(j=1; j≦count1; j++)」とする。ここで、deltaは(RNA[i],RNA[j])=(A,U),(U,A),(G,C),(C,G),(U,G),(G,U)のとき1の値をとる。
  • (RNA[i],RNA[j])=(A,U),(U,A),(G,C),(C,G),(U,G),(G,U)のときcount2に1を代入していき、配列への数値の代入が終わったら最後にcount2を出力する。

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

> ./(ファイル名) RNA:GGGGCCCCGGGGAAACCCCGGGGCCCCC >

実行してもエラーは出ないのですが、プログラム後半に記述したprintf文が適用されません。

該当のソースコード

C言語

1#include<stdio.h> 2#include<stdlib.h> 3#include<string.h> 4 5int main(void){ 6 char RNA[256]; 7 int count1, count2; 8 int i, j, max, delta; 9 10 printf("RNA:"); 11 scanf("%s", RNA); 12 13 count1 = strlen(RNA); 14 15 int **gamma; 16 gamma = (int**)malloc(sizeof(int*)*count1); 17 for(i = 0; i < count1; i++){ 18 gamma[i] = (int*)malloc(sizeof(int)*count1); 19 } 20 21 for(i = 0; i < count1; i++){ 22 gamma[i + 1][i] = 0; 23 } 24 for(i = 0; i <= count1; i++){ 25 gamma[i][i] = 0; 26 } 27 28 for(j = 1; j <= count1; j++){ 29 for(i = 0; i <= count1 - j; i++){ 30 if(RNA[i] == 'A' && RNA[j] == 'U'){ 31 delta = delta + 1; 32 count2 = count2 + 1; 33 } else if(RNA[i] == 'U' && RNA[j] == 'A'){ 34 delta = delta + 1; 35 count2 = count2 + 1; 36 } else if(RNA[i] == 'G' && RNA[j] == 'C'){ 37 delta = delta + 1; 38 count2 = count2 + 1; 39 } else if(RNA[i] == 'C' && RNA[j] == 'G'){ 40 delta = delta + 1; 41 count2 = count2 + 1; 42 } else if(RNA[i] == 'U' && RNA[j] == 'G'){ 43 delta = delta + 1; 44 count2 = count2 + 1; 45 } else if(RNA[i] == 'G' && RNA[j] == 'U'){ 46 delta = delta + 1; 47 count2 = count2 + 1; 48 } 49 50 if(gamma[i][j - 1] > gamma[i + 1][j] && gamma[i][j - 1] > gamma[i + 1][j - 1] + delta){ 51 gamma[i][j] = gamma[i][j - 1]; 52 } else if(gamma[i + 1][j]> gamma[i][j - 1] && gamma[i + 1][j] > gamma[i + 1][j - 1] + delta){ 53 gamma[i][j] = gamma[i + 1][j]; 54 } else if(gamma[i + 1][j - 1] + delta > gamma[i][j - 1] && gamma[i + 1][j - 1] + delta > gamma[i + 1][j]){ 55 gamma[i][j] = gamma[i + 1][j - 1] + delta; 56 } 57 58 delta = 0; 59 60 } 61 } 62 63 for(i = 0; i < count1; i++) 64 { 65 free(gamma[i]); 66 } 67 free(gamma); 68 69 printf("Max:%d\n", count2); 70 printf(""); 71 72 return 0; 73}

試したこと

「for(i = 0; i < count1; i++)」、「for(i = 0; i <= count1; i++)」、「 for(j = 1; j <= count1; j++)」の3つのfor文を//で消してコンパイル、実行してみたところ、

> ./(ファイル名) RNA:GGGGCCCCGGGGAAACCCCGGGGCCCCC Max:4201168 >

という結果になり、数値はともかく「printf("Max:%d\n", count2);」の文を出力できました。従ってこれらのfor文が何かしらの問題を抱えていることになるのだと推測できますが、なぜ3つのfor文が入るとprintf文が反映されなくなるのかが分かりません。

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

このプログラムはVScodeで作成しました。
プログラム内で配列の動的確保を行っていますが、今まで配列の動的確保を行ったことがあまりなく今回作成した時は様々なサイトを見ながら見様見真似で書きました。その為その部分でも書き間違いがあるかもしれません。もし2次元配列の動的確保の書き方が間違っている場合そちらに関しても回答をいただけると幸いです。

以下のような質問にはグッドを送りましょう

  • 質問内容が明確
  • 自分も答えを知りたい
  • 質問者以外のユーザにも役立つ

グッドが多くついた質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

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

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

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

下記のような質問は推奨されていません。

  • 間違っている
  • 質問になっていない投稿
  • スパムや攻撃的な表現を用いた投稿

適切な質問に修正を依頼しましょう。

回答1

0

ベストアンサー

count1×count1の配列gamma

C

1 for(i = 0; i < count1; i++){ 2 gamma[i + 1][i] = 0; 3 }

i = count1 - 1のとき、gamma[count1]にアクセスすることになり、これは事前に確保した領域の範囲外です。

C

1 for(i = 0; i <= count1; i++){ 2 gamma[i][i] = 0; 3 }

これも同様です。i=count1のとき範囲外です。

C

1 2 for(j = 1; j <= count1; j++){ 3 for(i = 0; i <= count1 - j; i++){ 4 /* 中略 */ 5 6 if(gamma[i][j - 1] > gamma[i + 1][j] && gamma[i][j - 1] > gamma[i + 1][j - 1] + delta){ 7 gamma[i][j] = gamma[i][j - 1]; 8 } 9// 後略

j=1のとき、i=count1 - 1となり得て、このときgamma[i+1][j]gamma[count1]にアクセスすることになり、範囲外です。

他にも何箇所か範囲外があります。

投稿2022/12/01 03:10

ozwk

総合スコア13048

良いと思った回答にはグッドを送りましょう。
グッドが多くついた回答ほどページの上位に表示されるので、他の人が素晴らしい回答を見つけやすくなります。

下記のような回答は推奨されていません。

  • 間違っている回答
  • 質問の回答になっていない投稿
  • スパムや攻撃的な表現を用いた投稿

このような回答には修正を依頼しましょう。

回答へのコメント

tk-watch

2022/12/01 04:08

ありがとうございます。 gamma[count1]が事前に確保した領域の範囲外とのことでしたが、これは int **gamma; gamma = (int**)malloc(sizeof(int*)*count1); for(i = 0; i < count1; i++){ gamma[i] = (int*)malloc(sizeof(int)*count1); } の「i < count1」を「i <= count1」にすれば解決する問題ではないのでしょうか?「i < count1」を「i <= count1」に変えてコンパイル、実行してみたのですが変わらずprintf文が反映されなくなってしまいます…。
ozwk

2022/12/01 04:48 編集

gamma = (int**)malloc(sizeof(int*)*count1); でgammaが count1 個の(int*)を確保しています。 ここでサイズが決まってます。 (正確にはgammaから連続して(int*)をcount1個だけ並べることができるサイズが確保される) そもそものアルゴリズムを流し読みしましたが、NxNの行列を用意して色々するというアルゴリズムなので 用意する行列(gamma)を大きくすることで対処するのではなく NxNとして用意した行列の範囲外をアクセスしてしまっている方を修正したほうがいい気がします。
tk-watch

2022/12/01 07:29

返信してくださりありがとうございます。NxNとして用意した行列の範囲外をアクセスしてしまっている方を修正するとなると、変えることになるのはfor文の定義ということですね。 初歩的な所で躓いている質問で申し訳ないのですが、「gamma = (int**)malloc(sizeof(int*)*count1);」でgammaが count1 個の(int*)を確保しているということは、gammaの配列がgamma[0]からgamma[count1]まで確保しているという事と同じではないのでしょうか?このプログラムの場合、NxNとして用意した行列の範囲はgamma[0][0]~gamma[count1][count1]として確保したつもりでいたのですが、その認識が間違っていたのでしょうか…?
ozwk

2022/12/01 07:31

count1が1だとしましょう。 gammaが 1個の(int*)を確保しているとき、 gammaの配列がgamma[0]からgamma[1]まで確保しているという事と同じですか? 違いますね、これだと2個確保しちゃってますね。
tk-watch

2022/12/01 07:38

ありがとうございます。という事はcount1個の(int*)を確保しているということは、gammaの配列がgamma[0]からgamma[count1 - 1]まで確保しているという認識でよろしいでしょうか?
ozwk

2022/12/01 07:41

はい。 int xs[N]はN要素の配列ですけどアクセスできるのは[0] から[N-1]ですよね それと一緒です。
tk-watch

2022/12/01 08:17

ありがとうございます。(初歩の初歩な質問ですみません…) 指摘していただいたfor(i = 0; i < count1; i++), for(i = 0; i <= count1; i++), for(j = 1; j <= count1; j++){for(i = 0; i <= count1 - j; i++){~}~}をそれぞれfor(i = 0; i < count1 - 1; i++), for(i = 0; i < count1; i++), for(j = 1; j < count1; j++){for(i = 0; i < count1 - j; i++){~}~}に変更してコンパイル、実行したところMaxのprintf文を出すことが出来ました(ただし数値は本来「Max:12」と返したいものが「Max:3399785」と返されていましたが…)。おそらくcount2の数え方に問題があると思われるので次はそこを直したいと思います。
jimbe

2022/12/01 16:49

count2 とか delta とか初期値が設定されていません。

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

ただいまの回答率
86.12%

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

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

質問する

関連した質問

同じタグがついた質問を見る

C

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