C语言使用注意事项(四)

来源:互联网 发布:windows基于什么内核 编辑:程序博客网 时间:2024/06/08 02:40

转载于http://blog.csdn.net/yming0221/article/details/7247075

1、scanf()输入注意

当你使用scanf("%d",&a),然后用gets()读取下一行的一个字符串时,调用后好像gets()函数没有执行。

原因:这是由于scanf()函数不处理回车换行符。这样以来gets()函数读取的只是回车换行符。所以好像时gets()函数没有执行。

解决方法:可以在scanf()函数后插入一个getchar()函数来吃掉那个回车换行符。


2、scanf()的缓冲区问题

为什么说scanf()函数有问题呢?就因为它适用于结构化,格式相对整齐的数据输入。

例如下面的例子

[cpp] view plaincopyprint?
  1. #include <stdio.h> 
  2.  
  3. int main(int argc,char **argv) 
  4. {        
  5.         char a; 
  6.         while(1) 
  7.         { 
  8.                 scanf("%c",&a); 
  9.                 printf("a=%c\n",a); 
  10.         } 
  11.         return 0; 


当输入连续asdfg时运行结果如下:


这里可以看出scanf()读取数据到缓冲区,当缓冲区不空时从缓冲区截取,当缓冲区为空时,再读一组数据到缓冲区。所以为保证安全

*可以在每次scanf()后加一个清空缓冲区的语句fflush(stdin),但是这不是所有的编译器都支持的,VC6.0支持,但是GCC不支持。

*使用scanf()的替代功能函数。可以先用fgets()读入一整行,然后用字符串处理函数进行字符串处理(strtok(),strtol(),atoi())


3、printf()和sprintf()函数

就像scanf()函数一样,这两个函数也存在缓冲区的问题,例如输出一个字符串,当你不可预测字符串的长度时,可能存在字符串的过长导致缓冲区溢出,从而影响其他内存区。

如下例子:

[cpp] view plaincopyprint?
  1. int main(int argc,char **argv) 
  2.         char a[11]={0}; 
  3.         const char *p="12345678901234"
  4.         sprintf(a,"%s",p); 
  5.         printf("a= %s\n",a); 
  6.  
  7.         return 0; 


当p的长度大于系统给a分配的内存区,这样就会导致系统错误。


*当我们知道字符串的结构,我们可以使用sprintf(a,"%10s",p);防止超越内存区。

*使用snprintf()函数原型int snprintf(char *restrict buf, size_t n, const char * restrict format, ...);

例如

[cpp] view plaincopyprint?
  1. int main(int argc,char **argv) 
  2.         char a[11]={0}; 
  3.         const char *p="12345678901234"
  4.         snprintf(a,sizeof(a),"%s",p); 
  5.         printf("a= %s\n",a); 
  6.  
  7.         return 0; 




4、GCC中qsort()函数使用方法

使用方法

*对int,char,double,float等数组排序方法

[cpp] view plaincopyprint?
  1. #include <stdlib.h> 
  2.  
  3. #define MY_TYPE int 
  4. static int cmp(constvoid *a,constvoid *b) 
  5.         return *(MY_TYPE *)a > *(MY_TYPE *)b ? 1 : -1; 
  6. int va[10]={6,3,2,4,7,1,9,8,5,0}; 
  7.  
  8. int main(int argc,char **argv) 
  9.         int i; 
  10.         for(i=0;i<10;i++) 
  11.         { 
  12.                 printf("%d ",va[i]); 
  13.         } 
  14.         printf("\n"); 
  15.         qsort(va,10,sizeof(va[0]),cmp); 
  16.         for(i=0;i<10;i++) 
  17.         { 
  18.                 printf("%d ",va[i]); 
  19.         } 
  20.         printf("\n"); 
  21.         return 0; 

*对结构体按一个关键字排序

[cpp] view plaincopyprint?
  1. #include <stdlib.h> 
  2.  
  3. #define MY_TYPE _st 
  4. typedef struct _st 
  5.         int va; 
  6.         char c; 
  7. }; 
  8. struct _st st[10]; 
  9.  
  10. static int cmp(constvoid *a,constvoid *b) 
  11.         return (*(struct MY_TYPE *)a).va > (*(struct MY_TYPE *)b).va ? 1 : -1; 
  12. int main(int argc,char **argv) 
  13.         int i; 
  14.         for(i=0;i<10;i++) 
  15.         { 
  16.                 st[i].va=10-i; 
  17.         } 
  18.         printf("\n"); 
  19.         qsort(st,10,sizeof(st[0]),cmp); 
  20.         for(i=0;i<10;i++) 
  21.         { 
  22.                 printf("%d ",st[i].va); 
  23.         } 
  24.         printf("\n"); 
  25.         return 0; 


