对int char 输入遇到的问题 的探讨

# include <stdio.h>//int char 输入容易出问题 下面的代码可以解决这个问题
# define N 10  //如果要录入X个字节则 N=X
int Getchar(char A[],int min,int max);//直到用户输入的字符串长度在[min,max]之间时 函数结束 返回字符串A的长度
int gainint(int *p,int a,int b);
int main(){
	char A[N+1];//最后一位存'\0'
	int B;
	printf("输入字符串:1--1字节");
    Getchar(A,1,1);
     printf("输入字符串:0--%d字节",N);
    Getchar(A,0,N);//因为min=0  这个时候直接输入回车 结束录入 字符串为空字符串
	 printf("输入字符串:1--%d字节",N);
    Getchar(A,1,N);//因为min=1  这个时候直接输入回车 是不会结束录入的
	printf("输入B 1----100:");
	gainint(&B,1,100);
    printf("输入B 2----4:");
	gainint(&B,2,4);
    return 0;
}
int gainint(int *p,int a,int b)//输入int *p直至满足(a,b)输入结束,并返回*p的位数      
{       
    do{      
        *p=a-1;    //此处是为了减少意外情况的发生 虽然那种意外情况不常见
        scanf("%d",p);      
        while(getchar()!='\n');      
        if(*p>b||*p<a)      
            printf("输入有误,请重新输入(%d--%d):\n",a,b);      
    }while(*p>b||*p<a);      
    return *p;      
}      
int Getchar(char *A,int min,int max)//长度在[min,max]  <闭区间>  之间时 函数结束 返回字符串A的长度    
{    
    int B,C;//B保存A的长度 C记录缓冲区的字符串    
    do{    
        B=-1;  C=0; //每次用户输入错误而循环时 都要初始化    
        fgets(A,max+1,stdin);//从键盘录入字符    
        while(A[++B]);  //求A的字符串长度    
        if(A[B-1]!='\n') while(getchar()!='\n') C++;    //如果缓冲区里读入的不是\n则记录字符串数量    
        else  A[--B]='\0'; //☆  去掉\n 并且字符串长度-1    
        if(C||B&&B<min) //如果缓冲区有字符串或者长度不够 则提示错误   但如果用户只输入回车而且min!=0则不提示错误 但还要输入当前字符串      
        printf("您输入的字符串长度:%d字节\n请重新输入!\n注:只输入(%d--%d)个字节!\n",B+C,min,max);    
    }while(C||B<min);    
    return B;//返回B 即:A字符串的长度    
}     

模拟用户输入密码框:

# include <stdio.h>//int char 输入容易出问题 下面的代码可以解决这个问题
# include <conio.h>
# define N 10  //如果要录入X个字节则 N=X
int Getchar(char A[],int min,int max);//直到用户输入的字符串长度在[min,max]之间时 函数结束 返回字符串A的长度
int main(){
	char A[N+1];//最后一位存'\0'
	printf("输入字符串:1--1字节:");
    Getchar(A,1,1);
	puts(A);
	printf("输入字符串:0--%d字节\n",N);
    Getchar(A,0,N);//因为min=0  这个时候直接输入回车 结束录入 字符串为空字符串
	puts(A);
	printf("输入字符串:1--%d字节\n",N);
	Getchar(A,1,N);//因为min=1  这个时候直接输入回车 是不会结束录入的
	puts(A);
    return 0;
}
int Getchar(char *A,int min,int max)//长度在[min,max]  <闭区间>  之间时 函数结束 返回字符串A的长度
{
    int B,C;
	do{
		B=0;
		while((C=getch())!='\r')
            if(C!=8&&B<max)
            {
                printf("*");
                A[B++]=C;
            }
			else if(C==8&&B>0){
			   printf("\b \b");
			   B--;
			}
        A[B]=0;
		if(B<min)
		{
			B+=printf("密码过短!");
			for(C=0;C<100000000;C++);
			while(B--)printf("\b \b");
		}
    }while(B<min);
	printf("\n");
    return B;
}

