Перейти из форума на сайт.

НовостиФайловые архивы
ПоискАктивные темыТоп лист
ПравилаКто в on-line?
Вход Забыли пароль? Первый раз на этом сайте? Регистрация
Компьютерный форум Ru.Board » Компьютеры » Прикладное программирование » Какую структуру данных для данной задачи на СИ рекомендуете?

Модерирует : ShIvADeSt

 Версия для печати • ПодписатьсяДобавить в закладки
Страницы: 1 2 3

Открыть новую тему     Написать ответ в эту тему

zam

Junior Member
Редактировать | Профиль | Сообщение | Цитировать | Сообщить модератору
Есть текстовый файл содержания:
 
ФИО
адрес
телефон
оценки по предметам (554554445) - каждая оценка своему предмету
 
ФИО
адрес
телефон
оценки по предметам (554554445) - каждая оценка своему предмету
 
ФИО
адрес
телефон
оценки по предметам (554554445) - каждая оценка своему предмету
 
ФИО
адрес
телефон
оценки по предметам (554554445) - каждая оценка своему предмету
 
И т.д. получаем базу данных. нужно придумать какую-то структуру данных (как представлять инфу), с учетом того, что требуется сортировать по фамилии, среднему баллу оценок -- все выводить на экран (в зависимости от выбора пользователей - или показывать то то или т то, сортировать по такому то критерию, редактировать, добавлять элементы в базу, сохранять базу в файл. Юзаю Борланд СИ 3.1 (все под ДОСом).
 
Как проще решить задачу и покажите как осуществить доступ ко всем полям (согласно вашему типу данных), главное простота в обращении. Спасибо.

Всего записей: 185 | Зарегистр. 19-01-2003 | Отправлено: 05:07 11-05-2003
Duke Shadow



Silver Member
Редактировать | Профиль | Сообщение | Цитировать | Сообщить модератору
Тебе в С или в С++?
Если в С, то сложнее. Если в С++, то классы - решение твоей проблемы. Первым делом класс строка (т.к. по умолчанию в БС++ 3.1 он отсутствует). Потом класс запись_в_базе_данных. Перегружай потоковые операторы ввода-вывода - получишь возможность читать и писать в файлы. Сортировку пиши с использованием библиотечной qsort - так проще. Дальше думаю сам разберёшься.
 
Вообще вопрос уж очень объемный, да и писать за тебя проги никто не будет.

Всего записей: 3911 | Зарегистр. 15-02-2003 | Отправлено: 06:49 12-05-2003
VonSimon



Advanced Member
Редактировать | Профиль | Сообщение | ICQ | Цитировать | Сообщить модератору
Duke Shadow

Цитата:
Юзаю Борланд СИ 3.1 (все под ДОСом).  

zam
Обыкновенный список на указателях чем не устраивает?
Или на курсорах...

Всего записей: 671 | Зарегистр. 14-01-2003 | Отправлено: 08:20 12-05-2003
zam

Junior Member
Редактировать | Профиль | Сообщение | Цитировать | Сообщить модератору
VonSimon
Можешь продемонстрировать? Можно просто массив юзать, первоначально нулевой, задавать определенную длину полей и считывать строку из файла в строку массива:
ФИО00000 Адрес000 Телефон0 Оценки00 - по восемь полей. Но расскажи про свою идею про список на указателях.
 
Да, никаких классов. Онли АНСИ СИ!

Всего записей: 185 | Зарегистр. 19-01-2003 | Отправлено: 14:39 12-05-2003
rew



Full Member
Редактировать | Профиль | Сообщение | ICQ | Цитировать | Сообщить модератору
ну дык делаешь структуру
typedef struct{
   char* fio;
   char* address;
   long telephone;// или тоже через стринг сделать
   int marks[9];
}student_data;
а там уже хоть просто массив, хоть связаный список, а хоть и дерево, как удобней

Всего записей: 442 | Зарегистр. 09-09-2001 | Отправлено: 14:55 12-05-2003
Peroon_N



Member
Редактировать | Профиль | Сообщение | ICQ | Цитировать | Сообщить модератору
rew
добавление к твоему предложению:
Я бы сделал еще одну структуру с указателем на student_data
и просто через new создавал новые структуры по шаблону student_data и указатели на них прибавлял в структуру с указателем...
удобно при записи в файл... сохраняеш весь этот ворох в файл и открываеш его от туда как хочеш, только счетчик надо сохранять дабы пямять неразрушить...
Код увы привести немогу, давно не кодил на С....

Всего записей: 281 | Зарегистр. 26-03-2003 | Отправлено: 16:59 12-05-2003
rew



Full Member
Редактировать | Профиль | Сообщение | ICQ | Цитировать | Сообщить модератору
Peroon_N
дых я ж и грю что вариатов море

Всего записей: 442 | Зарегистр. 09-09-2001 | Отправлено: 17:39 12-05-2003
VonSimon



Advanced Member
Редактировать | Профиль | Сообщение | ICQ | Цитировать | Сообщить модератору
zam
Создаешь структуру типа описанного выше
И оформляешь на нее указатель
При добавлении новых данных, функцией new, malloc (не помню точно) выделяешь память для новой структуры, записываешь ее, и указатель предыдущей структуры оформляешь на новую.
Таким образом у тебя есть указатель на начало списка и каждая структура указывает на последующую. Последняя указывает на ноль.

Всего записей: 671 | Зарегистр. 14-01-2003 | Отправлено: 19:36 12-05-2003
Begmart



Junior Member
Редактировать | Профиль | Сообщение | Цитировать | Сообщить модератору
Попытаюсь обобщить :). За код не отвечаю - на си давно не писал. Так вот...
Создаешь необходимую структуру - как вышеприведённая, только доработанная под твои нужды. Например:

