🎄teratailクリスマスプレゼントキャンペーン2024🎄』開催中!

\teratail特別グッズやAmazonギフトカード最大2,000円分が当たる!/

詳細はこちら
C

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

Q&A

解決済

4回答

1641閲覧

遺伝子情報の検索プログラム:C言語

ishiko

総合スコア6

C

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

0グッド

0クリップ

投稿2021/01/09 15:32

編集2021/01/10 04:31

前提・実現したいこと

ファイルから読み込んだ塩基配列(2000文字)の中に標準入力した文字列は何か所に入っているかを求めるプログラム。
めちゃくちゃ初心者なので分かりやすく教えていただけると嬉しいです。

自分で考えたこと:
1.塩基配列中に、入力した文字列の1文字目と同じ文字があるか1文字目から順々に見ていく。
2.同じ文字が出た時、入力した文字列の2文字目とその文字の次の文字が一致するか調べる。もし違ったら1に戻り、同じだったらまたその次の文字が一致するかを調べる。これを繰り返す。
3.入力した文字列の端まで一致したらカウントする。
4.1へ戻る

もっと良いやり方がある場合、そのやり方も教えてください。

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

実行結果が2000か所になります。確実に途中部分の計算が変なのだと思います。``` ###該当のソースコード #include<stdio.h> int str_length(const char s[]) { int len = 0; while (s[len]) len++; return len; } int main(void) char ch[2000]; FILE *fp; fp=fopen("file.txt","r"); if(fp == NULL){ perror("ファイルの読み込みに失敗\n"); return 1; } printf("▼=====テキストファイルの内容=====▼\n"); while((ch[2000] = fgetc(fp))!=EOF){ printf("%c",ch[2000]); } char str[2000]; printf("\nパターンを入力してください。*a,t,g,cのみ\n"); scanf("%s",str); /*ここからおかしい*/ int i=0,k=0,m=1,count=0; for(i=0;i<=2000;i++){ if( ch[i]=str[k] ){ for(m=1; m <= str_length(str); m++){ if(ch[i+m]!=str[k+m]){ break;} } if(m=str_length(str)){ count++; } } } printf("パターン「\"%s\"」は%d箇所に含まれています。",str,count); return 0; } ### 試したこと 肝心の計算部分以外は合っていました。 ### 補足情報(FW/ツールのバージョンなど) ここにより詳細な情報を記載してください。

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

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

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

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

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

episteme

2021/01/09 16:00 編集

コンパイル・エラーになります。 Cは、関数(main) 内で 関数(str_length) を定義することはできません。 なので > 肝心の計算部分以外は合っていました。 は 信じられません [追記] str_length を main外に追い出すことでコンパイルできました。 まず、ch[] にファイルのナカミがコピーされたか確認しましたか?
kazuma-s

2021/01/09 16:06

``` の使い方が間違っています。余計なものを削除してください。質問は編集できます。 #include <stdio.h> の直前に ```C だけの行を追加してください。 ソースコードの最後の } の直後に ``` だけの行を追加してください。
thkana

2021/01/10 02:49

他の言語の方がいいんじゃない? の流れで。 Pythonならこんな感じ? import re try: __allSeq=open(r'file.txt','r').read() __print('テキストファイルの内容') __print(allSeq) __partSeq = input('\nパターンを入力してください。*a,t,g,cのみ :') __match=re.findall(partSeq,allSeq) __print('パターン「"{0}"」は{1}箇所にふくまれています。'.format( partSeq, len(match))) except: __print('File Error!') Cで塩基配列のお題って何故かよく聞きますけど、なんなんでしょうね。
thkana

2021/01/10 03:24

> コンパイル・エラーになります。 gcc だと通っちゃいます。だからそれでいいという話じゃないですけれど。
guest

回答4

0

もっと良いやり方がある場合、そのやり方も教えてください。

せめてC++に乗り換えたほうがいいです。Cで文字列を扱うのはあまりにも効率が悪い。純粋なITのエンジニアの道を究めたいなら知りませんが、バイオをやりたいならわざわざCを選んで難解なポインタと戦う理由はないでしょう。

