2014 dxdy logo

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

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




Начать новую тему Ответить на тему На страницу 1, 2  След.
 
 Продолжение темы с записной книжкой. Си.
Сообщение22.11.2013, 19:17 


20/10/12
235
Добрый вечер, уважаемые участники форума! И это снова я, и у меня снова вопросы.
Часть программы, ответственная за ввод почти готова:
код: [ скачать ] [ спрятать ]
Используется синтаксис C++
/*Записная книга*/
#include <stdio.h>
#include <ctype.h>
#include <string.h>
#define MAXSIZE 100000
#define BUFF 400
#define MINIBUFF 10

int modecorrect(char *str); /*проверка управляющей строки */
int getdata(unsigned char *field, FILE *file); /*запись данных в файл */

struct person{ /*структура записи */
 unsigned char *name;
 unsigned char *surname;
 unsigned char *number;
};

int main(void)
{
FILE *MyBook;

struct person NewData;
unsigned char *out = malloc(10*BUFF * sizeof(unsigned char)); /* */
/*Указатели на поля*/
unsigned char *pname = &NewData.name;
unsigned char *psurname = &NewData.surname;
unsigned char *pnumber = &NewData.number;

unsigned char *mode = malloc(MINIBUFF * sizeof(unsigned char)); /* */
printf("MyBook 1.0\nEnglish language is used(!) \nChoose your mode:"); /*Выбор режима */
printf("\nInput \"Read\" or \"Add\"\n");
gets(mode);

if(!strcmp(mode,"Add"))
{

   if((MyBook = fopen("MyBook.txt", "a+")) == NULL)//
   printf("Writing MyBook.txt error");
   printf("Please, input new data\nto stop press <Enter>\n");
   while(1){
     printf("Name: ");
     getdata(pname, MyBook);

     if(!strcmp(pname, ""))
        break; /*Вот здесь может таиться основная ошибка!*/
     fprintf(MyBook, " ");
     printf("Surname: ");
     getdata(psurname, MyBook);

     fprintf(MyBook, " ");
     printf("Number: ");
     getdata(pnumber, MyBook);

     fprintf(MyBook, "\n");
}
fclose(MyBook);
}

if(!strcmp(mode,"Read"))
{
  if((MyBook = fopen("MyBook.txt", "r")) == NULL)
  printf("Reading MyBook.txt error");
  do{
    puts(fgets(out, MAXSIZE, MyBook));
  }while(!feof(MyBook));
  fclose(MyBook);
}
return 0;
}

int modecorrect(char *str) // Проверка управляющей строки
{
  if(!strcmp(str, "Add") || !strcmp(str, "Read"))
    return 1;
  return 0;
}

int getdata(unsigned char *field, FILE *file)
{
   gets(field);
   fputs(field, file);
   return;
}
 

Запись идет, но при использовании есть ошибки. Одна понятно где - я прошу программу уйти из ввода, как только было введено пустое имя пользователя. И там что-то не так с указателями на оставшиеся поля. Вторая ошибка - при выводе, он вообще не работает(с вводом тоже очень нужна помощь и конкретная). (Мне надо вывести данные из файла). Пожалуйста, потратьте немного времени и наставьте мою программу на путь истинный(как проще, как логичнее, красивее, правильнее).
Кроме того, есть вторая, не менее важная часть программы - нужно отсортирововать данные по одному из полей - и тоже вывести это дело из файла в консоль.

 Профиль  
                  
 
 Re: Продолжение темы с записной книжкой. Си.
Сообщение22.11.2013, 19:26 
Заслуженный участник


27/04/09
28128

(Оффтоп)

Извините, но зачем каждый раз открывать новую тему? Это уже третья часть о записной книжке — почему хотя бы не дописать её в тему со второй частью?

 Профиль  
                  
 
 Re: Продолжение темы с записной книжкой. Си.
Сообщение22.11.2013, 19:38 


20/10/12
235
arseniiv, прошу прощения, а её еще не посчитали закрытой? просто я не знаю, какие здесь порядки

 Профиль  
                  
 
 Re: Продолжение темы с записной книжкой. Си.
Сообщение22.11.2013, 19:45 
Заслуженный участник


27/04/09
28128
Темы здесь не закрываются. :-)

При копировании кода у вас в нём были отступы, или это форум «откорректировал»?

 Профиль  
                  
 
 Re: Продолжение темы с записной книжкой. Си.
Сообщение22.11.2013, 19:56 


20/10/12
235
Вообще говоря, были. Я уже отредактировал частично.

 Профиль  
                  
 
 Re: Продолжение темы с записной книжкой. Си.
Сообщение22.11.2013, 21:26 
Заслуженный участник


