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

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

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

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

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

rew



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

Цитата:
Что в твоей проге происходит тут:  
sa->students = (pstudent)realloc(sa->students,sizeof(student)*sa->size);  

realloc? изменяю, в данном случае увеличиваю размер массива (sa->students) на 1 элемент

Цитата:
и тут:  
*(sa->students+sa->size-1)=*ps;  

sa->students адрес начала массива
sa->size его размер
-1 потому что нужен индекс последнего элемента
получется адрес начала массива+индекс последнего элемента-> адрес последнего элемента, туда заносится адрес нового элемента.
незнаю как лучше обьяснить

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

Junior Member
Редактировать | Профиль | Сообщение | Цитировать | Сообщить модератору
Т.е. заносим последний элемент? Как по твоему - в чем ошибка в моей функции добавления студента:
 

Код:
 
#define ALEN 128
...
typedef struct
{
pstudent students;
int size;
} studentArray, *pstudentArray;
...
void IncStudentByUser(pstudentArray sa)
{
char *tempStr;
int len;
pstudent newStudent;
newStudent = (pstudent)malloc(sizeof(student));
 
tempStr = (char*)malloc(ALEN*sizeof(char));
memset(tempStr, 0, ALEN*sizeof(tempStr[0]));
 
tempStr[0]='V;
tempStr[1]='a';
tempStr[2]='V';
tempStr[3]='a';
tempStr[4]='Z;
 
len = strlen(tempStr);
 
tempStr[len] = '\0';
 
newStudent->fio = (char*)malloc(len);
strcpy(newStudent->fio,tempStr);
 
memset(tempStr, 0, ALEN*sizeof(tempStr[0]));
 
tempStr[0]='5';
tempStr[1]='4';
tempStr[2]='6';
 
len = strlen(tempStr);
 
tempStr[len] = '\n';
 
newStudent->marks = (char*)malloc(len);
strcpy(newStudent->marks,tempStr);
 
addStudentToArray(sa,newStudent);
free(tempStr);
}
...
studentArray sa;
...
IncStudentByUser(&sa);
 

 
буква совершенно рандомная вылазит в другое поле и встает перед другой фамилией.

Всего записей: 185 | Зарегистр. 19-01-2003 | Отправлено: 04:33 16-05-2003 | Исправлено: zam, 04:36 16-05-2003
Duke Shadow



Silver Member
Редактировать | Профиль | Сообщение | Цитировать | Сообщить модератору
zam
newStudent->fio = (char*)malloc(len);
Эт, ну дык, надо писать len+1, а то нулевой символ не влезет. Скорее всего в этом и косяк.
tempStr[len] = '\0';
Абсолютно лишнее. Ты ведь перед этим написал memset(tempStr, 0, ALEN*sizeof(tempStr[0])); Так что там по любому должен быть ноль. Да и как-то интересно получается - сперва определяем длину, а потом строку ограничиваем Может ты хотел, как и в случае с оценками приписать '\n'?
Ну и в случае с оценками правь также.
 
З.Ы.: Имхо, добавлять '\n' в конец строки - лишнее. Если тебе нужно для вывода на экран, то при выводе и добавляй, а так - от лукавого.

Всего записей: 3921 | Зарегистр. 15-02-2003 | Отправлено: 07:32 16-05-2003
zam

Junior Member
Редактировать | Профиль | Сообщение | Цитировать | Сообщить модератору
Duke Shadow
И впрямь косяк с этим был. А могу я обращаться к студенту по полю marks, т.е.
sa.students.marks[i]?
 
А как мне избежать (по-простому, т.к. по-сложному знаю как):
 
printf("FIO # ");
scanf("%s", tempStr);
printf("Marks # ");
scanf("%s", tempStr);
 
Ввожу в FIO два слова, одно запоминается как fio, другое как marks. Как мне все до нажатия Enter интерпретировать как ФИО.

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



Full Member
Редактировать | Профиль | Сообщение | ICQ | Цитировать | Сообщить модератору
sa.students[studentIndex].marks[markIndex]
 
Добавлено

Цитата:
Ввожу в FIO два слова, одно запоминается как fio, другое как marks. Как мне все до нажатия Enter интерпретировать как ФИО.  

непонял

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

Junior Member
Редактировать | Профиль | Сообщение | Цитировать | Сообщить модератору
rew
с этим покончил
 
Есть два вопроса:
1. Как получить доступ к каждому ЭЛЕМЕНТУ поля marks? Чтобы посчитать средний бал к примеру. Доп.структуру создавать?
 
