2014 dxdy logo

Научный форум dxdy

Математика, Физика, Computer Science, Machine Learning, LaTeX, Механика и Техника, Химия,
Биология и Медицина, Экономика и Финансовая Математика, Гуманитарные науки




Начать новую тему Ответить на тему
 
 Помогите с файлами в СИ
Сообщение10.05.2008, 10:05 


06/10/07
68
Sverige
Написал программу в Си , которая должна записывать список в файл, затем читать список из файла и выводит на экран.Но программа вылетает .Помогите, пожалуйста, найти ошибку.Заранее спасибо.Вот текст программы :
if(choice==3)
appeand();
/#include "stdafx.h"
#include<stdio.h>
#include<stdlib.h>
#define N 3
struct student {
char name[50];
char surname[50];
unsigned char year;
struct student* next;
struct student* prev;
} ;

struct student* InputElement(){
struct student* p=(struct student*)malloc(sizeof(struct student));
printf("input name:\n");
scanf("%s",p->name);
printf("input surname:\n");
scanf("%s",p->surname);
printf("input age:\n");
scanf("%d",&(p->year));
p->next=NULL;
p->prev=NULL;
return p;
};

struct student* AddToList(struct student* root,struct student* p){
if(NULL==p){
return root;
};
p->next=root;
p->prev=p->next;
return p;
};
void Max(struct student* root){
if(NULL==root)
return;
struct student* p=root;
int max;
while(p->next!=NULL){
if (p->next->year>max) {
max=p->next->year;
}
p=p->next;
}

printf("A senior student is %d\n**********************\n",max);

};

void Output(struct student* p){
while(p!=NULL){
printf("%s\t",p->name);
printf("%s\t",p->surname);
printf("%d\n",p->year);
p=p->next;
};
};

void FreeList(struct student* root){
if(NULL==root)
return;
struct student* q=root;
struct student* p=root->next;
struct student* f=root->prev;
while (q){

if(q==NULL){
return;
}
free(q);
q=p;
if(q){
p=q->next;
f=q->prev;
};
};
};
long size(FILE*f){
long current=ftell(f);
fseek(f,0,SEEK_END);
long size=ftell(f);
fseek(f,current,SEEK_SET);
return size;
}
struct student* root=NULL;
void write(){
for(int i=0;i<N;i++){
root=AddToList(root,InputElement());
};
struct student*p=root;
FILE*f2=fopen("student.txt","w");
while(p!=NULL){
fwrite(p,sizeof(p),1,f2);
p=p->next;
};
Max(root);
Output(root);
FreeList(root);
fclose(f2);
}
void read(){
FILE*f2=fopen("student.txt","r");
struct student*p=(struct student*)malloc(sizeof(struct student));
fread(&p,sizeof(p),1,f2);
while(p!=NULL){
for(int i=0;i<N;i++){
root=AddToList(root,p);
};
p=p->next;
};
Output(root);
fclose(f2);
}
void appeand(){
FILE*f2=fopen("student.txt","a");
long offset=ftell(f2);
void*e=(FILE*)malloc(offset);
for(int i=0;i<N;i++){
root=AddToList(root,InputElement());
}
struct student*p=root;
while(p!=NULL){
fwrite(e,sizeof(p),1,f2);
p=p->next;
};
free(e);
FreeList(root);
fclose(f2);
}


void main(){
int choice;
printf("1-read\n2-write\n3-appeand\n");
scanf("%d",&choice);
if(choice==1)
read();
if(choice==2)
write();
}

 Профиль  
                  
 
 
Сообщение10.05.2008, 11:35 


21/03/06
1545
Москва
Даже смотреть не буду, пока не вставите текст программы в тег CODE, и не отформатируете по-человечески.

Далее, "программа вылетает" - это слишком общий симптом. Конкретизируйте, как, как часто, при каком действии вылетает. Что из отладочных средств Вы пробовали применить и т.п.

 Профиль  
                  
 
 
Сообщение10.05.2008, 13:26 


06/10/07
68
Sverige
Извините. а вы можете сказать .что такое тэг Code ? Программа вылетает. когда я хочу прочитать записанный список в файл.

 Профиль  
                  
 
 
Сообщение10.05.2008, 15:41 


21/03/06
1545
Москва
Цитата:
Извините. а вы можете сказать .что такое тэг Code ?

