2017-02-17 4 views
0

У меня есть простая телефонная книга, написанная на C, которая сохраняет входную информацию в текстовый файл на моем компьютере.Программа телефонной книги C: как выйти из бесконечного цикла и как вернуться в меню оператора switch

#include <stdio.h> 
#include <stdlib.h> 
#include <string.h> 
#include <ctype.h> 
#include <stdbool.h> 

void validateName(char name[], FILE *fptr); 
void validateID(char id[], FILE *fptr); 
void validateScore(int score, FILE *fptr); 
void addContact(char name[], char id[], int score, FILE *fptr); 
void printContact(FILE *fptr); 
void printAll(); 

int main() 
{ 
    char name[30], id[10]; 
    int score; 
    int i; 

    FILE *fptr; 
    fptr = fopen("C:\\c\\program.txt","w"); 

    if(fptr == NULL) 
    { 
     printf("Error!"); 
     exit(1);    
    } 
    else { 

     bool flag = true; 
     do{ 
      printf("\n1. Press 1 to display record\n" 
        "2. Press 0 to add a new contact\n" 
        "3. Press -1 to display all records\n\n"); 

      int option; 
      scanf("%d", &option); 
      switch(option) { 
       case 1: 
        printContact(fptr); 
        flag = false; 
        break; 
       case 0: 
        addContact(name, id, score, fptr); 
        flag = false; 
        break; 
       case -1: 
        printAll(); 
        flag = false; 
        break; 
       default: 
        printf("wrong choice, try again\n\n");    
      }  

     } while(flag); 

    fclose(fptr); 
    return(0); 
    } 
} 

void validateName(char name[], FILE *fptr){ 

    bool flag = true; 

    while(flag){ 
     fgets(name, 30, stdin); 
     if ((strlen(name) < 3) || (strlen(name) > 20)) { 
       printf("error\nplease enter name again: "); 
     } else { 
      flag = false; 
     }  
    } 
} 

void validateID(char id[], FILE *fptr){ 

    bool flag = true; 
    while(flag) { 
     if (!isalpha(id[0])){ 
      printf("enter a letter as first char\n"); 
     } 
     else if(strlen(id) > 10) { 
      printf("error too much numbers \n"); 
     } else { 
      flag = false; 
     } 
    } 
} 

void validateScore(int score, FILE *fptr) { 

     if(score >= 0 && score <= 100) { 
      fprintf(fptr, "SCORE: %d\n", score); 
      } else { 
       printf("invalid input"); 

       (exit(1)); 
      } 
} 

void addContact(char name[], char id[], int score, FILE *fptr) { 

    //first name 
    printf("Enter name: ");  
    scanf("%s", name); 
    validateName(name, fptr); 
    fprintf(fptr,"NAME: %s \n", name); 

    //id 
    printf("Enter id: "); 
    scanf("%s", id); 
    validateID(id, fptr); 
    fprintf(fptr,"STUDENT NO: %s\n", id); 

    //score  
    printf("enter score: "); 
    scanf("%d", &score); 
    validateScore(score, fptr); 
} 

void printContact(FILE *fptr) { 

    int c; 
    char contacts[50]; 

    while((c = getchar()) != EOF) { 
     fscanf(fptr, "%s", &contacts); 

     for(int i = 50; i < 50; i++){ 
      printf("%s", &contacts); 
     } 
    } 




} 

void printAll() { 

} 

мой первый вопрос находится в функции validateID: я получаю в бесконечный цикл, когда я пытаюсь проверить первое условие, которое должно убедиться, что первый индекс является характер.

Моя вторая проблема: когда я ввожу имя, идентификатор студента и оценку, программа заканчивается, и я не возвращаюсь к оператору переключения меню, чтобы выбрать другие параметры?

Что я делаю неправильно или что мне не хватает?

ответ

0

Для validateID() вы ничего не меняете внутри цикла while, что приведет к прекращению. Вы всегда проверяете id[0] или strlen(id), но ничего не меняете о id или как вы его проверяете. Если id[0] не является буквенно-цифровым, вы просто наведете его навсегда. Или, если это буквенно-цифровое, но strlen(id) равно < = 10, вы навсегда зациклитесь на этом. Что именно вы здесь зацикливаете?

Ваша программа завершается после однократного выбора меню, потому что все выборы установить flag на ложь, и это никогда не будет повторно инициализируется true - поэтому цикл while завершается и программа завершается.

+0

Я зацикливаю, если первый символ не является буквенно-цифровым И если число меньше девяти чисел после первой буквы. поэтому, если эти условия не выполняются, цикл должен отображать ошибку и просить пользователя повторно ввести письмо или повторно ввести действительное количество чисел – Rgoat

+0

, как бы я повторно инициализировал флаг в инструкции switch? – Rgoat

+0

Вам нужно сказать компьютеру, чтобы он сделал то, что вы хотите. Ваш дизайн не позволяет делать то, что вы хотите, - я указал, почему ваша программа не работает, вам решать, как это исправить, как программист, поскольку это проблема дизайна, поскольку против конкретной ошибки. – Caleb

0

вы должны будете использовать scanf после этой строки printf("enter a letter as first char\n");

2

Идея иметь такие функции, как void validateXXX, на мой взгляд, неправильно. Сравните его с isalpha, который похож на проверку. isalpha возвращает int, так что вы можете использовать его для проверки. Вероятно, ваши функции проверки должны сделать то же самое. Таким образом, вместо:

void validateID(char id[], FILE *fptr){ 

    bool flag = true; 
    while(flag) { 
     if (!isalpha(id[0])){ 
      printf("enter a letter as first char\n"); 
     } 
     else if(strlen(id) > 10) { 
      printf("error too much numbers \n"); 
     } else { 
      flag = false; 
     } 
    } 
} 

функция может быть:

int validateID(char id[]){ 
    if (!isalpha(id[0])){ 
      printf("enter a letter as first char\n"); 
      return 0; 
    }  
    if(strlen(id) > 10) { 
      printf("error too much numbers \n"); 
      return 0; 
    }  
    return 1; 
} 

, а затем вы можете использовать его как:

do { 
    scanf("%s", id); // See below !!!! 
} while(!validateID(id)); 

так, что вы продолжаете читать, пока действительный ID не введен ,

Следующая:

Никогда использование scanf("%s", ...) - Никогда

Там нет проверки на длину ввода, так что пользователь может ввести некоторый текст слишком долго, чтобы быть сохранены в буфере вы (например, id). Это будет катастрофично для вашей программы, поскольку она будет писать границу внешнего массива. Ваша программа может рухнуть или сделать всевозможные странные вещи.

Вы должны использовать fgets для чтения пользовательского ввода. Это намного проще и безопаснее.

Для вашей основной петли:

Да, потому что это закончится, как вы установите flag ложь во всех case с в switch.

0

Ниже приведена декларация для функции isalpha().

int isalpha (int c);

Эта функция возвращает ненулевое значение, если c - алфавит, иначе он возвращает 0. Ваше время всегда будет поддерживать истинное состояние. что он входит в один из двух вышеперечисленных случаев? Поэтому, как только он уйдет, убедитесь, что вы вернули false или 0, пока оно не выйдет. Теперь вам решать, как это изменить.