В своей функции редактирования студента, при попытке получить fgets() ФИО, перескакиваю сразу на получение оценков (и в отладчике MS VC6.0++) не понимаю почему, вот моя функция редактирования студента.
 

Код:
 
#define ALEN 128
...
void EditStudentByUser(pstudentArray sa)
{
char *tempStr;
int len, j;
 
printf("Enter number of student for editing# ");
scanf("%d",&j);
 
//newStudent = (pstudent)malloc(sizeof(student));
 
tempStr = (char*)malloc(ALEN*sizeof(char));
 
if(tempStr==NULL)
exit(1);
 
memset(tempStr, 0, ALEN*sizeof(tempStr[0]));
 
printf("FIO?# ");
//scanf("%s", tempStr);
fgets(tempStr, ALEN, stdin);
 
len = strlen(tempStr);
tempStr[len-1] = '\0';
 
strcpy(sa->students[j].fio, tempStr);
 
memset(tempStr, 0, ALEN*sizeof(tempStr[0]));
printf("Marks# ");
//scanf("%s", tempStr);
fgets(tempStr, ALEN, stdin);
 
len = strlen(tempStr);
tempStr[len-1] = '\0';
 
strcpy(sa->students[j].marks,tempStr);
free(tempStr);
}
...
EditStudentByUser(&sa);
...
 

 
Уже с ума схожу почему пропускаем ввод ФИО.

Всего записей: 185 | Зарегистр. 19-01-2003 | Отправлено: 14:22 16-05-2003 | Исправлено: zam, 02:38 17-05-2003
rew



Full Member
Редактировать | Профиль | Сообщение | ICQ | Цитировать | Сообщить модератору
те вводиш номер студента и перескакивает сразу на фио? тогда вызывай flushall() перед каждым вводом с клавы, для очистки буфера клавы. тк после scanf("%d",&j); в буфере остается '\n'

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

Junior Member
Редактировать | Профиль | Сообщение | Цитировать | Сообщить модератору
rew
Спасибо, проблема была именно в этом. Осталось одно:  
 
Как получить доступ к каждому ЭЛЕМЕНТУ поля marks? Чтобы посчитать средний бал к примеру. Доп.структуру создавать?  
 
Подскажите плиз по этому поводу.  
 
 
 
Добавлено
т.е. имея запись 5444 нужно сложить 5+4+4+4 т.е. получить доступ к каждому элементу этого поля известной структуры

Всего записей: 185 | Зарегистр. 19-01-2003 | Отправлено: 05:06 17-05-2003
Begmart



Junior Member
Редактировать | Профиль | Сообщение | Цитировать | Сообщить модератору
zam
(marks[0] + marks[1] + marks[2] + marks[n-1]) / n. Знать бы n.
Почему так? Потому что когда ты объявляешь массив как "char marks[5]" си делает константный указатель marks, который указывает на нулевой элемент массива, а так же он (си) резервирует 5 байт для этого массива. Когда же ты объявляешь указатель "char* marks" и сам резервируешь 5 байт, то получается фактически таже самая структура, только указатель не константный и размер памяти ты можешь изменить. А фраза "marks[4]" независимо от способа объявления "marks" приводится к виду "*(marks + 4)" что будет верно при любом способе объявления "marks", т.к. "marks" и там и там является указателем (Если не ясно, что такое "*(marks + 4)", то это доступ к элементу, смещённому от "marks" на 4 элемента такого же размера, как и "marks". В твоём случае - на 4 байта, т.к. marks имеет тип char).

Всего записей: 99 | Зарегистр. 05-04-2003 | Отправлено: 07:40 17-05-2003
zam

Junior Member
Редактировать | Профиль | Сообщение | Цитировать | Сообщить модератору
Begmart
Точно!  
 
int i, float average_m=0;
 
  for(i=0; i<len-1;i++)
    average_m += *(tempStr+i) - '0';
 
  average_m /= i;
 
Всем Спасибо Большое. Я решил все возникающие по ходу задачи проблемы, с вашей помощью конечно. Теперь я имею представление о структурах, плотно поработал в отладчике MS VC, по назначению воспользовался sprintf() Ура!!! Спасибо. Если что - я спрошу.

Всего записей: 185 | Зарегистр. 19-01-2003 | Отправлено: 12:04 17-05-2003 | Исправлено: zam, 13:34 17-05-2003
Duke Shadow



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

Цитата:
Все таки нужно приводить к char, т.к. использую сортировку по среднему баллу

