Проблема при открытии файла И, возможно, при файловом вводе / выводе в строку

#c #arrays #string #char

#c #массивы #строка #символ

Вопрос:

Я пытаюсь написать программу, которая скопирует файл в строку (пока все хорошо получается), которая будет содержать базы ДНК. Затем основы преобразуются в белки, сначала находят первую последовательность ATG, затем считывают последовательности по 3 и конвертируют их, записывая в другой файл.

На данный момент программа завершает работу перед входом в первый цикл for .. И я не знаю, что вызывает проблему.

 int proteina(char DNA_origem[], char proteina_destino[]){
char aminocidosING [64][14]={"Isoleucine","Isoleucine","Isoleucine","Leucine","Leucine","Leucine","Leucine","Leucine","Leucine","Valine","Valine","Valine","Valine","Phenylalanine","Phenylalanine","Methionine","Cysteine","Cysteine","Alanine","Alanine","Alanine","Alanine","Glycine","Glycine","Glycine","Glycine","Proline","Proline","Proline","Proline","Threonine","Threonine","Threonine","Threonine","Serine","Serine","Serine","Serine","Serine","Serine","Tyrosine","Tyrosine","Tryptophan","Glutamine","Glutamine","Asparagine","Asparagine","Histidine","Histidine","Glutamic acid","Glutamic acid","Aspartic acid","Aspartic acid","Lysine","Lysine","Arginine","Arginine","Arginine","Arginine","Arginine","Arginine","Stop codons","Stop codons","Stop codons"};
char aminocidosPT [64][18]={"Isoleucina","Isoleucina","Isoleucina","Leucina","Leucina","Leucina","Leucina","Leucina","Leucina","Valina","Valina","Valina","Valina","Fenilalanina","Fenilalanina","Metionina","Cisteína","Cisteína","Alanina","Alanina","Alanina","Alanina","Glicina","Glicina","Glicina","Glicina","Prolina","Prolina","Prolina","Prolina","Treonina","Treonina","Treonina","Treonina","Serina","Serina","Serina","Serina","Serina","Serina","Tirosina","Tirosina","Triptofano","Glutamina*","Glutamina","Asparagina","Asparagina","Histidina","Histidina","Ácido glutâmico","Ácido glutâmico","Ácido aspártico","Ácido aspártico","Lisina","Lisina","Arginina","Arginina","Arginina","Arginina","Arginina","Arginina","Códons Stop","Códons Stop","Códons Stop"};
char codoes[64][3]={"ATT","ATC","ATA","CTT","CTC","CTA","CTG","TTA","TTG","GTT","GTC","GTA","GTG","TTT","TTC","ATG","TGT","TGC","GCT","GCC","GCA","GCG","GGT","GGC","GGA","GGG","CCT","CCC","CCA","CCG","ACT","ACC","ACA","ACG","TCT","TCC","TCA","TCG","AGT","AGC","TAT","TAC","TGG","CAA","CAG","AAT","AAC","CAT","CAC","GAA","GAG","GAT","GAC","AAA","AAG","CGT","CGC","CGA","CGG","AGA","AGG","TAA","TAG","TGA"};
char proteinas[64][1] = {"I","I","I","L","L","L","L","L","L","V","V","V","V","F","F","M","C","C","A","A","A","A","G","G","G","G","P","P","P","P","T","T","T","T","S","S","S","S","S","S","Y","Y","W","Q","Q","N","N","H","H","E","E","D","D","K","K","R","R","R","R","R","R",".",".","."};

/* a esta altura suponho que tenhas definido na main as strings dos aminoácidos*/


char **string1; 
FILE * ficheiro;
FILE * ficheiro_close;
int f_cmp; 
int k, i, start=0; /* variavel de comprimento */
char proteina_origem;

ficheiro = fopen(DNA_origem,"r"); /* DNA origem e a variavel onde ta guardada o nome do ficheiro do utilizador */
ficheiro_close = fopen(proteina_destino,"w ");

fscanf(ficheiro,"%c",string1); /* isto lê os conteudos da stream para a string, copiando pra lá o ficheiro. */

for(i=1;i<=f_cmp;i  ) {

   if (strncmp(string1[i],codoes[15],3)==0) {
      fputs(proteinas[15],ficheiro_close);

      for(k=i 2;k<=f_cmp;k 3) {

         if ((strncmp(string1[k],codoes[k],3))==0) {
            fputs(proteinas[k],ficheiro_close);

            if (k==61amp;amp;k==62amp;amp;k==63) {
                return(0);
            }
          }
        }
      }
    }
}
  

