# 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和形参的地方改一下即可。