知表不言 发表于 2017-7-18 08:03:50

关于输入的有效性判断的问题 scanf和getchar()

怎样才能完成有效性判断啊?前面用getchar()只能过第一个判断,后面就一直判断失败(清除缓冲区也没用)
改成整型用scanf输入数字好多了,可刚才试了下输入字母,又过不了判断了,就在*标记位置*改成‘return 0;’结束程序都退出不了{:9_234:}
具体代码如下
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

//输入的有效性判断未完成

struct Contact
{
        char name;
        charnum;
        struct Contact *next;
};
int mark = 0; //处理标记

void addPerson(struct Contact **head);
void findPerson(struct Contact *head);
void changePerson(struct Contact **head);
void delPerson(struct Contact **head);
void displayContacts(struct Contact **head);
void releaseMem(struct Contact *head);

int main()
{
        int ch;
        struct Contact *head = NULL;
        printf("\
        ##########################################\n\
        #   通   讯   录   程   序   #\n\
        ##########################################\n");
        while(1)
        {
                printf("功能列表:\n\
                1.插入新的联系人\n\
                2.查找已有的联系人\n\
                3.更改已有的联系人\n\
                4.删除已有的联系人\n\
                5.显示当前通讯录\n\
                6.退出通讯录程序\n");
                printf("请输入指令:");
                scanf("%d", &ch);
                while(ch < 1 || ch > 6)
                {
                        printf("请输入有效的数字!\n");
                        scanf("%d", &ch);               *******标注位置*******
                }
                switch(ch)
                {
                        case 1:addPerson(&head);break;
                        case 2:
                             {
                                     mark = 0;
                                     findPerson(head);
                                        if(mark == 0)
                                        {
                                                printf("\
                ***********************************\n\
                *很抱歉,未能找到符合条件的联系人!*\n\
                ***********************************\n");
                                        }
                                        break;
                             }
                        case 3:
                             {
                                     mark = 0;
                                        changePerson(&head);
                                        if(mark == 0)
                                        {
                                                printf("\
                ***********************************\n\
                *很抱歉,未能找到符合条件的联系人!*\n\
                ***********************************\n");
                                        }
                                        break;
                             }
                        case 4:
                             {
                                     mark = 0;
                                        changePerson(&head);
                                        delPerson(&head);
                                        if(mark == 0)
                                        {
                                                printf("\
                ***********************************\n\
                *很抱歉,未能找到符合条件的联系人!*\n\
                ***********************************\n");
                                        }
                                        break;
                             }
                        case 5:displayContacts(&head);break;
                        case 6:{
                                releaseMem(head);
                                return 0;
                             }
                }
        }
}

void addPerson(struct Contact **head)
{
        struct Contact *current = *head;
        struct Contact *previous = NULL;
        struct Contact *new = (struct Contact *)malloc(sizeof(struct Contact));
        if(new == NULL)
        {
                printf("内存分配失败了!\n");
                exit(-1);
        }
        printf("请输入新建联系人姓名:");
        scanf("%s", new->name);
        printf("请输入新建联系人联系方式:");
        scanf("%s", new->num);
        if(*head == NULL)
        {
                *head = new;
                new->next = NULL;
        }
        else
        {
                while(strcmp(current->num, new->num) < 0 && current->next != NULL)
                {
                previous = current;
                current = current->next;
                }
                if(previous == NULL)
                {
                        new->next = current;
                        *head = new;
                }
                else if(current == NULL)
                {
                        new->next = NULL;
                        current = new;
                }
                else
                {
                        new->next = current;
                        previous->next = new;
                }
        }
}

