C程序设计语言(第二版)-读书笔记

The C Programming Language

1. 设计一个程序,作用为无限字符输出:

int c;

printf(“Please in put the char …\n”);

//getchar接受字符输入并存放到缓冲区,逐个返回给c

c=getchar();

while(c!=EOF)

{

putchar(c);

c=getchar();

}

2. 设计一个程序,统计字符数目:

printf(“Please input char …/n”);

long nc=0;

while(getchar()!=EOF)

{

++nc;

}

printf(“%d\n”,nc);

3. 设计一个程序,统计单词的个数:

#define IN 1

#define OUT 2

//c表示charnc表示出现字符的数目,nw表示单词数目,nl表示段落数

int c, nc, nw, nl, state;

state = OUT;

nl = nw = nc =0;

 

while(c=getchar()!=EOF)

{

++nc;

if(c==’\n’)

{

    ++nl;

}

if(c==’ ’||c==’\n’||c==’\t’)

{

    state=OUT;

}

else if(state==OUT)

{

    state = IN;

    ++nw;

}

printf(“字符数:%d,单词数:%d,段落数:%d”,nc,nw,nl);

}

4. C语言中的数据类型:

|-char1byte)、int4byte)、float4byte)、double8byte)、bool(1byte)

|-整形两种限定符:

|-shortlong,用于限定整形intint可以不写。short int2byte)、long int4byte)。

|-unsignedsigned用于限定是否含有符号,可用于charint。默认为signed

5. 判断闰年:

int year=0;

scanf(“%d”,&year);

if(((year%4==0)&&(year%100)!=0)||year%400==0)

{

    printf(“This year %d is leap year”,year);

}

else

{

    …

}

6. enum#define定义常量的对比

|-enum定义枚举,#define定义宏,enum定义常量的值可以自动生成。

|-enum能够用于调试,而define定义的常量编译时不检查,只是对其进行字符的替换。

7. 常用函数自定义实现:

//strlen

int strlen(char s[])

{

int i=0;

while(s[i]!=’\0’)

{

    ++i;

}

return i;

}

//或者

int strlen(char *s)

{

int n;

for(n=0;*s!=’\0’;s++)

{

    n++;

}

return n;

}

//atoi

int atoi(char s[])

{

int n=0;

for(int i=0;s[i]>=’0’&&s[i]<=’9’;++i)

{

    n=(s[i]-‘0’)+10*n;

}

}

//lower

int lower(int c)

{

if(c>=’A’&&c<=’Z’)

{

    return c+(‘a’-‘A’)

}

else

    return c;

}

//strcat

void strcat(char s[], char t[])

{

int i=0;

int j=0;

while(s[i]!='\0')

{

++i;

}

while ((s[i++]=t[j++])!='\0')

{

}

}

//删除字符

void squeeze(char s[], int c)

{

    int j,j;

for(int i=j=0;s[i]!=’\0’;i++)

{

    if(s[i]!=c)

    {

        s[j++]=s[i];

}

s[j]=’\0’;

}

}

//trim,简化版,用于删除字符串尾部空格,理解break的使用

int trim(char s[])

{

int n;

for(n=strlen(s)-1;n>=0;n--)\

{

    if(s[n]!=’ ’&&s[n]!=’\t’&&s[n]!=’\n’)

    {

    break;

}

s[n+1]=’\0’;

return n;

}

}

//strcpy

void strcpy(char *s,char *t)

{

while((*s++==*t++)!=’\0’)

{}

}

//strcmp

int strcmp()

{

for(;*s==*t;s++,t++)

{

    if(*s==’\0’)

    {

        return 0;

}

return *s - *t);

}

}

8. 在进行复制和函数参数传递时,低精度的可以向高精度的进行自动转换。例如接受float参数的函数乐意接受doulbe类型的参数。高精度要转换成低精度就要进行强制类型转换。

9. c语言中,字符数组和字符串很容易引起混淆。c语言中的字符串被当做成字符数组来处理。字符串的定义有两种:

char * c = “Hello”;或者char s[] =“hello”;字符串在字符数组的结尾加上’\0’,因此对于char s2[] = {‘h’,’e’,’l’,’l’,’o’};sizeof(s2)=5,而sizeof(s)=6

10. 算法:

//冒泡

void bubble(int s[],int n)

