Аварийное завершение программы - C (СИ) (153295)

Узнай цену своей работы

Формулировка задачи:

В общем, благодаря советам здешних форумчан, я таки осилил небольшую программку на малознакомом мне Си (я как то больше шарп и делфи), имитирующую систему контроля версий. Суть в чем - создаем файл, руками в него что-то пишем, сохраняем в одноименной созданной папке. Потом при след запуске руками же выбираем этот же файл, редактируем и в итоге сам файл переписывается и создается его копия с номером ревизии. Все хорошо и все работает, НО при завершении программы в ветке переписывания файла происходит ошибка (хотя файл переписывается и сохраняется). Трассировал сам, пробовал разные варианты, но причину так и не отловил. Код (порядком кривой и некрасивый, но все же):
#include <stdio.h>
#include <stdlib.h>
#include <conio.h>
#include <dirent.h>
#include <direct.h>
#include <string.h>
 
const int MAX_LENGTH = 255;   //максимальная длина строки
const int ESC = 27;           //код клавиши Esc
FILE *fn;                     //указатель на файл 
 
int open_file(FILE **f, char *name, const char *type)
{
    if (((*f) = fopen(name,type)) == NULL)   //открываем файл
    {
        perror(name);                     //если не получилось - генерируем ошибку
        system("pause");
        return 1;                           //выходим из текущей итерации программы 
    }
    else return 0;
}
 
void write_to_file(FILE **f, char *name)   //запись в файл с именем name
{
     if (open_file(f,name,"w") != 0) return;
     printf("Введите содержимое нового файла (Esc для окончания ввода):\n");
     char *fstring = (char*)malloc(MAX_LENGTH);
     do
     {
        char c = getch();  
        if (c == ESC) break;      //ввод производится до нажатия пользователем Esc
        scanf("%s",fstring);      //прочитали строку
        fprintf(*f,fstring);       //записали ее в файл  
        fprintf(*f,"\n");          //добавили в файл символ переноса строки
     }
     while (true);   
     printf("Файл %s успешно записан.\n",name);
     fclose(*f);                 //закрываем файл
}
 
void make_a_copy(FILE **f, char *name, int revision)
{
     char *new_name = (char*)malloc(MAX_LENGTH);
     strcpy(new_name,name);
     sprintf(new_name, "%s_%d",name,revision);
     //strncat(new_name,ch,1);     //добавили к имени нашего файла _ и номер ревизии
     FILE *fnew;
     if ((open_file(f,name,"r") != 0) || (open_file(&fnew,new_name,"w")!=0)) return;
     char c;
     while((c = fgetc(*f)) != EOF)
       fputc(c, fnew);
     fclose(*f);
     fclose(fnew);
     printf("Копия файла с номером ревизии %d успешно создана.\n",revision);
}
 
void create_new_file(FILE **f)    //создание нового файла
{
     DIR *dir;
     printf("Введите имя нового файла: ");
     char *name = (char*)malloc(MAX_LENGTH);    
     scanf("%s",name);           //чтение имени  
     char *folder_name = (char*)malloc(MAX_LENGTH);
     strcpy(folder_name,name);
     strncat(folder_name,"/",1);  //добавляем к имени слэш для работы с директорией
     if (mkdir(name) == 0)        //пытаемся создать каталог для версий файла
     { 
        printf("Каталог для хранения версий файла %s успешно создан.\n",name);   //если такого каталога еще нет
        strncat(folder_name,name,strlen(name));    //добавили к имени каталога одноименный файл
        write_to_file(f,folder_name);              //создали и записали файл
     }
     else                                         //если каталог, а значит и файл, уже есть
     { 
        printf("Файл %s уже существует.\n Желаете ли вы его перезаписать?\n",name);
        printf("Введите y - для продолжения, n - для отмены.\n");
        printf("Ваш выбор : ");
        char *choice;
        scanf("%s",choice);                   //прочитали выбор пользователя
        if (strcmp(choice,"y") == 0)                    //если да
        { 
           int count = -2;                     //кол-во файлов в каталоге, а -2 потому что не считаются . и .. (текущий каталог и наверх)
           dir = opendir(folder_name);        //открыли каталог
           strncat(folder_name,name,strlen(name));    //добавили к имени каталога одноименный файл
           struct dirent *dp;
           while (((dp = readdir(dir)) != NULL))  //пока в каталоге есть непрочитанные файлы
           {
                 if (strcmp(dp->d_name, name)== 0)  //если найден главный файл (текущая версия)
                 {
                    write_to_file(f,folder_name);   //открыли для записи, переписали                   
                 }
                count++;                           //если файл еще не нашли - увеличили счетчик
           }
           if (count >= 1) //если у файла уже есть предыдущие версии
           {
               //make_a_copy(f,folder_name,count);  //создали копию с номером текущей ревизии     
           }
           closedir(dir);                  //закрыли директорию   
        }
        else
          if (strcmp(choice,"")!=0)
            {
               printf("Неверный код выбора.");
            }   
   }      
}

int main()
{   
    create_new_file(&fn);
    getch();
    return 0;
}
P.S. Компилятор от с++, поэтому int main() и пр. Заранее спасибо.

Решение задачи: «Аварийное завершение программы»

textual
Листинг программы
 char *choice;
   scanf("%s",choice);

Объяснение кода листинга программы

  1. Объявляется переменная типа char* с именем choice, которая будет хранить введенную пользователем строку.
  2. Пользователю предлагается ввести строку с помощью функции scanf, в которую передается форматная строка %s и адрес переменной choice.
  3. Функция scanf считывает введенную пользователем строку и сохраняет ее в переменной choice.

ИИ поможет Вам:


  • решить любую задачу по программированию
  • объяснить код
  • расставить комментарии в коде
  • и т.д
Попробуйте бесплатно

Оцени полезность:

6   голосов , оценка 3.333 из 5
Похожие ответы