投稿2021/01/09 16:39

KojiDoi

総合スコア13692

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

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

ishiko

2021/01/10 04:40

なるほど、、、 課題でCかC++を使えとのことなので、C++でも良いのです。 新しく勉強してみようかと思います。
guest

0

KojiDoiさんのおっしゃるとおりで、アルゴリズムを知りたいなら、他の言語で作った方が良いと思います。
pythonならこういうコードになります。

python

1with open('data', 'r') as f: 2 data = f.read() 3 4print(data) 5 6pattern = input('\nEnter pattern (a,t,g,c only): ') 7 8l_pattern = len(pattern) 9result = [] 10for i in range(len(data) - l_pattern + 1): 11 if pattern == data[i: i+l_pattern]: 12 result.append(i) 13 14print(f'There are {len(result)} patterns in the data') 15print(f'start indices are {result}')

実行すると以下のようになります。

python

1> python find_baseseq.py 2tatccatgcttacaacatgatttcaatgactcgattcacgttctgcgacgagtcatcactagtggtttagagactatagtgcatattaagctgtgggcggccaccgcatgaagcgccgcctgaaacgaggggtatagtaacctagttgtttcacaatcaacgtatgtccgcgtctaggatgtggcgacgcgaacaggtctacgagaaaagccactgaggcgcccttacttgagtgaggtttcgctgtatagattgagagagggagcttactgcattggatttacatgagtactgcatgtacgttatgtgaactttaatattagcagcgctgcttagcaattattgcgacaccacgtcggccatgtgaagcctctggagcgccgtttcatggaacgggacgcactaggcttcgtaaccccaccgaagtcattccgtcctgcgtcagccggtcggaacttcatgcttcccgtgtcgcatacataggctgaagccgccggatttaccaaatagggggcccatttctgatagatggcagacatcgtcgaagaagcacaaaattcatgctctgtaagccttagtagacttagcactttttagtcacttaactctcgaagaccaatcgacaagcttttcgggacctctcgtagtcccgttttatgatccggggaacggcgctcgaccatcctctccccaccgattcttcgacgctagcttactcacatgctgatcgctcggtacacttatagtactctgtcgtatactcttactgatgtaaatttagcaccagcactcatattactcttaccaaggtctatgaatagtagtatcaaacaattctggagacctcacttacataaggcagactctacatcatggatggggggtaccttcctcctgtactgagccccgcaggaaatcctttccgaaaaaaacgaaatcaacacggcccgcttacacaatagactgcgtatatgacgcgtccagttggcacgacttgagctctgtgactttaaacacactggcacaaggccaggtgcgtagaaccattaaataccgtccgggcccggggtataagactgcgcgagagagtcaacgatggtgtcgccgatgttcgaacgtgggtggaagtcgtgggctatgaccttaatctccctaataaatagtctatgatttctaagcactagcatggtggattcggtgcaactacttcaatgaggtgttttgggacagctatgcatgctccccagttcaagacgtggaagttcaaactgtaaaaagcgaaaagattgattacatgttcgaaccgttgttcacgcaggggatcgatgcccccgcgaagactgtttccattataagttggtctcagttgcaattattagccagttggtcagtggtcgcgtcggaaccggtgagggcaagtcagggtgtttgatctcgtgctcggccatgagtcgaaacccttacatatcaaagatatactgtgtaacaaaatcattgcagttaagacacagtattacgaatcgccgttagaaccggatgaaaatggactcccaaatcgaagtaggatctctcttgctaagacaacttgttctggtccgattggggatcaacgtggctactaaccgggtaattccgaggaatggacacttcgatcgtgagcccgaatctgatgcggacaagtgggacttagcacacctgggtagtagtgacttacctttccggtacttgccgaaagtggtaattggcttctttaggctaccccggaattacggctaatcactccggcgattcggccccagttcgtagcgttttcagttcgttcacttatcgtgcttggtttaaagatttaggacgctccatcagatcttgacatgatatagaacgggttttactagttgactatgagcactagatgccggctctacgctagataccaaagctttgcgtctttgaggccatcttctcccatggtgtatagtatctattagaaatgccgtaac 3 4Enter pattern (a,t,g,c only): taac 5There are 6 patterns in the data 6start indices are [137, 412, 602, 1483, 1619, 1996]