{

int tmp=0;

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

{

for (int j=0;j<n-i;j++)

{

if (s[j]>s[j+1])

{

tmp = s[j];

s[j] = s[j+1];

s[j+1] = tmp;

}

}

}

}

//折半查找,x是要查找的数字,v是已排序的数组,n是数组长度

int binsearch(int x,int v[],int n)

{

int low,high,mid;

low = 0;

high = n-1;

while (low<=high)

{

mid = (low + high)/2;

if(x<v[mid])

{

high = mid-1;

}

else if(x>v[mid])

{

low = mid +1;

}

else

return mid;

}

}

10. 对于extern修饰符,extern i;表示变量声明,并未生成对象,用于说明i为全局变量,可在不同的文件中调用。

11. 对于static修饰符,在c语言中,使用static声明变量为文件中访问,文件外不能访问该static变量。

12. 寄存器变量使用register表示,其访问速度快,但寄存器地址不能访问。

13. 预处理器:

|-#include<>系统默认搜索路径,””源文件路径+默认路径

|-#define:编译时进行字符替换

|-优点:节省调用开销

|-缺点:重复计算产生副作用

|-#ifndef…#define…#endif:条件包含

14. 关于*++(--)的结合性,先++*

|-*p++ ==> p++; *p;

|-(*p)++ ==> p指向的对象值+1;

例如int s[]={2,3};int *p = s;printf(“%d,”*p++);结果输出的是2,而不是3,因为是先引用在++

15. ++ii++:在VC编译环境下,如果在一个计算表达式中,首先计算++i,然后看有几个i++,完成该表达式后,有几个i++i就自增几。例如:int i=3,j; j=(i++) + (i++) + (++i);printf(“i=%d,j=%d”,i,j);编译输出为612

16. VC的编译器中,printf函数是自右向左执行的。例如,printf(“%d,%d”,i,i+1);首先计算i+1,然后再输出i

17. 使用宏编写比较两个数的大小

#define max(A,B) ((A)>(B)?(A) : (B))

注意一定要加括号,用于放回宏的副作用。

18. 对于32位的机器,指针永远占据4byte的长度,即sizeof(指针)=4

19. 数组名就是指向数组指针的首地址,与指向数组的指针相比(例如int a[]={2,3};int *p = a;),a不可以a++,但是p可以p++。在函数定义中,char *s < == > char s[].

20. *p++=value;理解为入栈,value放到p原先的位置,然后p++

val=*--p;理解为出栈,p地址首先减一,然后取值。

21. 命令行参数

#include <stdio.h>

void main(int argc,char* argv[])//或者int argc, char**argv

{

int i;

for(i=1;i<argc;i++)

{

    printf(“%s”,argv[i]);

}

}

22. 指向函数的指针

//函数的定义并声明

void printf()

{

    printf(“Hello”);

}

 

void (*f)();    //指向函数的指针声明

f = printf();    //赋值、初始化

(*f)();        //调用

int (*fun) (par):指向函数的指针,返回类型为int

int* fun(par):函数,返回类型为int *

23. union:单块存储区中管理不同类型的数据,其中所有元素相对于union基地地址的偏移为0

24. void* malloc(size_t n):返回n字节大小的未初始化的空间

void* calloc(size_t n,size_t size):返回能够容纳nsize大小的空间

 

PS:

1.###分别用与转换字符串和连接字符串。

#define TOSTRING(n) #n

#define CONTACT(n,m)n##m

2.i++++i效率问题:

对于原生数据,效率一样;对于自定义类型,i++返回的是临时变量(需要使用自增之后的值),++i返回的是引用(使用自增之后的值),效率高。

3.四字节对齐:

#define ALIGN4(n) (((n)+3)&(~3))

4.#pragma

#pragma message("Hello") 编译时输出信息

#pragma once 确保该文件被编译一次

5.#undef用于注销之前定义的宏变量

6.长度为0的数组:

也成为柔性数组,多用于占位符。不增加类型的大小(因此使用柔性数组而不用char*(四个字节))。这样一次malloc便能申请带有缓冲区的一块内存,并且是连续的内存。柔性数组可以按照数组的访问方式进行读取。如下:

typedef struct strZeroTest

{

    int num;

    char position[0];

} ZeroTest;

 

int main()

{

    ZeroTest *pzt = (ZeroTest*)malloc(sizeof(ZeroTest)+10);

    for (int i = 0; i < 10; ++i)

    {

        pzt->position[i] = i;

    }

    return 0;

}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值