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

原创作品,转载请标明http://blog.csdn.net/yming0221/article/details/7247075

更多查看

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

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

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

1、scanf()输入注意

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

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

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


2、scanf()的缓冲区问题

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

例如下面的例子

#include <stdio.h>

int main(int argc,char **argv)
{       
        char a;
        while(1)
        {
                scanf("%c",&a);
                printf("a=%c\n",a);
        }
        return 0;
}

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


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

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

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


3、printf()和sprintf()函数

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

如下例子:

int main(int argc,char **argv)
{
        char a[11]={0};
        const char *p="12345678901234";
        sprintf(a,"%s",p);
        printf("a= %s\n",a);

        return 0;
}

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


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

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

例如

int main(int argc,char **argv)
{
        char a[11]={0};
        const char *p="12345678901234";
        snprintf(a,sizeof(a),"%s",p);
        printf("a= %s\n",a);

        return 0;
}



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

使用方法

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

#include <stdlib.h>

#define MY_TYPE int
static int cmp(const void *a,const void *b)
{
        return *(MY_TYPE *)a > *(MY_TYPE *)b ? 1 : -1;
}
int va[10]={6,3,2,4,7,1,9,8,5,0};

int main(int argc,char **argv)
{
        int i;
        for(i=0;i<10;i++)
        {
                printf("%d ",va[i]);
        }
        printf("\n");
        qsort(va,10,sizeof(va[0]),cmp);
        for(i=0;i<10;i++)
        {
                printf("%d ",va[i]);
        }
        printf("\n");
        return 0;
}

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

#include <stdlib.h>

#define MY_TYPE _st
typedef struct _st
{
        int va;
        char c;
};
struct _st st[10];

static int cmp(const void *a,const void *b)
{
        return (*(struct MY_TYPE *)a).va > (*(struct MY_TYPE *)b).va ? 1 : -1;
}
int main(int argc,char **argv)
{
        int i;
        for(i=0;i<10;i++)
        {
                st[i].va=10-i;
        }
        printf("\n");
        qsort(st,10,sizeof(st[0]),cmp);
        for(i=0;i<10;i++)
        {
                printf("%d ",st[i].va);
        }
        printf("\n");
        return 0;
}

比较函数也可以写成如下形式

static int cmp(const void *a,const void *b)
{
        return ((struct MY_TYPE *)a)->va > ((struct MY_TYPE *)b)->va ? 1 : -1;
}


*对结构体多级排序

int cmp( const void *a , const void *b ) 
{ 
struct In *c = (In *)a; 
struct In *d = (In *)b; 
if(c->x != d->x) return c->x - d->x; 
else return d->y - c->y; 
} 
*对字符串数组排序
#include <stdlib.h>
#define LEN 30+1

char str[4][LEN];

static int cmp(const void *a,const void *b)
{
        return strcmp((char *)a,(char *)b);
}
int main(int argc,char **argv)
{
        int i;
        strcpy(str[0],"abaa");
        strcpy(str[1],"baaa");
        strcpy(str[2],"baaaa");
        strcpy(str[3],"aasasasaa");


        printf("\n");
        qsort(str,4,sizeof(str[0]),cmp);
        for(i=0;i<4;i++)
        {
                printf("%s\n",str[i]);
        }
        printf("\n");
        return 0;
}


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

double a,b;

.....

if( a == b )

这样不对,应该使用

#include <math.h>
......
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、如何定义参数可变的函数

#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>

void __print(const char *fmt,...)
{
        va_list argp;
        printf("INFO: ");
        va_start(argp,fmt);
        vprintf(fmt,argp);
        va_end(argp);
        printf("\n");
}
int main(int argc,char **argv)
{
        __print("%s","asddasda");
        return 0;
}

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


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

if(0 == x)

而不是if( x==0 )

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

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


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

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

void print1(int ca)
{
        switch(ca)
        {
                case 0:printf("\\");break;
                case 1:printf("/");break;
                case 2:printf("-");break;
        }
}
int main(int argc,char **argv)
{
        __print("%s","asddasda");
        int i;
        for(i=0;i<10;i++)
        {
                printf("\r");
                print1(i%3);
                fflush(stdout);
                sleep(1);
        }
        return 0;
}



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
C语言编程注意事项 1. 每个程序中一定包含main()函数, 尽管C语言中对函数命名没有限制。 2. printf函数永远不会自动换行, 只能用\n来实现, 回车键进行的换行在编译中会出现错误信息。 3. 在vs2008等平台中编译、测试要加 system("pause"); 来暂停dos自动退出引起的printf无法显示。 4. 所有自定义变量必须声明才能使用。 5. 每行一般只写一条语句, 在运算符两边加一个空格, 便于阅读。 6. 整数除法将会自动舍位, 不进行舍五入的操作。 7. for(初始化部分;条件部分;增长部分) 比while 更适用于初始化和增长步长都是单条语句的情况。 8. 使用 #define 名字替换文本对部分"幻数" 赋予意义便于阅读 #define结尾无需;号来结束。 9. EOF(end of file)表示没有字符输入时定义在stdio.h 头文件中 EOF不等于\n 换行等。 10. 由于!= 的优先级大于 = ,因此如果对判断中存在变量赋值时 应对赋值加() 例如: while((c = getchar()) != EOF)。 11. getchar() 用于用户输入直至键入回车键。 12. 变量名以字母和数字组成, (下划线"_"被默认为字符, 以下划线为首写字母的为库类变量名), 变量常以小写字母开头,内部变量名前31位有效, 外部变量名至少前6位保持唯一性。 13.在C语言中是区分字母大小写的。 14. 一个字符常量为一个整数, 用''单引号括起来。例如: '0' 为48, 它与0没有任何关系。 15. ANSI C语言的转义符: \a 响铃符; \b 回退符; \f 换页符; \n 换行符; \r 回车符; \t 横向制表符 ; \v 纵向制表符; \\ 反斜杠; \? 问号; \' 单引号; \" 双引号; \ooo 八进制数; \xhh 十六进制数; '\0' 表示0, 即(null)。 16. 'x'与"x"的区别: 'x'表示一个整数, 字母x在其字符集中对应的数值, "x"表示包含一个字符x 以及一个结束符'\0'。 17. const在声明变量中起限制作用, 该限定变量的值不能被修改。 18. %运算符不能应用于float或double类型。 19. char类型转换为int型时, 因为无法判断它是signed还是unsigned,这样其结果有可能为负数, 所以转换时尽量指定signed和unsigned限制符。 20. ++i与i++ 的不同之处: ++i是先 +1再使用i, i++ 是先使用i再 +1。 21. 三元运算符"?:" 第一个表达式的括号不是必须的, 但是由于三元表达式的优先级非常低, 因此我们还是将第一个表达式用()括起来以便于阅读和理解。 22. C语言中可以使用递归 (即函数调用自身函数), 这样做并不节省储存空间也不加快执行速度, 只是使程序紧凑便于理解。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值