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, Супермодераторы



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

Сейчас этот форум просматривают: Bing [bot]


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

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