void findPerson(struct Contact *head)
{
        char target;
        struct Contact *previous = NULL;
        struct Contact *current = head;
        printf("请输入要查找的联系人姓名或号码:");
        scanf("%s", target);
        do
        {
                if(!strcmp(current->num, target) || !strcmp(current->name, target))
                {
                        mark = 1;
                        printf("已经找到符合条件的联系人...\n");
                        printf("\t姓名:%s\t联系方式%s\n", current->name, current->num);
                }
                previous = current;
                current = current->next;
        }while(current != NULL);
}
void changePerson(struct Contact **head)
{
        int confirm;
        char new1;
        char target;
        struct Contact *previous = NULL;
        struct Contact *current = *head;
        printf("请输入要修改的联系人姓名或号码:");
        scanf("%s", target);
        while(current != NULL)
        {
                if(!strcmp(current->num, target) || !strcmp(current->name, target))
                {
                        mark = 1;
                        printf("已经找到符合条件的联系人...\n");
                        printf("\t姓名:%s\t联系方式%s\n", current->name, current->num);
                        printf("您想将%s修改为:", target);
                        scanf("%s", new1);
                        printf("确认修改(修改:1/取消:2):");
                        scanf("%d", &confirm);
                        while(confirm != 1 && confirm != 2)
                        {
                                printf("输入错误请重新输入!\n确认修改(修改:1/取消:2):");
                        }
                        if(confirm == 1)
                        {
                                if(!strcmp(current->num, target))
                                {
                                        strcpy(current->num, new1);
                                }
                                else
                                {
                                        strcpy(current->name, new1);
                                }
                        }
                }
                previous = current;
                current = current->next;
        }
}

void delPerson(struct Contact **head)
{
        int confirm;
        char target;
        struct Contact *previous = NULL;
        struct Contact *current = *head;
        if(*head == NULL)
        {
                printf("联系人总数为0,无法完成该操作!\n");
                printf("\
                ************************************\n\
                ***联系人总数为0,无法完成该操作!***\n\
                ************************************\n");
                return;
        }
        printf("请输入要删除的联系人姓名或号码:");
        scanf("%s", target);
        while(current != NULL)
        {
                if(!strcmp(current->num, target) || !strcmp(current->name, target))
                {
                        mark = 1;
                        printf("已经找到符合条件的联系人...\n");
                        printf("\t姓名:%s\t联系方式%s\n", current->name, current->num);
                        printf("确认删除(删除:1/取消:2):");
                        scanf("%d", &confirm);
                        while(confirm != 1 && confirm != 2)
                        {
                                printf("输入错误请重新输入!\n确认删除(删除:1/取消:2):");
                        }
                        if(confirm == 1)
                        {
                                if(previous == NULL) //删除的目标为第一个联系人
                                {
                                        previous = *head;
                                        *head = (*head)->next;
                                        free(previous);
                                }
                                else
                                {
                                        previous->next = current->next;
                                        free(current);
                                }
                        }
                }
                previous = current;
                current = current->next;
        }
}

void displayContacts(struct Contact **head)
{
        if(*head == NULL)
        {
                printf("无联系人可显示!\n");
                return;
        }
        struct Contact *current = *head;
        printf("\n\
                *********************\n\
                * 显示联系人信息如下*\n\
                *********************\n");
        while(current != NULL)
        {
                printf("\t姓名:%s\t联系方式%s\n", current->name, current->num);
                current = current->next;
        }
        printf("\n");
}

void releaseMem(struct Contact *head)
{
        struct Contact *previous = NULL;
        struct Contact *current = head;
        while(current != NULL)
        {
                previous = current;
                current = current->next;
                free(previous);
        }
}

新手·ing 发表于 2017-7-18 08:38:37

http://blog.csdn.net/hao5743/article/details/6939661

ba21 发表于 2017-7-18 08:51:21

本帖最后由 ba21 于 2017-7-18 08:52 编辑

        while(1)
                                {
                                        printf("是否继续添加数据?(y/n):");
                                        do
                                        {
                                                ch=getchar();
                                               
                                        }while(ch != 'y' && ch !='n');
                                        if (ch == 'y')
                                                add(&head);
                                        else
                                                break;
                                }                                       