09/09/10
3729
Цитата:
unsigned char *pname = &NewData.name;
unsigned char *psurname = &NewData.surname;
unsigned char *pnumber = &NewData.number;

А что здесь происходит?

 Профиль  
                  
 
 Re: Продолжение темы с записной книжкой. Си.
Сообщение22.11.2013, 21:40 


20/10/12
235
Joker_vD, задумывалось как указатели на поля структурной переменной New Data

 Профиль  
                  
 
 Re: Продолжение темы с записной книжкой. Си.
Сообщение22.11.2013, 21:56 
Заслуженный участник


09/09/10
3729
Но ведь указатель на поле типа "указатель на unsigned char" имеет тип unsigned char **, разве нет?

 Профиль  
                  
 
 Re: Продолжение темы с записной книжкой. Си.
Сообщение22.11.2013, 22:05 


20/10/12
235
Joker_vD, согласен, но почему-то работает и так :?:

-- 22.11.2013, 22:18 --

Самая последняя версия, что я написал(что бы вам меня не ругать, там, где я исправился):
код: [ скачать ] [ спрятать ]
Используется синтаксис C++
#include <stdio.h>
#include <ctype.h>
#include <string.h>
#define SIZE 100
#define BUFF 10000
#define MODBUFFER 10
/*Размер вывода, пока набирается 4000, но страховка*/
/*Размер 100 x (10 + 10 + 20 ) = 4000*/

/*Записная книга*/
/*Прототипы*/
int modecorrect(char *str); /*Проверка упр. строки*/
int getdata(unsigned char *field, FILE *file); /*Получение данных формы*/

struct person{ /*Структура записи*/
unsigned char name[10];
unsigned char surname[10];
unsigned char number[20];
};

int main(void)
{
FILE *MyBook;
struct person NewData;
struct person Contacts[SIZE];
unsigned char *out = malloc(BUFF * sizeof(unsigned char));
/*указатель в файле при выводе и сортировке*/
unsigned char *pname = &NewData.name;
unsigned char *psurname = &NewData.surname;
unsigned char *pnumber = &NewData.number;

unsigned char *mode = malloc(MODBUFFER * sizeof(unsigned char)); /* */

printf("MyBook 1.0\nEnglish language is used(!) \nChoose your mode:"); /* */
printf("\nInput \"Read\" or \"Add\"\n");
gets(mode);

if(!strcmp(mode,"Add"))
{
if((MyBook = fopen("MyBook.txt", "a+")) == NULL)//
printf("Writing MyBook.txt error");

printf("Please, input new data\nto stop press <Enter>\n");
while(1){//////////////////
printf("Name: ");
 getdata(pname, MyBook);
fprintf(MyBook, " ");

if(!strcmp(pname, ""))
 break;

printf("Surname: ");
 getdata(psurname, MyBook);
fprintf(MyBook, " ");

printf("Number: ");
 getdata(pnumber, MyBook);
fprintf(MyBook, "\n");

}//////////////////////////
fclose(MyBook);
}

if(!strcmp(mode,"Read"))
{
if((MyBook = fopen("MyBook.txt", "r")) == NULL)
printf("Reading MyBook.txt error");
do{
fscanf(MyBook, "%c" , out);
putchar(*out);
}while(!feof(MyBook));

fclose(MyBook);
}
return 0;
}

int modecorrect(char *str) //
{
if(!strcmp(str, "Add") || !strcmp(str, "Read"))
 return 1;
return 0;
}

int getdata(unsigned char *field, FILE *file)
{
gets(field);
fputs(field, file);
return;
}

Сейчас самое актуальное - написать еще сортировку для введенных данных по полям
qsort у меня имеется свой написанный, но вот с синтаксисом также пока не ясно

 Профиль  
                  
 
 Re: Продолжение темы с записной книжкой. Си.
Сообщение22.11.2013, 22:26 
Заслуженный участник


09/09/10
3729
Работает? В смысле "компилируется"? Ну, для Си это означает очень мало, на самом-то деле.

Однако работать как задумано оно не может в принципе: ваши gets портят стек.

Давайте разберемся, что вообще делает ваша программа: она создает локальную переменную NewData — в ней лежат четыре указателя (которые вы не инициализируете). Потом она берет указатели на куски переменной NewDatapname и т.д. Дальше вы выделяете 100-байтовый буфер и помещаете указатель на него в out. Вводите с клавиатуры строчку в этот буфер. Далее, если введено "Add", то вы пытаетесь открыть на запись файл "MyBook.txt" — если не выходит, вы об этом пишете в консоль, но продолжаете работу. Работа эта такая: печатаем "Name: " на экран, и вводим с клавиатуры строку в буфер, на который указывает pname. Вот только pname указывает ни на какой не на буфер, а внутрь структуры NewData. Куда вы и пишете введенную строку. Кстати, вся NewData имеет размер 12 байт (24 байта на x64), так что достаточно длинная строка будет затирать содержимое переменных pname, psurname, pnumber и mode, адрес возврата из main... что-то мне прямо захотелось написать эксплойт для вашей программы.