*对结构体多级排序

[cpp] view plaincopyprint?
  1. int cmp( constvoid *a , constvoid *b )  
  2. {  
  3. struct In *c = (In *)a;  
  4. struct In *d = (In *)b;  
  5. if(c->x != d->x) return c->x - d->x;  
  6. else return d->y - c->y;  
  7. }  

*对字符串数组排序

[cpp] view plaincopyprint?
  1. #include <stdlib.h> 
  2. #define LEN 30+1 
  3.  
  4. char str[4][LEN]; 
  5.  
  6. static int cmp(constvoid *a,constvoid *b) 
  7.         return strcmp((char *)a,(char *)b); 
  8. int main(int argc,char **argv) 
  9.         int i; 
  10.         strcpy(str[0],"abaa"); 
  11.         strcpy(str[1],"baaa"); 
  12.         strcpy(str[2],"baaaa"); 
  13.         strcpy(str[3],"aasasasaa"); 
  14.  
  15.  
  16.         printf("\n"); 
  17.         qsort(str,4,sizeof(str[0]),cmp); 
  18.         for(i=0;i<4;i++) 
  19.         { 
  20.                 printf("%s\n",str[i]); 
  21.         } 
  22.         printf("\n"); 
  23.         return 0; 


5、程序中条件语句中的double值的相等判断

double a,b;

.....

if( a == b )

这样不对,应该使用

[cpp] view plaincopyprint?
  1. #include <math.h> 
  2. ...... 
  3. if (fabs(a - b)<= epsilon * fabs(a)) 


6、C语言中取整的方法

我们知道float或double化为整型可以使用

(int)(a+0.5);但是这样对负数不合适。

应该使用这样的方法

(int)(x<0 ? x - 0.5 : x + 0.5);


7、C中数学方法获得 π 的值

可以自己定义也可以使用数学函数计算

4*atan(1.0) 或 acos(-1.0)


8、如何定义参数可变的函数

[cpp] view plaincopyprint?
  1. #include <stdio.h> 
  2. #include <stdlib.h> 
  3. #include <stdarg.h> 
  4.  
  5. void __print(constchar *fmt,...) 
  6.         va_list argp; 
  7.         printf("INFO: "); 
  8.         va_start(argp,fmt); 
  9.         vprintf(fmt,argp); 
  10.         va_end(argp); 
  11.         printf("\n"); 
  12. int main(int argc,char **argv) 
  13.         __print("%s","asddasda"); 
  14.         return 0; 

注意参数个数至少是一个。


9、为什么有的人判断语句的写法如下

if(0 == x)

而不是if( x==0 )

当然这两个都没有错误。这是由于防止"=="写成"="。

当把变量放在前面,“==”写成“=”编译器就会报错,不至于引发不应该出现的BUG


10、如何实现控制台的“转动的小棒”来显示程序的执行进度。

这里需要使用fflush(stdout);来清空输出缓冲区。

[cpp] view plaincopyprint?
  1. void print1(int ca) 
  2.         switch(ca) 
  3.         { 
  4.                 case 0:printf("\\");break
  5.                 case 1:printf("/");break
  6.                 case 2:printf("-");break
  7.         } 
  8. int main(int argc,char **argv) 
  9.         __print("%s","asddasda"); 
  10.         int i; 
  11.         for(i=0;i<10;i++) 
  12.         { 
  13.                 printf("\r"); 
  14.                 print1(i%3); 
  15.                 fflush(stdout); 
  16.                 sleep(1); 
  17.         } 
  18.         return 0;