Чтение определенной части текстового файла в виде строки в C? - PullRequest
8 голосов
/ 19 июня 2019

Я пишу код, который читает огромные текстовые файлы, содержащие базы ДНК, и мне нужно иметь возможность извлекать определенные части. Файл выглядит так:

TGTTCCAGGCTGTCAGATGCTAACCTGGGG
TCACTGGGGGTGTGCGTGCTGCTCCAGCCT
GTTCCAGGATATCAGATGCTCACCTGGGGG

...

Каждая строка состоит из 30 символов.

У меня есть отдельный файл с указанием этих частей, то есть у меня есть значение start и значение end . Поэтому для каждого значения start и end необходимо извлечь соответствующую строку в файле. Например, если у меня есть start = 10, end = 45, мне нужно сохранить строку, которая начинается с 10-го символа первой строки (C) и заканчивается 15-м символ 2-й строки (C) в отдельном временном файле.

Я попытался использовать функцию fread, как показано ниже для тестового файла с вышеуказанными строчками букв. Параметры были start = 1, end = 90, и результирующий файл выглядит так:

TGTTCCAGGCTGTCAGATGCTAACCTGGGG
TCACTGGGGGTGTGCGTGCTGCTCCAGCCT
GTTCCAGGATATCAGATGCTCACCTGGG™eRV

Каждый запуск даст случайные символы в конце.

код:


FILE* fp;
fp=fopen(filename, "r");
if (fp==NULL) puts("Failed to open file");

int start=1, end=90;
char string[end-start+2]; //characters from start to end = end-start+1

fseek(fp, start-1, SEEK_SET);

fread(exon,1, end-start+1, fp);

FILE* tp;
tp=fopen("exon", "w");
if (tp==NULL) puts("Failed to make tmp file");

fprintf(tp, "%s\n", string);
fclose(tp);

Я не мог понять, как fread обрабатывает символы \ n, поэтому я попытался заменить его следующим:

int i=0;
char ch;
while (!feof(fp))
{
            ch=fgetc(fp);

            if (ch != '\n') 
            {
                string[i]=ch;
                i++;
                if (i==end-start) break;
            }

}
string[end-start+1]='\0';

Создан следующий файл: TGTTCCAGGCTGTCAGATGCTAACCTGGGGTCACTGGGGGTGTGCGTGCTGCTCCAGCCTGTTCCAGGATATCAGATGCTCACCTGGGGô

(без разрывов строк, что я не против). Снова при каждом запуске я получаю другой случайный символ вместо «G».

Что я делаю не так? Есть ли способ сделать это с помощью fread или какой-либо другой функции?

Заранее спасибо.

1 Ответ

1 голос
/ 19 июня 2019

Я изменил ваш код и добавил к нему комментарии для объяснения.

Пожалуйста, пройдите. Вы пренебрегли проверкой ошибок, в коде мало неопределенных переменных.

Я вернулся из блока if при ошибке, более подходящим будет goto`.

Пожалуйста, обратитесь к этому комментарию для того, чтобы добавить 1 или 2 символа к start и end.

#include <stdio.h>
#include <string.h>
#include <stdlib.h>

int main()
{
        FILE* fp;
        // fp = fopen(filename, "r");
        // since the filename is undeclared i have used hard coded file name
        fp = fopen("dna.txt", "r");
        // Nothing wrong in performing error checking
        if (fp == NULL) {
                puts("Failed to open file");
                return -1; 
        }

        // Make sure start is not 0 if you want to use indices starting from 1
        int start = 1, end = 90; 

        // I would adjust the start and end index by adding count of '\n' or '\r\n' to the start and end
        // Here I am adjusting for '\n' i.e 1 char
        // since you have 30 chars so hardcoding it.
        int m = 1; // m depends on whether it is \n or \r\n
                   // 1 for \n and 2 for \r\n
        --start; --end; // adjusting indexes to be 0 based
        if (start != 0)
                start = start + (start / 30) * m;   // start will be 0
        if (end != 0)
                end = end + (end / 30) * m;         // start will be 93

        // lets declare the chars to read
        int char_to_read = end - start + 1;

        // need only 1 extra char to append null char
        // If start and end is going to change, then i would suggest using malloc instead of static buffer
        // because compiler cannot predict the memory to allocate to the buffer if it is dependent on external factor
        // char string[char_to_read + 1]; //characters from start to end = end-start+1

        char *string = malloc(char_to_read + 1); 
        if (string == NULL) {
                printf("malloc failed\n");
                fclose(fp);
                return -2;
        }

        // zero the buffer
        memset(string, 0, char_to_read + 1); 

        int rc = fseek(fp, start, SEEK_SET);
        if (rc == -1) {
                printf("fseek failed");
                fclose(fp);
                return -1;
        }

        // exon is not defined, and btw we wanted to read in string.
        int bytes_read = fread(string, 1, char_to_read, fp);

        // Lets check if there is any error after reading
        if (bytes_read == -1) {
                fclose(fp);
                return -1; 
        }

        // Now append the null char to the end
        string[bytes_read] = 0;
        printf("%s\n", string);
        fclose(fp);

        // free the memory once you are done with it
        if (string)
                free(string);


// Now u can write it back to file.
//      FILE* tp;
//      tp=fopen("exon", "w");
//      if (tp==NULL) puts("Failed to make tmp file");

//      fprintf(tp, "%s\n", string);
//      fclose(tp);
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...