[英]Get the length of each line in file with C and write in output file
我是一名生物學專業的學生,我試圖學習perl,python和C,並且還在我的工作中使用這些腳本。 因此,我有一個文件如下:
>sequence1
ATCGATCGATCG
>sequence2
AAAATTTT
>sequence3
CCCCGGGG
輸出應如下所示,即每個序列的名稱以及每一行中的字符數,並在文件末尾打印序列的總數。
sequence1 12
sequence2 8
sequence3 8
Total number of sequences = 3
我可以使perl和python腳本正常工作,以python腳本為例:
#!/usr/bin/python
import sys
my_file = open(sys.argv[1]) #open the file
my_output = open(sys.argv[2], "w") #open output file
total_sequence_counts = 0
for line in my_file:
if line.startswith(">"):
sequence_name = line.rstrip('\n').replace(">","")
total_sequence_counts += 1
continue
dna_length = len(line.rstrip('\n'))
my_output.write(sequence_name + " " + str(dna_length) + '\n')
my_output.write("Total number of sequences = " + str(total_sequence_counts) + '\n')
現在,我想用C編寫相同的腳本,這是我到目前為止已經實現的:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(int argc, char *argv[])
{
input = FILE *fopen(const char *filename, "r");
output = FILE *fopen(const char *filename, "w");
double total_sequence_counts = 0;
char sequence_name[];
char line [4095]; // set a temporary line length
char buffer = (char *) malloc (sizeof(line) +1); // allocate some memory
while (fgets(line, sizeof(line), filename) != NULL) { // read until new line character is not found in line
buffer = realloc(*buffer, strlen(line) + strlen(buffer) + 1); // realloc buffer to adjust buffer size
if (buffer == NULL) { // print error message if memory allocation fails
printf("\n Memory error");
return 0;
}
if (line[0] == ">") {
sequence_name = strcpy(sequence_name, &line[1]);
total_sequence_counts += 1
}
else {
double length = strlen(line);
fprintf(output, "%s \t %ld", sequence_name, length);
}
fprintf(output, "%s \t %ld", "Total number of sequences = ", total_sequence_counts);
}
int fclose(FILE *input); // when you are done working with a file, you should close it using this function.
return 0;
int fclose(FILE *output);
return 0;
}
但是這段代碼當然充滿了錯誤,我的問題是,盡管學習了很多,但我仍然無法正確理解和使用內存分配和指針,因此我知道我在那部分尤其有錯誤。 如果您可以對我的代碼發表評論,看看它如何變成可以實際運行的腳本,那就太好了。 順便說一句,在我的實際數據中,每行的長度都沒有定義,因此我需要為此使用malloc和realloc。
對於像這樣的簡單程序,您一次只看幾行,就不必擔心動態內存分配。 使用合理大小的本地緩沖區可能已經足夠了。
另一件事是,C不特別適合於快速和骯臟的字符串處理。 例如,標准庫中沒有strstrip
函數。 您通常最終自己實現這種行為。
一個示例實現如下所示:
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <ctype.h>
#define MAXLEN 80 /* Maximum line length, including null terminator */
int main(int argc, char *argv[])
{
FILE *in;
FILE *out;
char line[MAXLEN]; /* Current line buffer */
char ref[MAXLEN] = ""; /* Sequence reference buffer */
int nseq = 0; /* Sequence counter */
if (argc != 3) {
fprintf(stderr, "Usage: %s infile outfile\n", argv[0]);
exit(1);
}
in = fopen(argv[1], "r");
if (in == NULL) {
fprintf(stderr, "Couldn't open %s.\n", argv[1]);
exit(1);
}
out = fopen(argv[2], "w");
if (in == NULL) {
fprintf(stderr, "Couldn't open %s for writing.\n", argv[2]);
exit(1);
}
while (fgets(line, sizeof(line), in)) {
int len = strlen(line);
/* Strip whitespace from end */
while (len > 0 && isspace(line[len - 1])) len--;
line[len] = '\0';
if (line[0] == '>') {
/* First char is '>': copy from second char in line */
strcpy(ref, line + 1);
} else {
/* Other lines are sequences */
fprintf(out, "%s: %d\n", ref, len);
nseq++;
}
}
fprintf(out, "Total number of sequences. %d\n", nseq);
fclose(in);
fclose(out);
return 0;
}
許多代碼是關於強制參數以及打開和關閉文件的。 (如果您將stdin
和stdout
用於文件重定向,則可能會削減很多代碼。)
核心是大的while
循環。 注意事項:
fgets
將返回NULL
。 '\\0'
終止 ">"
是由兩個字符'>'
和結束的'\\0'
的字符串文字。 int
,但是因為一行中不能有負數個字符,所以使用無符號類型可能會更好。) line + 1
等效於&line[1]
。 對於初學者來說,這可能是很多需要跟蹤的地方。 對於像您這樣的小型文本處理任務,Python和Perl絕對更適合。
編輯 :上面的解決方案不適用於長序列; 僅限MAXLEN
字符。 但是,如果只需要長度而不是序列的內容,則不需要動態分配。
這是一個不讀取行,而是讀取字符的更新版本。 在'>'
上下文中,它存儲了引用。 否則,它只會保持計數:
#include <stdlib.h>
#include <stdio.h>
#include <ctype.h> /* for isspace() */
#define MAXLEN 80 /* Maximum line length, including null terminator */
int main(int argc, char *argv[])
{
FILE *in;
FILE *out;
int nseq = 0; /* Sequence counter */
char ref[MAXLEN]; /* Reference name */
in = fopen(argv[1], "r");
out = fopen(argv[2], "w");
/* Snip: Argument and file checking as above */
while (1) {
int c = getc(in);
if (c == EOF) break;
if (c == '>') {
int n = 0;
c = fgetc(in);
while (c != EOF && c != '\n') {
if (n < sizeof(ref) - 1) ref[n++] = c;
c = fgetc(in);
}
ref[n] = '\0';
} else {
int len = 0;
int n = 0;
while (c != EOF && c != '\n') {
n++;
if (!isspace(c)) len = n;
c = fgetc(in);
}
fprintf(out, "%s: %d\n", ref, len);
nseq++;
}
}
fprintf(out, "Total number of sequences. %d\n", nseq);
fclose(in);
fclose(out);
return 0;
}
筆記:
fgetc
從文件讀取一個字節,並在文件結束時返回此字節或EOF
。 在此實現中,這是唯一使用的閱讀功能。 fgetc
在這里實現的。 您也可以在跳過初始尖括號后使用fgets
。 n
是總計數, len
是直到最后一個非空格的計數。 (您的行可能僅由ACGT組成,沒有任何尾隨空格,因此您可以跳過空格測試,並使用n
代替len
。) #include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(int argc, char *argv[]){
FILE *my_file = fopen(argv[1], "r");
FILE *my_output = fopen(argv[2], "w");
int total_sequence_coutns = 0;
char *sequence_name;
int dna_length;
char *line = NULL;
size_t size = 0;
while(-1 != getline(&line, &size, my_file)){
if(line[0] == '>'){
sequence_name = strdup(strtok(line, ">\n"));
total_sequence_coutns +=1;
continue;
}
dna_length = strlen(strtok(line, "\n"));
fprintf(my_output, "%s %d\n", sequence_name, dna_length);
free(sequence_name);
}
fprintf(my_output, "Total number of sequences = %d\n", total_sequence_coutns);
fclose(my_file);
fclose(my_output);
free(line);
return (0);
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.