Код:
typedef struct{  
   char* fio;
   char* address;
   char* phone;
   char* marks;
} student;

Оценки сделал массивом чаров на случай, если их переменное количество. Как вариант можно сделать фиксированный размер записи (если записей не слишком много). Далее делаешь любой вид масства переменного размера - или связанный список или массив ссылок. Таким образом, при добавлении новой записи, во-первых, создаёшь экземпляр student, а во-вторых с помощью new или malloc (лушче new, хотя без разницы) заполняешь поля. Всё. Или тебе код написать? ;)

Всего записей: 99 | Зарегистр. 05-04-2003 | Отправлено: 20:10 12-05-2003
VonSimon



Advanced Member
Редактировать | Профиль | Сообщение | ICQ | Цитировать | Сообщить модератору

Цитата:
Или тебе код написать?

Код я думаю можно поискать на специализированных сайтах
типа codenet, материалов куча и по сортировкам и по структурам.
ЗЫ: есть прикольная книга - Структуры и алгоритмы обработки данных, в учебе помогает

Всего записей: 671 | Зарегистр. 14-01-2003 | Отправлено: 21:36 12-05-2003
Duke Shadow



Silver Member
Редактировать | Профиль | Сообщение | Цитировать | Сообщить модератору

Цитата:
лушче new, хотя без разницы

Не прокатит. Оператор из С++. Треба - С only.
zam

Цитата:
Да, никаких классов. Онли АНСИ СИ!

А препода переубедить нельзя? Просто геммороя на С намного больше. Если нельзя, то:

Код:
 
/*Описание структуры от Begmart'а*/
/*Читаем одного студента из файла*/
void ReadFromFile(student *s,FILE *from)
{
 char tempStr[1024];/*Если у тебя строки бывают длинее, то правь*/
 fgets(tempStr,1023,from);
 tempStr[strlen(tempStr)-1]=0;
 s->fio=(char*)malloc(strlen(tempStr)+1);
 strcpy(s->fio,tempStr);
 /*И т.д. для всех полей*/
}
 

Не забываем возвращать память системе

Код:
 
void KillStudent(student *s)
{
 free(s->fio);
 /*И все остальные поля*/
}
 

Теперь посчитаем сколько записей в файле

Код:
 