Стоп! Если тебе нужна сортировка по среднему баллу, то... ДЕЛАЙ сортировку ПО СРЕДНЕМУ БАЛЛУ. Добавляй в структуру ещё одно поле "средний" балл, хранить его в файле не обязательно. После считывания всех структур из файла пробегаем по массиву и расчитываем средний балл для всех элементов. После чего пишем правильную функцию сравнения, qsort. А тот вариант, который у тебя просто берёт и сравнивает оценки по порядку.

Цитата:
Теперь я имею представление о структурах, плотно поработал в отладчике MS VC. Ура!!! Спасибо.

Пожалуйста. Мы старались Только в начале, кажися, Борланд Си фигурировал

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

Junior Member
Редактировать | Профиль | Сообщение | Цитировать | Сообщить модератору
Duke Shadow
Я в файле не храню средний бал, считываю все оценки:  
 

Код:
 
//################ begin marks ################
memset(tempStr, 0, ALEN*sizeof(tempStr[0]));
st = fgets(tempStr, len, from);
if (st==NULL)
return 1;
 
len = strlen(tempStr);
tempStr[len-1] = '\0';
 
for(i=0; i<len-1;i++)
average_m += *(tempStr+i) - '0';
 
average_m /= i;
 
memset(tempStr, 0, len);
sprintf(tempStr, "%f", average_m);
 
newStudent->marks = (char*)malloc(len);
strcpy(newStudent->marks,tempStr);
//################ end marks ################
 

 
т.е. в поле marks я записываю уже средний бал, посчитанный заранее.
 
Возникла трудность с функцией удаления студента из базы данных. Как она (на ваш взгляд) должна выглядеть, чтобы корректно удалить студента из базы данных.  
 
 
 
 
Добавлено
а отладчик MS VC очень удобный. Вот.

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



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

Цитата:
Возникла трудность с функцией удаления студента из базы данных. Как она (на ваш взгляд) должна выглядеть, чтобы корректно удалить студента из базы данных

самое простое считать с файла все данные в массив, удалить из массива и записать обратно в файл весь массив

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

Junior Member
Редактировать | Профиль | Сообщение | Цитировать | Сообщить модератору
rew
Нет, я имел в виду удаление с экрана произвольного студента с порядковым номером j --- sa->students[j], без удаления из файла, примерно то же, что делает ф-ия добавления у тебя, только не добавления, а удаления.
 
 
Добавлено
Какая у меня ошибка?
 

Код:
 
void delStudentFromArray(pstudentArray sa, pstudent ps, int i)
{
free(sa->students[i].fio);
free(sa->students[i].address);
free(sa->students[i].phone);
free(sa->students[i].marks);
 
sa->size--;
 
sa->students = (pstudent)realloc(sa->students, sizeof(student)*sa->size);
*(sa->students+sa->size-1) = *ps;
}
 
int DelStudentByUser(pstudentArray sa)
{
 
  int i;
  pstudent ps;
 
  printf("NUMBERof student for deleting# ");
  scanf("%d", &i);
  flushall();
 
  delStudentFromArray(sa, ps+1, i);
  return 0;
}
...
DelStudentByUser(&sa);
 

 

Всего записей: 185 | Зарегистр. 19-01-2003 | Отправлено: 16:07 17-05-2003 | Исправлено: zam, 16:38 17-05-2003
Begmart



Junior Member
Редактировать | Профиль | Сообщение | Цитировать | Сообщить модератору
zam
Удаление записи из текстового файла производится простой перезаписью всей базы без удалённо записи. Т.е. тебе надо прочесть всю базу в память. Удалить нужного студента и сохранить полученную базу. Как удалить студента. Если у тебя массив ссылок - для начала освободить память под строчки, потом обнулить ссылку - структура уничтожится, потом сместить все последующие ссылки (после обнулённой) на 1 влево (вверх, ближе к началу массива - как больше нравится), наконец уменьшить счётчик записей, ещё хорошо бы уменьшить размер самого массива на 1 Если у тебя массив структур, то будет геморрой со смещением, но ведь у тебя ссылки, правда?

Всего записей: 99 | Зарегистр. 05-04-2003 | Отправлено: 19:45 17-05-2003
rew



Full Member
Редактировать | Профиль | Сообщение | ICQ | Цитировать | Сообщить модератору
мож есть какие глюки/баги, но удаление должно быть примерно такое

Код:
 
