Бронирование адреса и запись в файл - PullRequest
0 голосов
/ 09 декабря 2011
#include <stdio.h>

#define TRUE 1
#define FALSE 0

typedef struct contact {    
char firstname [40];    
char lastname [40]; 
char address [100]; 
char phone[10];
}contact;   


int main ()
{   FILE *pFile;
    contact entry = {""};
    int choice, firstname_flag = TRUE, lastname_flag = TRUE, address_flag = TRUE, phone_flag = TRUE;

    pFile = fopen("C:\\contacts.txt", "a+");

    if(!pFile){
        printf("File could not be open.");
        return 1;
        }

    do{
    printf("Choose a selection:\n\n");
    printf("1. First name:\n");
    printf("2. Last name:\n");
    printf("3. Address:\n");
    printf("4. Phone number:\n\n");
    scanf( "%d", &choice);
    }while((choice < 1 || choice > 4));

    switch (choice){
    case 1:
        firstname_flag = FALSE;
        printf("Please enter first name: \n");    
        scanf("%s", &entry.firstname);
        break;
    case 2:
        lastname_flag = FALSE;
        printf("Please enter last name: \n");     
        scanf("%s", &entry.lastname);
        break;
    case 3:
        address_flag = FALSE;
        printf("Please enter address: \n");   
        scanf("%s", &entry.address);
        break;
    case 4:
        phone_flag = FALSE;
        printf("Please enter phone number: \n");      
        scanf("%s", &entry.phone);
        break;
    default:
        break;
    }

    printf("\nYou will now be asked to enter the other items. \n\n");

    if(firstname_flag){
        printf("Please enter first name: \n");
        scanf("%s", &entry.firstname);
    }    
    if(lastname_flag){
    printf("Please enter last name: \n");
    scanf("%s", &entry.lastname);
    }
    if(address_flag){
        printf("Please enter address: \n");
        scanf("%s", &entry.address);
    }
    if(phone_flag){
        printf("Please enter phone number: \n");
        scanf("%s", &entry.phone);
    }

    fwrite (here)

    fclose(pFile);

    getchar();
    return 0;
}

Вот код, который у меня есть.Во-первых, есть ли что-нибудь вопиющее, что выдает себя за недействительную или неправильную практику и т. Д.?2-й я хочу записать имя, фамилию, адрес и номер телефона в файл.Я не уверен, нужно ли мне писать "запись" или нет.Кроме того, я заметил, что при выборе адреса «Сначала» это почти как если бы буфер не был пустым, и то, что я поставил после пробела, то есть 123 «Парк», «Парк», будет неправильно использоваться в качестве имени, а следующая запись, которую я бы вставил, будет «Последняя»название.Будем весьма благодарны за любые предложения по использованию кода и прочее.Еще раз спасибо

1 Ответ

1 голос
/ 09 декабря 2011

1

N ° 1. В ответ на: «недопустимая или неправильная практика». Некоторые из них являются скорее вопросами вкуса…

  • Если вы «должны» использовать scanf, не указывайте его на строковом буфере с помощью %s: укажите длину буфера, например, от %32s до уменьшите (но возможно не исключайте, что кто-то просто слишком много печатал и ломал вашу программу (или хуже ...) - Но, читайте № 3 ниже, чтобы узнать больше по этому вопросу…
    • Если вы разрабатываете что-то с открытым исходным кодом или для личного использования, GNU readline - очень хороший вариант (но это GPL , а не LGPL , так что он может не будет использоваться в "не-libre" работах ...)
  • Ваш инициализатор структуры не охватывает все элементы. Вы можете использовать {"", "", "", ""}
  • Вы имели в виду fwrite(entry)?
  • Если вы проверяете пропущенные поля перед записью файла, вы можете оставить банк флагов в стороне и вместо этого зацикливаться на «недействительном условии».

     while ('\0' == entry.firstname[0]) {
        printf("Please enter first name: \n");
        scanf("%40[^\r\n\0\04]", &entry.firstname[0]);
     }
    
  • Нет необходимости открывать файл так рано и оставлять его открытым в ожидании взаимодействия с пользователем. Открытие файла в режиме a+ является довольно «опасным» (см. man lockf для «тощего»), потому что кто-то другой может попытаться записать файл в то время, пока вы находитесь; если оставить его открытым в этом режиме на длительное время, риск возрастет.

  • Вам, вероятно, следует использовать strerror(errno) для предоставления пользователю подробной информации о сбое системного вызова, например, при проверке кодов возврата fopen, fwrite и fclose. Из-за того, что буферизованный ввод / вывод работает, fclose может даже сообщать о проблеме, возникшей с fwrite при некоторых обстоятельствах.
  • Напечатайте ваши сообщения об ошибках на stderr, используя fprintf (stderr,); вместо выходного потока…
  • Если вы собираетесь использовать флаги для указания того, что данные являются «действительными» (или, по крайней мере, таковыми могут быть), вам, вероятно, следует сделать это после после Пользователь пытается ввести его, а не раньше.
  • Функции - ваши друзья ... Я бы, вероятно, разбил что-то вроде этого, используя функцию для сбора ввода пользователя (что-то вроде prompt_for_field ("first name", &entry.firstname);), функцию для проверки пропущенных записей и запроса их, а также функцию для записи запись в файл, не менее…
  • Обычно считается хорошей формой exit с main, а не return, например, с использованием exit(EXIT_SUCCESS) / exit(EXIT_FAILURE). Я считаю, что идея заключается в поддержке эзотерических и возможных вымерших систем, которые могут рассматривать некоторые значения, отличные от 0, как успешный код состояния (VMS, возможно?), Но, тем не менее, легче читать: -)

2

И № 2, да, вы можете fwrite(entry), и до тех пор, пока вы никогда не измените определение struct contact, вы сможете прочитать его обратно в полном порядке. Со временем вы, вероятно, захотите переключиться на более простой текстовый формат (#include <json-xml-init-religious-war>), но в этом небольшом примере нет острой необходимости вводить такую ​​сложность.

3

Наконец, N ° 3, вам, вероятно, следует использовать &entry.address[0], чтобы получить адрес начала char[], но наиболее важно: scanf %s не читает строку. Это выглядит как printf %s, но это не ...

s Соответствует последовательности символов без пробелов; следующий указатель должен быть указателем на символ массив, который достаточно длинный, чтобы содержать входную последовательность и завершающий нулевой символ ('\ 0'), который добавляется автоматически. Строка ввода останавливается на пустом месте или на максимальной ширине поля, что произойдет первым.

Видите это "не пробел?"«Это то, что у вас есть. Остальная часть вашего ввода (после первого пробела) остается в буфере клавиатуры, ожидая, пока другой scanf его прочитает. Хороший ('ish) способ чтения из терминала и принятия пробела -%40[^\r\n\0\04], заменив 40 размером вашего строкового буфера (char[]). Это означает, что можно принять (до) 40 символов, если только они не являются: возврат каретки, новая строка,нулевой байт или код конца файла (^D).

В целом, вы все равно на правильном пути. Удачи: -)

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...