int Count()
{
 int c=0; FILE *file; student dummy;
 file=fopen("students.dat","r");
 /*Проверка открылся или нет, если нет, то return -1;*/
 while(!feof(file))
 {
  ReadFromFile(&dummy,file);
  c++;
  KillStudent(&dummy);
 }
 fclose(file);
 return c;
}
 

Ну и дальше всё вообще тривиально

Код:
 
student *All;
int Number;
int main(int,char*[])
{
 Number=Count();
 if (Number<=0) return -1; /*Либо файл пустой либо не открылся*/
 All=(student*)malloc(sizeof(student)*Number);
 /*Открываем файл как в ф-ции Count*/
 for(int i=0;i<Number;i++)
     ReadFromFile(All[i],file);
 fclose(file);
 ...
 /*Сортировка делается так*/
 qsort(All,Number,sizeof(student),функция_сравнения);
 ...
 for(i=0;i<Number;i++) /*Т.к. БС 3.1, то i уже есть*/
     KillStudent(All[i]);
 free(All);
 return 0;
}
 

Все. Пиши функцию записи в файл (каждый параметр в новой строке), функции сравнения студентов (всё элементарно реализуется через strcmp, даже сравнение оценок), навешивай на всё это междумордие и можно сдаваться.
 
Косяк только один, зато какой - лишнее считывание файла, при подсчёте студентов. При маленьких размерах файла - некритично (если конечно не дисководом дёргать).
 
З.Ы.: Не уверен что в С есть операция -> Так вроде в стандарт вписался.

Всего записей: 3911 | Зарегистр. 15-02-2003 | Отправлено: 15:53 13-05-2003
rew



Full Member
Редактировать | Профиль | Сообщение | ICQ | Цитировать | Сообщить модератору
переделал немного под динамический массив, что б не считывать 2 раза
добавил еще одну структуру studentArray для того что б хранить в ней массив и его длинну в одном месте, можно было обойтись и без этого, но мне так больше нравится хз, вроде работает, правда опять же только для одного поля fio

Код:
 
#include<stdio.h>
#include<conio.h>
#include<string.h>
 
typedef struct{
   char* fio;
   char* address;
   char* phone;
   char* marks;
}student,*pstudent;
 
typedef struct{
pstudent students;
int size;
}studentArray,*pstudentArray;
 
void initStudentArray(pstudentArray sa){
sa->students=NULL;
sa->size=0;
}
void addStudentToArray(pstudentArray sa,pstudent ps){
sa->size++;
sa->students=(pstudent)realloc(sa->students,sizeof(student)*sa->size);
    *(sa->students+sa->size-1)=*ps;
}
void freeStudentArray(pstudentArray sa){
int i;
for(i=0;i<sa->size;i++){
free(sa->students[i].fio);
}
free(sa->students);
initStudentArray(sa);
}
void printStudentArray(studentArray sa){
int i;
for(i=0;i<sa.size;i++){
puts(sa.students[i].fio);
}
}
int ReadFromFile(pstudentArray sa,FILE *from)
{
char tempStr[1024];
pstudent newStudent=(pstudent)malloc(sizeof(student));
if(feof(from)){
return 0;
}
if(fgets(tempStr,1023,from)==NULL){
return 0;
}
if(tempStr[strlen(tempStr)-1]==10){
tempStr[strlen(tempStr)-1]=0;
}
newStudent->fio=(char*)malloc(strlen(tempStr)+1);
strcpy(newStudent->fio,tempStr);
addStudentToArray(sa,newStudent);
return 1;
}
 
int fcmpStudentName(const void *src, const void *dst){
return strcmp(((pstudent)(src))->fio,((pstudent)(dst))->fio);
}
void main(){
FILE *file;
studentArray sa;
initStudentArray(&sa);
file=fopen("students.dat","r");
if(file==NULL){
puts("file not found");
return;
}
while(ReadFromFile(&sa,file));
fclose(file);
qsort(sa.students,sa.size,sizeof(student),&fcmpStudentName);
printStudentArray(sa);
freeStudentArray(&sa);
}  
 
 