В начале текста Вашей программы пишите [cоde], в конце - [/cоde], или, что тоже самое, выделяете мышкой весь текст Вашей программы в окошке браузера, и жмете на кнопочку Code сверху окошка набора сообщения. Она делает то же самое. При этом оформление текста Вашей программы сохраняется (отступы, табуляция и пр.), а также программа попадает в красиво оформленную, отделенную часть сообщения.

Цитата:
Программа вылетает. когда я хочу прочитать записанный список в файл.

Извините, не понял - так прочитать из файла, или все-таки записать в файл???

 Профиль  
                  
 
 
Сообщение10.05.2008, 16:36 


06/10/07
68
Sverige
Код:
if(choice==3)
appeand();
/#include "stdafx.h"
#include<stdio.h>
#include<stdlib.h>
#define N 3
struct student {
char name[50];
char surname[50];
unsigned char year;
struct student* next;
struct student* prev;
} ;

struct student* InputElement(){
struct student* p=(struct student*)malloc(sizeof(struct student));
printf("input name:\n");
scanf("%s",p->name);
printf("input surname:\n");
scanf("%s",p->surname);
printf("input age:\n");
scanf("%d",&(p->year));
p->next=NULL;
p->prev=NULL;
return p;
};

struct student* AddToList(struct student* root,struct student* p){
if(NULL==p){
return root;
};
p->next=root;
p->prev=p->next;
return p;
};
void Max(struct student* root){
if(NULL==root)
return;
struct student* p=root;
int max;
while(p->next!=NULL){
if (p->next->year>max) {
max=p->next->year;
}
p=p->next;
}

printf("A senior student is %d\n**********************\n",max);

};

void Output(struct student* p){
while(p!=NULL){
printf("%s\t",p->name);
printf("%s\t",p->surname);
printf("%d\n",p->year);
p=p->next;
};
};

void FreeList(struct student* root){
if(NULL==root)
return;
struct student* q=root;
struct student* p=root->next;
struct student* f=root->prev;
while (q){

if(q==NULL){
return;
}
free(q);
q=p;
if(q){
p=q->next;
f=q->prev;
};
};
};
long size(FILE*f){
long current=ftell(f);
fseek(f,0,SEEK_END);
long size=ftell(f);
fseek(f,current,SEEK_SET);
return size;
}
struct student* root=NULL;
void write(){
for(int i=0;i<N;i++){
root=AddToList(root,InputElement());
};
struct student*p=root;
FILE*f2=fopen("student.txt","w");
while(p!=NULL){
fwrite(p,sizeof(p),1,f2);
p=p->next;
};
Max(root);
Output(root);
FreeList(root);
fclose(f2);
}
void read(){
FILE*f2=fopen("student.txt","r");
struct student*p=(struct student*)malloc(sizeof(struct student));
fread(&p,sizeof(p),1,f2);
while(p!=NULL){
for(int i=0;i<N;i++){
root=AddToList(root,p);
};
p=p->next;
};
Output(root);
fclose(f2);
}
void appeand(){
FILE*f2=fopen("student.txt","a");
long offset=ftell(f2);
void*e=(FILE*)malloc(offset);
for(int i=0;i<N;i++){
root=AddToList(root,InputElement());
}
struct student*p=root;
while(p!=NULL){
fwrite(e,sizeof(p),1,f2);
p=p->next;
};
free(e);
FreeList(root);
fclose(f2);
}


void main(){
int choice;
printf("1-read\n2-write\n3-appeand\n");
scanf("%d",&choice);
if(choice==1)
read();
if(choice==2)
write();
}[code][/code]



Добавлено спустя 27 секунд:

Программа вылетает при чтении из файла.

 Профиль  
                  
 
 
Сообщение10.05.2008, 17:24 


21/03/06
1545
Москва
Товарищ! Хорошо, что Вы научились работать с тегом CODE, однако форматирования текста программы у Вас как не было, так и нет! Расставьте пробелы и/или знаки табуляции где это нужно, в соответствии со стандартами языка Си, будьте добры!

Не анализируя текст Вашей программы, фраза "Программа вылетает при чтении из файла." наводит на мысль о том, что Вы не выделили достаточно памяти, или выделили ее криво, для данных, читаемых из файла. В любом случае, после запуска Вашей программы в 90% случаев, должно выводиться сообщение, позволяющее как-то проанализировать причину "вылета". Напишите ОС и компилятор, который Вы используете!

Добавлено спустя 4 минуты 40 секунд:

Пример правильного форматирования текста программы Вы можете посмотреть, например, тут.

 Профиль  
                  
 
 
Сообщение10.05.2008, 18:36 