下面 strcmp 要引入 #include "string.h"
printf("已经找到该记录,是否删除?(y/n)");
                        scanf("%s",ch);
                        if(strcmp(ch,"Y")==0||strcmp(ch,"y")==0)
                        {
                              for(j=i;j<m;j++)
                                        comm=comm;
                              m--;
                              printf("成功删除!\n");
                        }

知表不言 发表于 2017-7-18 22:16:12

终于找到答案了,初始判断条件字符未赋予初始化值;
当scarf期待获取数值却在缓冲区得到一个字母他就会跳过该条语句,不给判断条件赋值,而遇到后面判断语句条件字符就是一个随机数(未初始化,内存内信息是随机的),就会循环读取,而那个字母还在缓冲区,就会接着判断,解决方法就是给判断条件初始化为一个合理的值,比如下面这样:
#include<stdio.h>
#include<stdlib.h>
#include<time.h>
#define random(x) (rand()%x)
#define SUM 96//每列显示长度(数字+空格)
int main()
{
        int c, x, s;
        int n = 0;//n有效范围0~999999999
        srand((int)time(0));
        printf("您想获取多少行的随机数字:");
        c = 0;//记录输错次数
        do
        {
                if(n < 0)
                {
                        printf("输入错误,请重新输入:");
                }
                scanf("%d",&n);
                fflush(stdin);
                c++;
                if(c > 9)
                {
                        printf("输入次数过多,请稍后重试!\n");
                        n = 0;//n为0时直接退出程序
                }
        }while(n < 0 || n > 999999999);
        if(n)
        {
                printf("您是否想在随机数字间加入空格(输入0不加空格):");
                scanf("%d",&s);
        }
        for(; n; n--)
        {
                for(x=0;x<SUM;x++)
                {
                        if(s)
                        {
                                printf("%d ",random(10));
                                x++;
                        }
                        else
                        {
                                printf("%d",random(10));
                        }
                }
                putchar('\n');
        }
return 0;
}

知表不言 发表于 2017-7-19 23:33:54

我把昨天的代码又重新改了一下,把输入无效字符和输入负数等价,这样就不会一输入无效字符就秒退程序啦{:10_282:}
#include<stdio.h>
#include<stdlib.h>
#include<time.h>
#define random(x) (rand()%x)
#define SUM 96//每列显示长度(数字+空格)
int main()
{
        int c, x, s;
        int n = -1; //给n初始化
        srand((int)time(0));
        printf("您想获取多少行的随机数字:");
        c = 0; //输入错误计数
        do
        {
                if(c != 0 && n < 0) //首次读取前不报错
                {
                        printf("输入错误,请重新输入:");
                }
                scanf("%d",&n);
                if(n == -1)//n为初始值说明输入的不是有效数字(或者-1)
                {
                        getchar();//从缓冲区中读取无效字符
                }
                c++;
                if(c > 9) //输入9次无效(数字/字符)后直接退出程序
                {
                        printf("输入次数过多,请稍后重试!\n");
                        return 0;
                }
        }while(n < 0 || n > 999999999);
        if(n)
        {
                printf("您是否想在随机数字间加入空格(输入0不加空格):");
                scanf("%d",&s);
        }
        for(; n; n--)
        {
                for(x=0;x<SUM;x++)
                {
                        if(s)
                        {
                                printf("%d ",random(10));
                                x++;
                        }
                        else
                        {
                                printf("%d",random(10));
                        }
                }
                putchar('\n');
        }
return 0;
}

知表不言 发表于 2017-8-14 23:12:41

又想到一种判断输入有效性的方法,就是直接把scanf函数当作判断条件,以下这段代码是甲鱼老师数据结构与算法系列中逆波兰表达式的改进版,就它为例子吧^_^
#include <stdio.h>
#include <stdlib.h>