投稿2021/01/10 04:27

ppaul

総合スコア24670

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

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

ishiko

2021/01/10 04:43

課題でして、CかC++を使わなければならないんです、、、
ishiko

2021/01/10 04:45

わざわざありがとうございます。 pythonやってみます。
guest

0

[ご参考] Cによる回答ではありません。C++ならこんな↓実装になるかと。

C++

1#include <iostream> 2#include <fstream> 3#include <string> 4 5int main() { 6 using namespace std; 7 ifstream stream("file.txt"); 8 if ( !stream.is_open() ) return 1; 9 10 string sequence((istreambuf_iterator<char>(stream)), istreambuf_iterator<char>()); 11 12 string pattern; 13 cout << "\nパターンを入力してください。*a,t,g,cのみ :" << std::flush; 14 cin >> pattern; 15 16 int match_count = 0; 17 for ( string::size_type pos = 0; (pos = sequence.find(pattern, pos)) != string::npos; ++pos ) { 18 ++match_count; 19 } 20 cout << "パターン[" << pattern << "]は" << match_count << "箇所に含まれています。\n"; 21}

投稿2021/01/09 18:18

編集2021/01/09 18:21
episteme

総合スコア16612

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

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

ishiko

2021/01/10 04:41

C++勉強してみます! 参考にさせていただきます。
guest

0

ベストアンサー

char ch[2000]; と宣言したら、
ch[0]~ch[1999] しかアクセスできません。ch[2000] は範囲外です。

関数main の中で、関数str_length を定義していますが、
これは gcc の拡張機能です。規格準拠の C ではそんなことはできません。
<string.h> に標準関数 strlen があるので、それを使いましょう。

if( ch[i] = str[k] ){
これは比較ではなく、代入です。== を使いましょう。

文字列の中の文字列を検索する strstr があるので、それを使うと、

C

1#include <stdio.h> // fopen, fclose, printf, fscanf, scanf 2#include <string.h> // strstr 3 4int main(void) 5{ 6 FILE *fp = fopen("file.txt", "r"); 7 if (fp == NULL) { 8 perror("ファイルの読み込みに失敗\n"); 9 return 1; 10 } 11 char ch[2000]; 12 fscanf(fp, "%1999s", ch); 13 fclose(fp); 14 15 printf("▼=====テキストファイルの内容=====▼\n%s\n", ch); 16 17 printf("\nパターンを入力してください。*a,t,g,cのみ\n"); 18 char str[2000]; 19 scanf("%1999s", str); 20 21 int count = 0; 22 for (char *p = ch; p = strstr(p, str); p++) count++; 23 24 printf("パターン「\"%s\"」は%d箇所に含まれています。", str, count); 25 return 0; 26}

これを試すとどうなりますか?

投稿2021/01/09 15:54

編集2021/01/09 16:09
kazuma-s

総合スコア8224

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

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

ishiko

2021/01/10 04:38

できました!strlen ですね?調べてみます。 上のプログラムについて分からないところまた聞くかもしれないです。
ppaul

2021/01/10 06:39

ファイルから読み込んだ塩基配列(2000文字)とのことですので、 char ch[2001]; にして、 fscanf(fp, "%2000s", ch); にしないと、最後の文字が読めていませんね。 あと、forの中のp = strstr(p, str); は、代入と判定を連続して行う処理ですので、しっかり理解しておいてください。
ishiko

2021/01/10 08:47

分かりました!ナル文字ってやつですね。 =と==の違いも理解できました。 ご丁寧にありがとうございます。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.36%

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

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

質問する

関連した質問