06/10/07
68
Sverige
Код:
if(choice==3)
appeand();
/#include "stdafx.h"
#include<stdio.h>
#include<stdlib.h>
#define N 3
struct student
{
   char name[50];
   char surname[50];
   unsigned char year;
   struct student* next;
   struct student* prev;
} ;

struct student* InputElement()
{
    struct student* p=(struct student*)malloc(sizeof(struct student)); 
    printf("input name:\n");
    scanf("%s",p->name);
    printf("input surname:\n");
    scanf("%s",p->surname);
    printf("input age:\n");
    scanf("%d",&(p->year));
    p->next=NULL;
    p->prev=NULL;
    return p;
};

struct student* AddToList(struct student* root,struct student* p)
{
  if(NULL==p)
   {
     return root;
   };
  p->next=root;
  p->prev=p->next;
  return p;
};
void Max(struct student* root)
{
  if(NULL==root)
  return;
  struct student* p=root;
  int max;
  while(p->next!=NULL){
  if (p->next->year>max)
  {
     max=p->next->year;
  }
   p=p->next;
}

printf("A senior student is %d\n**********************\n",max);

};

void Output(struct student* p)
{
   while(p!=NULL)
  {
     printf("%s\t",p->name);
     printf("%s\t",p->surname);
     printf("%d\n",p->year);
     p=p->next;
   };
};

void FreeList(struct student* root)
{
   if(NULL==root)
   return;
   struct student* q=root;
   struct student* p=root->next;
   struct student* f=root->prev;
   while (q)
  {

     if(q==NULL)
    {
   return;
    }
    free(q);
    q=p;
    if(q)
      {
    p=q->next;
    f=q->prev;
      };
   };
};
long size(FILE*f)
{
   long current=ftell(f);
   fseek(f,0,SEEK_END);
   long size=ftell(f);
   fseek(f,current,SEEK_SET);
   return size;
}
struct student* root=NULL;
void write()
{
   for(int i=0;i<N;i++)
  {
     root=AddToList(root,InputElement());
  };
  struct student*p=root;
  FILE*f2=fopen("student.txt","w");
  while(p!=NULL)
   {
     fwrite(p,sizeof(p),1,f2);
     p=p->next;
   };
  Max(root);
  Output(root);
  FreeList(root);
  fclose(f2);
}
void read()
{
  FILE*f2=fopen("student.txt","r");
  struct student*p=(struct student*)malloc(sizeof(struct student));
  fread(&p,sizeof(p),1,f2);
  while(p!=NULL)
   {
    for(int i=0;i<N;i++)
     {
     root=AddToList(root,p);
     };
   p=p->next;
   };
  Output(root);
  fclose(f2);
}
  void appeand()
{
  FILE*f2=fopen("student.txt","a");
  long offset=ftell(f2);
  void*e=(FILE*)malloc(offset);
  for(int i=0;i<N;i++)
    {
     root=AddToList(root,InputElement());
    }
  struct student*p=root;
  while(p!=NULL)
    {
     fwrite(e,sizeof(p),1,f2);
     p=p->next;
     };
  free(e);
  FreeList(root);
  fclose(f2);
}


  void main()
{
  int choice;
  printf("1-read\n2-write\n3-appeand\n");
  scanf("%d",&choice);
  if(choice==1)
  read();
  if(choice==2)
  write();
}[code][/code]


Добавлено спустя 39 секунд:

Я использую Microsoft VIsual studio.

 Профиль  
                  
 
 
Сообщение10.05.2008, 21:47 
Заслуженный участник


15/05/05
3445
USA
Несколько вопросов:

1. Какого типа ваш файл с данными? Судя по расширению - текстовый, судя по операциям чтения-записи - двоичный.
Какой тип Вы указали в Вашей программе?

2. Для переменной
Код:
struct student *p;
чему равно
Код:
sizeof(p)
?

3. Почему у Вас конец функции main() залез в начало кода? :)

 Профиль  
                  
 
 
Сообщение10.05.2008, 23:29 


06/10/07
68
Sverige
1.Мой файл с данными должен быть текстовым .Как написать операцию чтения и записи, так что бы он оставался текстовым?
2.Честно говоря, даже не знаю. Это очень важно ?
3.Извиняюсь:)))

 Профиль  
                  
 
 
Сообщение11.05.2008, 01:20 
Заслуженный участник