Всего записей: 442 | Зарегистр. 09-09-2001 | Отправлено: 23:20 13-05-2003
Duke Shadow



Silver Member
Редактировать | Профиль | Сообщение | Цитировать | Сообщить модератору
rew
Красиво. Чуть больше писанины, зато потом меньше мороки.

Цитата:
правда опять же только для одного поля fio

Расширить нетрудно, было бы желание...
zam
Ну что хватило?

Всего записей: 3911 | Зарегистр. 15-02-2003 | Отправлено: 10:48 14-05-2003
rew



Full Member
Редактировать | Профиль | Сообщение | ICQ | Цитировать | Сообщить модератору
офф
Duke Shadow
tnx правда такой стиль организации, не я придумал очень удобно для обьемных прог, получается почти как работа с классами - поля храняться в структуре и есть набор функций для обслуживания этих структур

Всего записей: 442 | Зарегистр. 09-09-2001 | Отправлено: 14:51 14-05-2003
Duke Shadow



Silver Member
Редактировать | Профиль | Сообщение | Цитировать | Сообщить модератору
Тоже оффтопом пойдет. Забанят, блин.
rew
Ещё есть идеи приближения программирования на С к программированию на С++. Создаёшь структуру, в неё запихиваешь указатели на функции. В итоге получаешь структуру до боли напоминающую класс с методами. Конечно нужно передавать адрес обрабатываемого объекта непосредственно, т.к. this не предусмотрен. Ну и ещё так косячков по мелочи, но если деваться некуда, то уже и такой подход - это уже хорошо.

Всего записей: 3911 | Зарегистр. 15-02-2003 | Отправлено: 17:00 14-05-2003
zam

Junior Member
Редактировать | Профиль | Сообщение | Цитировать | Сообщить модератору
Большое Спасибо за идеи, в структурах я совсем новичек, подскажите, почему вылетает с ошибкой, когда хочу прочитать файл с оценками (+к фамилиям?)? Хочу отсортировать по баллу, вот файл:
Maksim
55
Anton
44
Vova
33
Mihail
22
 
Закомментированный код - это мое видение чтения файла с оценками, но он не работает. Объясните, что я не правильно понял.

Код:
 
#include <stdio.h>
#include <conio.h>
#include <string.h>
#include <stdlib.h>
 
typedef struct{
   char* fio;  
   char* address;
   char* phone;  
   char* marks;  
}student, *pstudent;  
 
typedef struct{  
  pstudent students;  
  int size;
} studentArray, *pstudentArray;  
 
void initStudentArray(pstudentArray sa){  
  sa->students=NULL;
  sa->size=0;  
}
 
void addStudentToArray(pstudentArray sa,pstudent ps){  
  sa->size++;  
  sa->students = (pstudent)realloc(sa->students,sizeof(student)*sa->size);  
  *(sa->students+sa->size-1)=*ps;
}
 
void freeStudentArray(pstudentArray sa){
  int i;
 
  for(i=0;i<sa->size;i++)
    free(sa->students[i].fio);
 
/*  for(i=0;i<sa->size;i++)
    free(sa->students[i].marks);
*/
  free(sa->students);
  initStudentArray(sa);
}
 
void printStudentArray(studentArray sa){
 
  int i;
 
  for(i=0;i<sa.size;i++)
    puts(sa.students[i].fio);
 
}
 
/*void printStudentArrayMarks(studentArray sa){
 
  int i;
 
  for(i=0;i<sa.size;i++)
    puts(sa.students[i].marks);
 
}
*/
int ReadFromFileFio(pstudentArray sa,FILE *from) {
 
  char tempStr[1024];
  int len;
  char *st;
 
  pstudent newStudent;
 
  newStudent = (pstudent)malloc(sizeof(student));
 
  if(feof(from))
    return 0;
 
  st = fgets(tempStr,1023,from);
 
  len = strlen(tempStr);
 
  if(st==NULL)
    return 0;
 
  if(tempStr[len-1]==10)
    tempStr[len-1]=0;
 
  newStudent->fio = (char*)malloc(len+1);
  strcpy(newStudent->fio,tempStr);
 
  addStudentToArray(sa,newStudent);
 
  return 1;
}
 
