c语言杂谈1

一、数据类型

一些常见的数据类型在这里我也就不多做介绍了。

1._Bool类型

这部分我想先来说说_Bool类型。_Bool类型是由C99引入的,用于表示布尔值,即逻辑true(真)与false(假)。因为C用值1表示true,用值0表示false,所以_Bool类型实际上也是一种整数类型。只是原则上它仅仅需要1位来进行存储。

而在一般地,cwhileif等判断语句中,只有0被认为是假,任何非零的值都认为是真。

另外C99还提供一个stdbool.h的头文件。包含这个头文件可以使用bool来代替_Bool,并把truefalse定义成值10的符号常量。

如果系统还不支持_Bool类型,则可以使用int来代替_Bool

二、可移植类型:inttypes.h

C99提供了一个可选的名字集合,以确切地描述有关信息。例如int16_t表示一个16位有符号整数类型,uint32_t表示一个32位无符号整数类型。

要使用这些名字对于程序有效,应当在程序中包含inttypes.h头文件。因为,与int不同,uint32_t不是关键字。

三、ctype.h系列字符函数

ANSI C有一系列标准的函数可以用来分析字符;ctype.h头文件包含了这些函数的原型。这些函数接受一个字符作为参数,如果该字符属于某特定的种类则返回一个非零值。

例:

#include <stdio.h>

#include <ctype.h>

 

int main()

{

       char ch;

      

       while((ch = getchar()) != '/n')

       {

              if(isalpha(ch))

                     putchar(ch + 1);

              else

                     putchar(ch);

       }

       putchar(ch);

      

       return 0; 

}

运行结果:

 

 

 

 

 

注意:映射函数并不改变原始的参数,它们只返回改变后的值。也就是说,下列语句是不改变ch的值,

                     tolowerch),但可以 ch = tolowerch

关于一些其他函数可以查阅相关手册,本人推荐C-FreeC/C++语言参考帮助文档。

四、系统定义的明显常量

C头文件limits.hfloat.h分贝提供有关整数类型的大小限制的详细信息。每个文件都定义了一系列应用您的实现的明显常量。

五、sizeof运算符和size_t类型

size_t不是一个新类型。相反,与可移植类型相同,使根据标准类型定义的。

六、getchar()

1.使用输入缓冲:

首先看个例子:

#include <stdio.h>

int main( )

{

    int guess = 1;

 

    printf("Pick an integer from 1 to 100. I will try to guess ");

    printf("it./nRespond with a y if my guess is right and with");

    printf("/nan n if it is wrong./n");

    printf("Uh...is your number %d?/n", guess);

    while (getchar() != 'y')      /* get response, compare to y */

        printf("Well, then, is it %d?/n", ++guess);

    printf("I knew I could do it!/n");

 

    return 0;

}

运行结果:


 

 

 

 

 

 

注意该程序在每次您输入n时都进行两次猜测。这中间所发生的事情是改程序读去n响应并把它看作是您对1的否定,然后读取换行字符并把它看作是您对2的否定。

一种解决方法是使用while循环来丢弃输入行的其余部分,包括换行符。这种方法还能够把诸如nono way这样的响应得简单的n响应一样看待。即在循环跳出前加虾面的语句:

while(getchar () != ‘/n’)

{

       continue;

}

 

2.混合输入数字和字符

getchar()读取每个字符,包括空格、制表符和换行符。而scanf()在读取数字时则跳过空格、制表符和换行符。

void display(char cr, int lines, int width);

int main( )

{

    int ch;             /* character to be printed    */

    int rows, cols;     /* number of rows and columns */

    printf("Enter a character and two integers:/n");

    while ((ch = getchar()) != '/n')

    {

        scanf("%d %d", &rows, &cols);

        display(ch, rows, cols);

        printf("Enter another character and two integers;/n");

        printf("Enter a newline to quit./n");

    }

    printf("Bye./n");

    

    return 0;

}

 

void display(char cr, int lines, int width)

{

    int row, col;

 

    for (row = 1; row <= lines; row++)

    {

        for (col = 1; col <= width; col++)

            putchar(cr);

        putchar('/n');  /* end line and start a new one */

    }

}

运行结果,这里就不给出了,可以自己运行一下。顺便提到一句,以上程序都是在C-Free4.1mingw2.95下编译,调试的。

这个程序的问题还是出在换行符上。因为scanf()函数将该换行符留在输入队列中。与scanf()不同,getchar()并不跳过换行符。

 

七、复合文字

C99新增了复合文字(compound literal)。文字是非符号常量。开发C99标准委员会认为,如果有能够表示数足和结构内容的复合文字,那么在编写程序时将更为方便。

例:

(int [2]){10, 20};          //一个复合文字

(int [ ]){10, 20, 40};      //也是一个复合文字

由于复合文字没有名称,因此不可能在一个语句中创建他们,然后再另一个语句中使用。而是必须在创建他们的同时通过某种方法来使用他们,一种方法是使用指针来保存其位置。

int *pt1

pt1 = (int [2]){10, 20};

请注意这个文字常量被标示为一个int数组。与数组名相同,这个常量同时代表首元素的地址。因此可以用它给一个指向int的指针赋值。随后就可以使用这个指针。

例:

#include <stdio.h>

#define COLS 4

int sum2d(int ar[][COLS], int rows);

int sum(int ar[], int n);

 

int main(void)

{

     int total1, total2, total3;

     int * pt1;

     int (*pt2)[COLS];

 

     pt1 = (int [2]) {10, 20};

     pt2 = (int [2][COLS]) { {1,2,3,-9}, {4,5,6,-8} };

 

     total1 = sum(pt1, 2);

     total2 = sum2d(pt2, 2);

     total3 = sum((int []){4,4,4,5,5,5}, 6);

     printf("total1 = %d/n", total1);

     printf("total2 = %d/n", total2);

     printf("total3 = %d/n", total3);

    

     return 0;

}

 

int sum(int ar[], int n)

{

    int i;

    int total = 0;

 

    for( i = 0; i < n; i++)

        total += ar[i];

       

    return total;

}

 

int sum2d(int ar[][COLS], int rows)

{

    int r;

    int c;

    int tot = 0;

 

    for (r = 0; r < rows; r++)

        for (c = 0; c < COLS; c++)

            tot += ar[r][c];

           

    return tot;

}

运行结果:

   

 

八、snprintf( )引发的一些讨论

许多现有的代码调用的是sprintf,但sprintf不检查目标缓冲区是否溢出。相反,snprintf要求其第二个参数指定目标缓冲区的大小,因此可确保缓冲区不溢出。

snprintf相对较晚才加到ANSI C标准,在称为ISO C99的版本中引入。几乎所有厂商都把它作为标准C函数库德一部分加以提供,而且含有许多免费的版本可用。

值得注意的是,许多网络入侵是由黑客通过发送数据,导致服务器对sprintf的调用溢出其缓冲区而发生的。你必须小心使用的函数还有getsstractstrcpy,通常应调用fgetsstrncatstrncpy函数代替。更好的选择是使用后来才引入的函数strlcatstrlcpy,它们确保结果是终结得到的字符串。

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值