15/05/05
3445
USA
Dmytro Sheludchenko писал(а):
2.Честно говоря, даже не знаю. Это очень важно ?
Два моих вопроса (3-й не в счет) касаются принципиальных проблем Вашей программы, которые сразу бросаются в глаза. Это была подсказка для Вас:
1) Вы открываете текстовый файл, открываете в режиме "text", но читаете как двоичный.
2) Если бы файл вдруг случайно оказался двоичным, открытым в режиме "binary", то все равно Вы неправильно задаете размер записи.
sizeof(p) - это размер указателя, а не размер struct student, на которую он указывает.

Цитата:
Как написать операцию чтения и записи, так что бы он оставался текстовым?
Вам бы учебник почитать...

 Профиль  
                  
 
 
Сообщение11.05.2008, 10:12 


06/10/07
68
Sverige
В учебнике Кернигана очень мало сказано про файлы и работу с ними В этом и проблема.Не могли бы Вы подсказать мне, как решить эту проблему?

 Профиль  
                  
 
 
Сообщение11.05.2008, 10:49 
Заслуженный участник


15/05/05
3445
USA
Dmytro Sheludchenko писал(а):
В учебнике Кернигана очень мало сказано про файлы и работу с ними В этом и проблема.Не могли бы Вы подсказать мне, как решить эту проблему?
Книга Кернигана и Ричи - это учебник по языку С. А работа с файлами в С - это не часть языка, а часть библиотеки поддержки. Смотрите учебники по VS, Help/MSDN. Есть примеры, поставляемые вместе с VS.

 Профиль  
                  
 
 
Сообщение12.05.2008, 05:05 


08/01/08
21
Первый корень ваших проблем -- непонимание разницы между
char abc[50];
и
char *abc;

В первом случае распределяется 50 байт под массив. Вы можете сразу сделать scanf("%s", abc); и пользователь может ввести не более 50 байт, иначе -- выход за границы памяти (ошибку не получите, но времени на отладку потратите прилично).

Во втором случае в памяти распределяется указатель. Только указатель, указывающий на случайную ячейку памяти. Перед его использованием сначала нужно выделить память и записать полученный указатель в abc. Только после этого возможно scanf("%s", abc); Снова, если пользователь введёт больше данных, чем выделено памяти -- выход за границы памяти.

Разница в том, что в первом случае у вас массив char[50], точно так же как и был бы int[123], и double[456]. Просто в Си значением переменной-массива является адрес её нулевого элемента, то есть, указатель на нулевой элемент,

Во втором случае -- просто указатель.

Другая проблема исходит из первой. sizeof(имя переменной) равняется sizeof(тип этой переменной). Пусть у вас
struct student st;
В данном случае st -- это сама структура. Под неё уже выделена память. sizeof(p) или sizeof(struct student) будет включать размер всей структуры, всех её полей.

Второй вариант:
struct student *p;
Тут p -- просто указатель. Без разницы, какой адрес памяти вы ему присвоите, размер самого указателя не изменится. Так вот, sizeof(p) или sizeof(struct student *) это и есть размер самого указателя. Это размер той памяти, которая достаточна для хранения адреса структуры struct student.

Общие замечания по коду:
* не ставьте точки с запятой после блоков функций, после блоков while(){}, if(){} и так далее. В Си точка с запятой после блока с кодом никогда не ставится (в смысле, не требуется синтаксически, как в паскале function ... begin ... end; <-- тут нужна точка с запятой). Да, это разрешено синтаксисом, и даже работает, но обозначает совершенно не то, что вы ожидали (в Си точка с запятой сама по себе обозначает "пустой оператор" -- указание "ничего не делать").

* пользуйтесь отступами. Вам может показаться, что это лишняя трата времени, но подумайте о следующем. Расстановка отступов займёт от силы минуты три. А ваш код форумчане рассматривают уже два дня. Да я мне кажется, что и вы сами как минимум пол-часа просто смотрели на свой код, пытаясь найти ошибки. Расстановка отсупов и пробелов внутри выражений здорово помогает чтению кода.

 Профиль  
                  
Показать сообщения за:  Поле сортировки  
Начать новую тему Ответить на тему  [ Сообщений: 13 ] 

Модераторы: Karan, Toucan, PAV, maxal, Супермодераторы



Кто сейчас на конференции

Сейчас этот форум просматривают: нет зарегистрированных пользователей


Вы не можете начинать темы
Вы не можете отвечать на сообщения
Вы не можете редактировать свои сообщения
Вы не можете удалять свои сообщения
Вы не можете добавлять вложения

Найти:
Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group