Аварийное завершение программы - C (СИ) (153295)
Формулировка задачи:
В общем, благодаря советам здешних форумчан, я таки осилил небольшую программку на малознакомом мне Си (я как то больше шарп и делфи), имитирующую систему контроля версий. Суть в чем - создаем файл, руками в него что-то пишем, сохраняем в одноименной созданной папке. Потом при след запуске руками же выбираем этот же файл, редактируем и в итоге сам файл переписывается и создается его копия с номером ревизии. Все хорошо и все работает, НО при завершении программы в ветке переписывания файла происходит ошибка (хотя файл переписывается и сохраняется). Трассировал сам, пробовал разные варианты, но причину так и не отловил. Код (порядком кривой и некрасивый, но все же):
P.S. Компилятор от с++, поэтому int main() и пр. Заранее спасибо.
#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;
}Решение задачи: «Аварийное завершение программы»
textual
Листинг программы
char *choice;
scanf("%s",choice);
Объяснение кода листинга программы
- Объявляется переменная типа char* с именем choice, которая будет хранить введенную пользователем строку.
- Пользователю предлагается ввести строку с помощью функции scanf, в которую передается форматная строка
%sи адрес переменной choice. - Функция scanf считывает введенную пользователем строку и сохраняет ее в переменной choice.