#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;
}
pstudent removeStudent(pstudentArray sa,int index){
int i;
student removedStudent;
if(index>=0&&index<sa->size){
removedStudent=sa->students[index];
for(i=index;i<sa->size-1;i++){
sa->students[i]=sa->students[i+1];
}
sa->size--;
sa->students=(pstudent)realloc(sa->students,sizeof(student)*sa->size);
return &removedStudent;
}
return NULL;
}
void freeStudent(pstudent std){
if(std!=NULL){
free(std->fio);
free(std->marks);
}
}
void freeStudentArray(pstudentArray sa){
int i;
for(i=0;i<sa->size;i++){
freeStudent(&sa->students[i]);
}
free(sa->students);
initStudentArray(sa);
}
void printStudentArray(studentArray sa){
int i;
for(i=0;i<sa.size;i++){
printf("%s:%s\n",sa.students[i].fio,sa.students[i].marks);
}
}
int readLine(char** dst,FILE* file){
char line[1024];
int len;
if(feof(file)||fgets(line,1024,file)==NULL){
return 0;
}
len=strlen(line);
if(line[len-1]=='\r'||line[len-1]=='\n'){
line[len-1]='\0';
}
*dst=(char*)malloc(len+1);
strcpy(*dst,line);
return 1;
}
int ReadFromFile(pstudentArray sa,FILE *from) {
pstudent newStudent;
newStudent = (pstudent)malloc(sizeof(student));
if(readLine(&newStudent->fio,from)==0){
free(newStudent);
return 0;
}
if(readLine(&newStudent->marks,from)==0){
free(newStudent);
return 0;
}
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;
pstudent ds;
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);
ds=removeStudent(&sa,0);
freeStudent(ds);
        puts("------------------------");
printStudentArray(sa);
freeStudentArray(&sa);
        getch();
}  
 

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

Junior Member
Редактировать | Профиль | Сообщение | Цитировать | Сообщить модератору
На теории все просто, с кодом rew вылетает с закрытием приложения, показывая при этом содержимое регистра CS и еще чего-то. Ничего не понимаю.
 

Код:
 
 
void freeStudentArray(pstudentArray sa){
  int i;
 
  for(i=0;i<sa->size;i++) {
    free(sa->students[i].fio);
    free(sa->students[i].address);
    free(sa->students[i].phone);
    free(sa->students[i].marks);
  }
 
  free(sa->students);
  initStudentArray(sa);
}
...
int removeStudent(pstudentArray sa)
{
 
  int i, j;
  student removedStudent;  
 
  printf("NUMBER# ");
  flushall();
  scanf("%d", &j);
 
  if(j>=0 && j<sa->size)
  {
    removedStudent = sa->students[j];
 
    for(i=j;i<sa->size-1;i++)
    sa->students[i] = sa->students[i+1];
 
    sa->size--;  
     
    sa->students = (pstudent)realloc(sa->students,sizeof(student)*sa->size);
    return &removedStudent;  
  }  
 
  return 0;  
}
...
int main(void)  
{
...
pstudent ds;
...
case '6':
        ds = removeStudent(&sa);
 
        if(ds)
          freeStudentArray(ds);
        else
          exit(1);  
...
}
 


Всего записей: 185 | Зарегистр. 19-01-2003 | Отправлено: 00:44 18-05-2003 | Исправлено: zam, 00:45 18-05-2003
rew



Full Member
Редактировать | Профиль | Сообщение | ICQ | Цитировать | Сообщить модератору
int removeStudent(pstudentArray sa)  
{  
...  
return &removedStudent;// тут возвращается совсем не инт
...
return 0;  
}  

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

Junior Member
Редактировать | Профиль | Сообщение | Цитировать | Сообщить модератору
Я очепятался, конечно не int, а указатель.

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



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

Код:
sa->students = (pstudent)realloc(sa->students,sizeof(student)*sa->size);

sa есть массив pstudent, а не student. Короче говоря:

Код:
sa->students = (pstudent)realloc(sa->students,sizeof(pstudent)*sa->size);

Ща тоже код наваяю. Присоединюсь, так сказать, к вашей пьянке
 
Добавлено
Стоп. Гоню. Го всё равно код наваяю .
 
Добавлено
rew
ты возвращаешь из функции ссылку на локальную переменную. При том, что при выходе из функции все локальные переменные уничтожаются. Или это бред или одно из двух...

Всего записей: 99 | Зарегистр. 05-04-2003 | Отправлено: 10:07 18-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-2025

BitCoin: 1NGG1chHtUvrtEqjeerQCKDMUi6S6CG4iC

Рейтинг.ru