/*int ReadFromFileMarks(pstudentArray sa,FILE *from) {
 
  char tempStr[1024];
  int len;
  char *st;
 
  pstudent newStudent;
 
  newStudent = (pstudent)malloc(sizeof(student));
 
  if(feof(from))
    return 0;
 
  st = fgets(tempStr,1023,from);
 
  len = strlen(tempStr);
 
  if(st==NULL)
    return 0;
 
  if(tempStr[len-1]==10)
    tempStr[len-1]=0;
 
  newStudent->marks = (char*)malloc(len+1);
  strcpy(newStudent->marks,tempStr);
 
  addStudentToArray(sa,newStudent);
 
  return 1;
}
*/
int fcmpStudentName(const void *src, const void *dst) {
  return strcmp( ((pstudent)(src))->fio,((pstudent)(dst))->fio);
}
 
/*int fcmpStudentMarks(const void *src, const void *dst) {
  return strcmp( ((pstudent)(src))->marks,((pstudent)(dst))->marks);
}
*/
int main(void)
{
  FILE *file;
  char ch;
  int d=1;
 
  studentArray sa;
  clrscr();
  printf("0. Прочитать файл\n1. Сортировка по фамилии\n2. Сортировка по среднему баллу\nДля выхода нажмите ESC\n\n\n");
 
  initStudentArray(&sa);
 
  file = fopen("students.dat","r");
 
  if(file==NULL)
  {
    printf("Файл не найден\n");
    getch();
    return 1;
  }
 
  while(d) {
    d = ReadFromFileFio(&sa,file);
/*    d = ReadFromFileMarks(&sa,file);*/
  }
 
 
  fclose(file);
  do {
    ch = getch();
    switch(ch) {
      case '0':
        clrscr();
        printStudentArray(sa);
        printf("\n\n0. Прочитать файл\n1. Сортировка по фамилии\n2. Сортировка по среднему баллу\nДля выхода нажмите ESC\n\n\n");
        break;
      case '1':
        clrscr();
        qsort(sa.students,sa.size,sizeof(student),&fcmpStudentName);
        printStudentArray(sa);
        printf("\n\n0. Прочитать файл\n1. Сортировка по фамилии\n2. Сортировка по среднему баллу\nДля выхода нажмите ESC\n\n\n");
        break;
      case '2':
//      qsort(sa.students,sa.size,sizeof(student),&fcmpStudentMarks);
        break;
      case 'q':
        exit(1);
    }
 
  } while (ch!=0x1b);
 
/*  printStudentArrayMarks(sa);*/
 
  freeStudentArray(&sa);
  return 0;
}
 
 

 
 
Добавлено
И как мне в контексте использования вашей структуры загнать строку оценок:
454545454445 и посчитать ее средний бал и использовать этот средний бал в привязке в вышеобозначенному студенту?

Всего записей: 185 | Зарегистр. 19-01-2003 | Отправлено: 01:26 15-05-2003 | Исправлено: zam, 03:08 15-05-2003
rew



Full Member
Редактировать | Профиль | Сообщение | ICQ | Цитировать | Сообщить модератору

Код:
/*считывать последовательные данные с одного файла нужно также последовательно*/
int ReadFromFile(pstudentArray sa,FILE *from) {  
  char tempStr[1024];  
  int len;  
  char *st;  
  pstudent newStudent;  
   if(feof(from))        
      return 0;  
   newStudent = (pstudent)malloc(sizeof(student));  
// read fio
  st = fgets(tempStr,1023,from);  
 
  len = strlen(tempStr);  
 
  if(st==NULL)  
    return 0;  
 
  if(tempStr[len-1]=='\r')  
    tempStr[len-1]='\0';  
 
  newStudent->fio = (char*)malloc(len+1);  
  strcpy(newStudent->fio,tempStr);  
//end read fio
//read maks  
  st = fgets(tempStr,1023,from);  
  len = strlen(tempStr);  
  if(st==NULL)  
    return 0;  
  if(tempStr[len-1]=='\r')  
    tempStr[len-1]='\0';  
  newStudent->fio = (char*)malloc(len+1);  
  strcpy(newStudent->marks,tempStr);  
// end read marks
//нужно вынести чтение fio и marks в отдельную функцию, тк одно и тоже, но сча лень
  addStudentToArray(sa,newStudent);  
  return 1;  
}  
 