Кроме того, компилятор выдает предупреждение, если я не использую ** при определении символа. Не могли бы вы пролить немного света, пожалуйста? Это должен быть всего лишь простой проект, но я застрял в этой последней функции..

Не обращайте внимания на имена переменных и комментарии, они на португальском.

Большое вам спасибо за ваше время!

Комментарии:

1. Перед его использованием убедитесь, что ficheiro указан действительный указатель на файл (путем проверки if(ficheiro)

2. У меня раньше был printf для тестирования, распечатывающий переменную, и это сработало как по волшебству.

3. Также не хватает немного кода, но он все равно не работает, на всякий случай, перед циклом for, f_cmp=strlen(*string1);

4. Хорошо, тогда, вероятно, дело не в этом, но вы все равно должны проверять указатели на файлы в любом случае 🙂

5. String1 беспокоит меня по ряду направлений, поскольку сначала он используется как символ в fscanf. Затем вы пытаетесь использовать его как строку, разыменовывая его, но это не строка… И вы пропускаете 0-й элемент (массивы в C изменяются от 0 до размера 1), так что вы, скорее всего, перейдете к концу.

Ответ №1:

Если вы используете указатели, то после объявления вы должны инициализировать указатель подходящей допустимой памятью. После инициализации указатель указывает только на адрес, либо на адрес какой-либо другой переменной, либо на память, которую вы создаете для этого указателя (например, с помощью malloc() или оператора new). Лучше используйте массив символов, если это не повредит вашему подходу к кодированию для выполнения вашей задачи.

Однако, если вы объявите string1 как

символ ** string1

используйте fscanf следующим образом:

fscanf(ficheiro,"%c", *string1);

Комментарии:

1. Когда указатель только объявлен, он вообще не указывает на адрес.

2. @DaRk_f0x: Попробуйте использовать cin>> или getline() вместо fscanf, или используйте объекты fstream для чтения из файлов, поскольку это более удобно. Но это мое предложение, вам решать, какое из них подходит лучше.

Ответ №2:

Я полагаю, что одна проблема связана с вашим fscanf вызовом. Вы пытаетесь отсканировать значение и сохранить его в переменной string1, но для string1 не выделено памяти. Как у вас есть сейчас, string1 — это просто указатель на указатель на символ char, поэтому нет места для хранения фактического строкового значения. Вы могли бы либо разместить его в стеке, либо разместить в куче. Попробуйте что-то вроде этого:

 char string1[80]; // Or use whatever size makes sense here

...

fscanf(ficheiro, "%c", string1);
  

Кроме того, возможно, вы уже делаете это, но вы должны fclose восстановить файлы, когда закончите с ними.

Комментарии:

1. У меня была запущена программа с char string1[10] , и она все еще не работала, возможно, потому, что файл предположительно неизвестного размера? В строке это было бы длиной более 1200 символов.

2. Также файл никогда не имеет фиксированного размера, потому что я успешно работал с char string[] ранее, но, похоже, проблема может быть в неизвестном размере..

3. @DaRk_f0x: Не стесняйтесь делать строку более объемной — например, 16384, 65536 — она находится в стеке и будет восстановлена при завершении функции. НО: %c считывает только один символ — вы, вероятно, хотите «%s» или «%[xyz]» — прочитайте свою scanf справочную страницу. А еще лучше, используйте механизмы C : if (std::ifstream ficheiro(DNA_origem)) { std::string string1; if (std::getline(ficheiro, string1)) { ... } } . std::string может увеличиваться до любого размера. Действительно ли в вашем файле всего одна строка?

4. @OP: вы хотите читать построчно, используя fscanf? Это плохая идея, если вы не хотите использовать токенизированное чтение из файла. для чтения строк используйте функцию fgets. И если вам нужно заранее узнать размер файла, используйте функцию stat, чтобы получить все атрибуты / параметры, связанные с файлом.. который включает размер файла в байтах.

5. Это проект для класса моей подруги, и учитель против того, чтобы они использовали более продвинутые материалы.. Предполагалось, что я должен был спроектировать цикл, используя только fputc и fgetc и тому подобное, даже fcnaf для работы со строкой обычно не разрешался, если бы я слушал все, что говорит парень.. Но я не могу заставить его работать с такими базовыми командами, поскольку мне приходится искать в блоках по 3 =

Ответ №3:

Это неправильно :

fscanf(ficheiro,"%c",string1);

Я вижу, что string1 только объявлена, но не инициализирована.

Комментарии:

1. Я не уверен, что понимаю, что вы имеете в виду: S

2. Именно то, что говорили другие. символ ** string1 должен указывать на некоторую память .. либо в стеке, либо в куче. Поскольку вы не сделали ни того, ни другого ..fscanf завершится ошибкой.