#define STACK_INIT_SIZE 20
#define STACKINCREMENT10

typedef double ElemType;

typedef struct
{
        ElemType *base;
        ElemType *top;
        int StackSize;
}Stack, *pStack;

void StackInit(pStack *ptr);
void StackDestroy(pStack ptr);
void StackPop(pStack ptr, ElemType * p);
void StackPush(pStack ptr, ElemType data);

int main()
{
        char c = '0';
        ElemType num, a, b;
        Stack stack;
        pStack ptr = &stack;
        StackInit(&ptr);
        system("clear");
        printf("\n\n友情提示:\n\t1.可分别用小写字母p m t d替代加减乘除运算符\n");
        printf("\t2.(加减号+数字)前的空格不可省略,或可用p m替换加减号(本程序支持负数预算)\n");
        printf("\t3.连续两个数字间空格不可省略,其余项可连续输入\n\n");
        printf("请输入逆波兰表达式:");
//        printf("%d\n", (scanf("%lf", &num)));
//        printf("%f\n", num);
        while(c != '#')
        {
                while(1)
                {
                        if(scanf("%lf", &num))
                        {
                                StackPush(ptr, num);
                        }
                        else
                        {
                                c = getchar();
                                if(c == '+' || c == '-' || c == '*' || c == '/' || c == 'p' || c == 'm' || c == 't' || c == 'd' || c == '#')
                                {
                                        break;
                                }
                        }
                }
                switch(c)
                {
                        case '+':
                        case 'p':
                                StackPop(ptr, &b);
                                StackPop(ptr, &a);
                                StackPush(ptr, a + b);
                                break;
                        case '-':
                        case 'm':
                                StackPop(ptr, &b);
                                StackPop(ptr, &a);
                                StackPush(ptr, a - b);
                                break;
                        case '*':
                        case 't':
                                StackPop(ptr, &b);
                                StackPop(ptr, &a);
                                StackPush(ptr, a * b);
                                break;
                        case '/':
                        case 'd':
                                StackPop(ptr, &b);
                                StackPop(ptr, &a);
                                if(b == 0)
                                {
                                        printf("除数不能为零!\n");
                                        exit(-1);
                                }
                                StackPush(ptr, a / b);
                                break;
                        default:
                                break;
                }
                if(ptr->top - ptr->base != 1 && c == '#')
                {
                        c = getchar();
                }
        }
        if(ptr->top != ptr->base)
        {
                StackPop(ptr, &num);
                printf("\n最终计算结果为:%f\n\n", num);
        }
        StackDestroy(ptr);
        return 0;
}

void StackInit(pStack *ptr)
{
        (*ptr)->base = (ElemType *)malloc(sizeof(ElemType) * STACK_INIT_SIZE);
        (*ptr)->top = (*ptr)->base;
        (*ptr)->StackSize = STACK_INIT_SIZE;
        return;
}

void StackPush(pStack ptr, ElemType data)
{
        int len = ptr->top - ptr->base;
        if((ptr->top - ptr->base) >= ptr->StackSize)
        {
                ptr->base = (ElemType *)realloc(ptr->base, sizeof(ElemType) * (STACK_INIT_SIZE + STACKINCREMENT));
                ptr->top = ptr->base + len;
                ptr->StackSize += STACKINCREMENT;
        }
        *(ptr->top) = data;
        ptr->top++;
//        printf("压入数据%f\n", data);
        return;
}

void StackPop(pStack ptr, ElemType * p)
{
        if(ptr->top == ptr->base)
        {
                printf("输入错误,请检查后重新输入!\n");
                exit(-1);
        }
        else
        {
        ptr->top--;
        *p = *(ptr->top);
//        printf("压出数据%f\n", *p);
        }
        return;
}

void StackDestroy(pStack ptr)
{
        free(ptr->base);
        return;
}
页: [1]
查看完整版本: 关于输入的有效性判断的问题 scanf和getchar()