также лучше будет

Код:
 
void freeStudentArray(pstudentArray sa){  
   int i;  
   for(i=0;i<sa->size;i++) {
      free(sa->students[i].fio);  
      free(sa->students[i].marks);  
   }
   free(sa->students);  
   initStudentArray(sa);  
}  
 
void printStudentArray(studentArray sa){    
  int i;    
  for(i=0;i<sa.size;i++){
    printf("fio=%s,marks=%s\n",sa.students[i].fio,sa.students[i].marks);  
  }
}  
 
 

 
Добавлено
а проблема была в том что в массив по четным заносилась сначала структура с fio, по нечетным marks

Всего записей: 442 | Зарегистр. 09-09-2001 | Отправлено: 03:16 15-05-2003 | Исправлено: rew, 03:17 15-05-2003
zam

Junior Member
Редактировать | Профиль | Сообщение | Цитировать | Сообщить модератору
ПОНЯТНО. Почему вылетает (или наложение на другую запись - другого студента при этой функции добавления?

Код:
 
void IncStudentByUser(pstudentArray sa) {
 
char tempStr[1024], tStr[1024];
int len;
pstudent newStudent;
newStudent = (pstudent)malloc(sizeof(student));
 
printf("FIO : ");
scanf("%s", &tempStr);
len = strlen(tempStr);
 
tempStr[len] = '\0';
 
newStudent->fio = (char*)malloc(len+1);
strcpy(newStudent->fio,tempStr);
 
printf("Marks : ");
scanf("%s", &tStr);
len = strlen(tStr);
 
tStr[len] = '\n';
 
newStudent->marks = (char*)malloc(len+1);
strcpy(newStudent->marks,tStr);
 
addStudentToArray(sa,newStudent);
}

 
Добавлено
Еще один вопрос, как из этой структуры редактировать определенного студента.
 
Например на экране
 
1. ФИО1 54
2. ФИО2 45
3. ФИО3 445
 
как должна выглядеть функция? непонятно...

Всего записей: 185 | Зарегистр. 19-01-2003 | Отправлено: 22:24 15-05-2003
rew



Full Member
Редактировать | Профиль | Сообщение | ICQ | Цитировать | Сообщить модератору

Цитата:
как из этой структуры редактировать определенного студента

если у тебя указатель на структуру pstudentArray то sa->students[i].fio, а если сама структура studentArray то sa.students[i].fio

Всего записей: 442 | Зарегистр. 09-09-2001 | Отправлено: 23:29 15-05-2003
zam

Junior Member
Редактировать | Профиль | Сообщение | Цитировать | Сообщить модератору
rew
Что в твоей проге происходит тут:
sa->students = (pstudent)realloc(sa->students,sizeof(student)*sa->size);
 
и тут:
*(sa->students+sa->size-1)=*ps;
?
 

Всего записей: 185 | Зарегистр. 19-01-2003 | Отправлено: 23:55 15-05-2003
Открыть новую тему     Написать ответ в эту тему

Страницы: 1 2 3

Компьютерный форум Ru.Board » Компьютеры » Прикладное программирование » Какую структуру данных для данной задачи на СИ рекомендуете?


Реклама на форуме Ru.Board.

Powered by Ikonboard "v2.1.7b" © 2000 Ikonboard.com
Modified by Ru.B0ard
© Ru.B0ard 2000-2024

BitCoin: 1NGG1chHtUvrtEqjeerQCKDMUi6S6CG4iC

Рейтинг.ru