# include <stdio.h>//int char 输入容易出问题 下面的代码可以解决这个问题
# include <conio.h>
# define N 10  //如果要录入X个字节则 N=X
int secret_char(char A[],int min,int max);//直到用户输入的字符串长度在[min,max]之间时 函数结束 返回字符串A的长度
int main()
{
    char A[N+1];
    printf("用户名:");
    secret_char(A,2,10);
    puts(A);
    return 0;
}
int secret_char(char *A,int min,int max)//长度在[min,max]  <闭区间>  之间时 函数结束 返回字符串A的长度
{
    int B,C,D;
    do
    {
        B=max+printf("[");for(C=1; C<B; C++)printf(" ");printf("]");
        while(B--)printf("\b");
        B=0;
        while((C=getch())!='\r')
            if(C!=8&&B<max)
            {
                printf("%c",C);
                A[B++]=C;
            }
            else if(C==8&&B>0)
            {
                printf("\b \b");
                B--;
            }
            else if(B>=max)
            {
                D=printf("]长度:[%d,%d]!",min,max);
                for(C=0; C<100000000; C++);
                while(D-->1)printf("\b \b");
                printf("\b");
            }
        A[B]=0;
        if(B<min)
        {
            D=B+printf("Too short!");
            for(C=0; C<100000000; C++);
            while(D--)printf("\b \b");
            printf("\b");
        }
    }
    while(B<min);
    printf("\n");
    return B;
}


下面是我琢磨这两个函数的过程

在visualc++6.0或其他的编辑器中 ,几乎每一个程序都有输入   最频繁的  大概就是   int char 的类型的输入了 ,我们经常会遇到这样一个问题:在输入数据时输入了字母或其他字符 就是没有输入数,程序此时会停止运行或者死循环;或者在输入char类型时数组超界了,程序停止了运行,要么就是虽然得到了合法的字符或数字,但是缓冲区没有清理干净,或者即使清理干净了,操作却多了一些^^^^。作为一个计算机编程的 即使程序做的很好,却没有排错和检验 那么这样的程序经不起一点摧残。

我曾经做过许多次输入方面的检验函数  其中不乏 很复杂的 或者   需要很多头文件的 ,在一年半的摸索中我写出了很多关于输入方面的检验函数,虽然我没有做过大程序,但我编的程序很难出现程序突然停止运行的情况 也很难出现野指针的情况。在摸索过程中我遇过这些问题,在这之前有必要说一些东西:

gets();程序容易出现输入的字符过多导致数组超界而死亡--不安全。

scanf();输入的如果不是数字或者 输入了  数字+空格+数字,第二个数字在缓冲区可能会被下一个输入量读取--导致界面输出的不美观,隐藏安全隐患。

fgets(a,N,stdin)如果a字符数组的长度为N 则第N-1个字符自动变为'\0',多余的将留在缓冲区,可能会被下一个变量读走,有安全隐患。

我在学C语言程序设计时在书上出现过这样的int类型的排错

 int a;

printf("请输入a(1-100)\n");

scanf("%d",&a);

while(a>100||a<1)

{

printf("输入有误请重新输入!\n");

scanf("%d",&a);

while(getchar()!='\n');

}

在初学时我经常用这个来拍错,但使用过程中发现了很多问题:

1:对于上面的a如果我一次性输入了数字和空格交替,如   0 0 101 1 2(此时按回车)

程序出现:

输入有误请重新输入!

输入有误请重新输入!      两次提示

然后我又将while(getchar()!='\n');放到了printf("输入有误请重新输入!\n");之前  但是又出现了问题。

如果在a 之后又出现了需要用户输入比如b(1--100)的情况

那么我如果在 输入a时 输入了  1    101(此时回车),那么b的输入直接就开始了  如果在输入b时还有提示 则又会出现:

请输入a(1-100): 1     1(此时回车)

请输入b(1--100)

输入有误请重新输入!

造成界面不好。而且如果一个程序老是用这个则显得代码很冗长。而且 主要矛盾问题没有解决。

我试了很多个,最终写出了以下代码:

int a;

do{

   printf("请输入a(1-100)\n");

scanf("%d",&a);

while(getchar()!='\n');

}while(a<1||a>100);

开始时用的很“爽”,即使用户输入 数字+空格+数字 也不会被读取到下一个变量中,可是我又发现了一个问题,如果一个程序里有循环机制,a恰巧在这个循环及治理比如:

int a,b;

do{

do{

   printf("请输入a(1-100)\n");

scanf("%d",&a);

while(getchar()!='\n');

}while(a<1||a>100);

printf("请输入b(b!=0)\n");

scanf("%d",&b);

while(getchar()!='\n');

}while(!b);

那么如果我输入的b不正确 ,在循环时又要重新输入a但是a已经是输入正确的了---

于是我又改了一下:

int a=-1;

while(a>100||a<1)

{

  printf("请输入a(1-100)\n");

scanf("%d",&a);

while(getchar()!='\n');

}这样虽然要让a赋一个不合法的初始值,但也算解决了这个问题,但是 如果一个程序老写这样的虽然不长只有3-4行但重复的代码,那么也会导致程序冗长。

于是,我又想了很久,最后写出了一个函数,能解决很大一部分问题。

代码 如下:

int gainint(int *p,int a,int b)//a为最小值b为最大值
{
int c[2]={0,1};
do{
 scanf("%d",p);
 while(getchar()!='\n');  
       if(*p>b||*p<a)
  printf("输入有误,请重新输入(%d--%d):",a,b);
}while(*p>b||*p<a);
    while(*p/c[1])
{
c[1]*=10;
c[0]++;
}
return c[0];//返回数字的位数
}

在主函数中可以变换花样的调用:

1:如果我想输入a,a没有在循环机制里,则主函数中可以这样写:

printf("请输入a(1--100)");

gainint(&a,1,100);

2:如果a在循环机制里我输入的a合法了,需要在循环时跳过a的输入可以这样写:

int a=-1;

if(a<1||a>100)

{

 

printf("请输入a(1--100)");

gainint(&a,1,100);

}

3:如果我只想要某些区间的特殊数字比如我只要10-20或40--60之间的数可以这样写:

do{

   printf(“请输入a(10--20   40--60)\n”)

gainint(&a,10,60);

}while(a>20&&a<40);

基本上出现的大部分问题都可以解决了。

而且此函数重复调用之后,代码虽然增加了此函数的长度,但程序变得更健壮了,而且可以在一定程度上减小代码:例如输入年月日

# include <stdio.h>
int gainint(int *p,int a,int b);
int main(){
int month[]={31,28,31,30,31,30,31,31,30,31,30,31},i;
int charge[6]={1,1,1,2016,12,0};
char zifu[][5]={"年份","月份","天数"};
int a[3];
for(i=0;i<3;i++)
{
printf("请输入%s(%d--%d):\n",zifu[i],charge[i],charge[i+3]);
gainint(&a[i],charge[i],charge[i+3]);
if(i==0)
month[1]=!(a[0]%4&&a[0]%100)||!(a[0]%400)?29:28;
if(i==1)
charge[5]=month[a[1]-1];
}
printf("%04d年%02d月%02d日",a[0],a[1],a[2]);
getchar();
return 0;
}
int gainint(int *p,int a,int b)//a为最小值b为最大值
{
int c[2]={0,1};
do{
scanf("%d",p);
while(getchar()!='\n');  
if(*p>b||*p<a)
printf("输入有误,请重新输入(%d--%d):",a,b);
}while(*p>b||*p<a);
    while(*p/c[1])
{
c[1]*=10;
c[0]++;
}
return c[0];//返回数字的位数
}


有兴趣的可以将代码试一下 无论你输入非数字或者小数或者多个数据  只要不合法都会提示重新输入,小数的部分直接清除掉。

另外,最头疼的大概就是char类型的输入了;如果你一不小心还没有输入字符就按下了回车。。。直接就相当于没有录入。。。

经过了很多尝试我最后得到了以下代码:

int gainchar(char *a,int min,int max)//对*a输入范围(min,max),如果字符数组中存在'\n',将其改为'\0'
{
int c;
do{
fgets(a,max,stdin);
c=strlen(a);
c=a[c-1]=='\n'&&c<max?c-1:c;
if(c>=max-1)
while(getchar()!='\n');
else
a[c]='\0';
if(c&&(c>max||c<min))//如果用户只输入'\n'则不提示输入错误,否则提示错误
printf("输入有误,请重新输入只录入(%d--%d)字节:\n",min,max-1);
}while(c>max||c<min);
    return c;
}

因为字符数组的最后一个字符必须要是'\0'所以如果你要录入四-八个字节那么数组长度最小是9

在主函数中调用如下:

# include <stdio.h>
# include <string.h>
# define N 13   //如果想录入x个字节那么就把N的数值改成x+1
int gainchar(char *a,int min,int max);//返回字符长度
void main(){
int a;
char b[N];
printf("请输入一段字符串,只录入(2--%d)字节:",N-1);
a=gainchar(b,2,N);
printf("字符数组b为:\n%s 长度%d",b,a);
    getchar();
}
int gainchar(char *a,int min,int max)//对*a输入范围(min,max),如果字符数组中存在'\n',将其改为'\0'
{
int c;
do{
fgets(a,max,stdin);
c=strlen(a);
c=a[c-1]=='\n'&&c<max?c-1:c;
if(c>=max-1)
while(getchar()!='\n');
else
a[c]='\0';
if(c&&(c>max||c<min))//如果用户只输入'\n'则不提示输入错误,否则提示错误
printf("输入有误,请重新输入只录入(%d--%d)字节:\n",min,max-1);
}while(c>max||c<min);
    return c;

}

//之后对他又改进了一下 就得到了最上面的Getchar函数

//这样输入char就像输入int一样的感觉。而且只要形参正确不会导致数组溢出。

以上就是主要的内容了,对于输入float等将gainint的函数scanf和形参的地方改一下即可。




  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值