-- Пт ноя 22, 2013 23:27:29 --

О, у вас уже другой код. Сейчас гляну.

-- Пт ноя 22, 2013 23:45:59 --

Ну, программа как-то работает — по Add добавляет строки в файл, по Read читает их из файла.

 Профиль  
                  
 
 Re: Продолжение темы с записной книжкой. Си.
Сообщение23.11.2013, 00:19 


20/10/12
235
И это снова я, на этот раз данные, записанные в файл нужно отсортировать по одному из полей структуры, например, по имени. Для этого нужен массив структур такого типа?
Используется синтаксис C++
struct person Contacts[SIZE];
 

А вот дальше - сложный момент - нужно из файла считать информацию и заполнить этот массивчик. Лично моя программа в текстовом файле пишет что-то похожее на
Код:
...
Abraham Louis 89005663423
Antony Griffits 88055664545
Daniel James 87056777712
Howard Richards 89212112131
Arnold Karol 89914551471
...

name, surname и number разделены пробелами
после каждой записи - символ конца строки (и так понятно).
Вот для этого я уже придумать ничего не могу. Пока у меня полная ерунда, подскажите, как надо?
q указывает на символ файла(пока первый) (Как это организовать?)
Используется синтаксис C++
void fill_struct(unsigned char *q, struct person BigArray[], FILE* file)
{
/*
  do{
    while(!(*q!=' ' && *(q+1)==' ')) //Закончилось имя
    {
          fgets(/*Честно говоря я не понимаю, как обратиться к полю элемента массива структур здесь , MODBUFFER, file);
    }
*/

  }while(!feof(file));

}

 Профиль  
                  
 
 Re: Продолжение темы с записной книжкой. Си.
Сообщение23.11.2013, 02:03 
Заслуженный участник


09/09/10
3729
Какого все-таки страшного Слонопотама вы рисуете.
Код:
size_t fillStruct(FILE *file, struct person bigArray[], size_t arraySize) {
    size_t index = 0;
    while((index < arraySize) && !feof(file)) {
        if (fscanf(file, " %9s %9s %19s \n", bigArray[index].name, bigArray[index].surname, bigArray[index].number) == 3) {
            ++index;
        }
    }
    return index;
}


Используется это примерно так:
Код:
if(!strcmp(mode,"Read"))
{
    size_t i, count;
    if((MyBook = fopen("MyBook.txt", "r")) == NULL) {
        printf("Reading MyBook.txt error");
    }
    else {
        count = fillStruct(MyBook, Contacts, SIZE);
        printf("%d\n", count);
        for (i = 0; i < count; ++i) {
            printf("%s %s %s\n", Contacts[i].name, Contacts[i].surname, Contacts[i].number);
        }
        fclose(MyBook);
    }
}


И да, уберите вы в
Код:
unsigned char *pname = &NewData.name;
unsigned char *psurname = &NewData.surname;
unsigned char *pnumber = &NewData.number;

амперсанды. Неужели компилятор не выводит предупреждение, что там типы разнятся?

 Профиль  
                  
 
 Re: Продолжение темы с записной книжкой. Си.
Сообщение23.11.2013, 16:39 


20/10/12
235
А откуда 3 в строке
Код:
if (fscanf(file, " %9s %9s %19s \n", bigArray[index].name, bigArray[index].surname, bigArray[index].number) == 3) {
?

 Профиль  
                  
 
 Re: Продолжение темы с записной книжкой. Си.
Сообщение23.11.2013, 18:06 
Заслуженный участник


09/09/10
3729
shukshin
А все остальное понятно? :-) Это проверка на то, что строка соответствует формату — fscanf возвращает число успешно заполненных аргументов. Их здесь три.

 Профиль  
                  
 
 Re: Продолжение темы с записной книжкой. Си.
Сообщение23.11.2013, 18:38 


20/10/12
235
Joker_vD, замечаю за собой тенденцию тупить в самых очевидных вещах.
Ну вот еще не понимаю откуда define size_t берется?
Код:
" %9s %9s %19s \n"
вот со спецификаторами здесь тоже можно было бы уточнить, честно говоря, никогда этим не пользовался...

 Профиль  
                  
Показать сообщения за:  Поле сортировки  
Начать новую тему Ответить на тему  [ Сообщений: 22 ]  На страницу 1, 2  След.

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



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

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


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

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