zoukankan      html  css  js  c++  java
  • 读书笔记之:C/C++程序员实用大全—C/C++最佳编程指南

    这本书中列出了31章共1500个知识点,带有很多的例子。本书适合对C/C++有一些了解的程序员进行查缺补漏。因为这里边对知识点的讲解比较凌乱不是很条理,前面的内容有时就用到了后面内容,如果你不是了解的话,读起来就比较困难了。

    本书还有一个很大的特点是很多地方是针对Dos 平台的,我是使用的linux,所以有很多地方是不适合的。即便是对于windows 平台,有些地方可能也不适用了。因为这本书还是比较老的。有些不需要的地方可以跳过。关于C++的介绍,如果你是刚刚学C++话还是要先读《C++ Primer》,那本书比较条理,可以让你理清关系。了解各个知识点。

    书最后的关于Windows编程的部分我基本没有看,因为相对来说知识比较旧了,并且我是Linux平台的。

     第1章 C语言入门

    1. 许多C编译器把%i格式符等价于%d。最好使用%d,因为%i是一个比较陈旧的格式符,以后的编译器可能不支持它。

    %ld可以来显示长整型

    %e 科学计数法显示浮点数

    %g 根据实际情况自行选择使用%f还是%e来显示浮点数

    显示数值正负号:在格式符中紧跟%后添加一个+号即可。如%+d,%+f

    %05d 其中5用来表示显示数值时所采用的最少的字符数目,0表示使用0填充,

    %8.3f表示共至少8位,其中小数点后保留3位

    %-5d 左对齐

    2. 为了引导printf在八进制或十六进制前添加合适的前缀,可紧跟格式符号%后置入#。如:

    printf("value is %#x\n",value);

    3. 判断printf已经显示的字符数目

    当程序作复杂的屏幕格式化时,有时需要知道printf已经显示的字符数目,可以使用%n

    如:printf("abd%n 123456%n\n",&a,&b);

    执行完之后a=3,b=10

    printf的返回值是已经输出的字符总数

    4.ANSI设备驱动器

     

    第2章 宏与常量

    1. 预定义宏

    __FILE__ __LINE__ __DATE__ __TIME__

    __STDC__用来判断是否是ANSI C编译器

    2.改变与处理器行计数

    利用#line预处理来改变行号

    如:#line 100 "FILENAME.c" //表示当前行为100行,下面如果出现__LINE__的话,是从现在开始计数的

     

    第3章 字符串

    1. C中常用的字符处理函数

    #include <ctype.h>

    int isalnum(int c);

    int isalpha(int c);

    int iscntrl(int c);

    int isascii(int c);

    #include <ctype.h>

    int isdigit(int c);

    int isodigit(int c);

    int isxdigit(int c);

    #include <ctype.h>

    int isgraph(int c);

    int ispunct(int c);

    int isprint(char c);

    #include <ctype.h>

    int islower(int c);

    int isupper(int c);

    #include <ctype.h>

    int isblank(int c);

    int isspace(int c);

    ing iswhite(int c);

    #include <ctype.h>

    int tolower(int c);

    int toupper(int c);

     

    2. 常用的字符串处理函数

    #include <string.h>

    char* strcat(char*dest,const char*src);

    char* strncat(char*dest,const char*src,size_t n);

    #include <string.h>

    int strcmp(const char *s1,const char *s2);

    int strncmp(const char *s1,const char *s2,size_t n);

    #include <string.h>

    size_t strlen(const char*s);

    #include <string.h>

    char*strstr(const char*src,cosnt char*sub);

    char*strtok(char* str,const char*set);

    #include <string.h>

    char *strchr(const char*s,int c);

    char *strrchr(const char*s,int c);

    #include <stdlib.h>

    double strtod(const char *nptr, char **endptr);

    float strtof(const char *nptr, char **endptr);

    long double strtold(const char *nptr, char **endptr);

    #include <stdlib.h>

    double atof(const char*str);

    int atoi(const char*str);

    long atol(const char*str);

    long long atoll(const char*str);

    #include <string.h>

    char* strcpy(char*dest,const char*src);

    char* strncpy(char*dest,const char*src,size_t n);

    #include <string.h>

    int strcoll(const char*s1,const char*s2);

    size_t strxfrm(char *dest,const char*src,size_t len);

    #include <string.h>

    size_t strspn(const char*s,cosnt char*set);

    size_t strcspn(const char*s,cosnt char*set);

    char* strpbrk(const char*s,const char*set);

     

    第4章 函数

    1. 在C语言中,如果用户自定义的函数名称和库函数的名称是一样的,那么编译器一般会选择使用用户定义的函数。

    堆栈的基本目的就是用来支持函数调用的。函数调用的时候,编译器会将返回地址和参数压入堆栈。

    程序员将计算机用来压入和弹出堆栈所花费的时间成为函数的开销。

    2. volatile关键字

    3. 与堆栈相关:调用结构和基指针

    4. 支持参数个数可变的函数

    为了支持参数可变,在C中是使用宏va_arg,va_end和va_start(在头文件stdarg.h中定义)引导程序创建自己的支持参数个数可变的函数。实质上是宏每次从堆栈中取得参数,一直到程序获取最后一个参数。使用这些宏获取参数时,必须知道每个参数的类型。在printf这个最典型的不定参数个数函数中使用标识符(如%d,%s,%f)来匹配参数类型。

    可以使用类似printf中使用的格式符将参数类型传递给函数:

    result=add_values("%d %d %d",1,2,3);

     

    第5章 键盘操作

    1.

    #include <stdio.h>

    int fgetc(FILE *stream);

    char *fgets(char *s, int size, FILE *stream);

    int getc(FILE *stream);

    int getchar(void);

    char *gets(char *s);

    int ungetc(int c, FILE *stream);

    上面几个函数的关系:

    fgetc()是从stream中读取下一个字符串,然后返回,

    getc和fgetc是等价的,只不过它是用宏实现的。

    getchar()等价于getc(stdin)

     

    gets()是从stdin读入多个字符到缓冲s中,知道遇到行终结符,并且在s中使用'\0'代替终结符

    第6章 数学

    1. 获得浮点数的尾数和指数

    可以使用frexp函数来获得浮点数的指数和尾数

    #include <math.h>

    double frexp(double value,int *exponent);

    其中返回值是位数,第二个参数是指数

     

    类型float大小为4字节,即32位,内存中的存储方式如下:

    高地址<-------------------------------------->低地址

    | 符号位 | 指数 | 尾数 |

    | 1 bit | 8 bit | 23 bit |

    31<------>30<--------->22<---------------------->0

     

    类型double大小为8字节,即64位,内存布局如下:

    高地址<---------------------------------------->低地址

    | 符号位 | 指数 | 尾数 |

    | 1 bit | 11 bit | 52 bit |

    63<------>62<------------>51<--------------------->0

     

    2. 计算X*2E的结果

    可以使用ldexp函数来计算x*2e

    #include <math.h>

    double ldexp(double value,int exponent);

    3. 在文件stdlib.h提供了宏min和max

    4. 把浮点值分解成整数和小数部分

    使用modf函数来把浮点数分解成整数和小数部分。

    #include <math.h>

    double modf(double value,double *integer_part);

    5. #include <math.h>

    double pow(double value,double power);

    double pow10(int power);

     

    double log(double value);

    double log10(double value);

    6.生成随机数

    C中提供的生成随机数函数:rand和random,它们两个都返回整型随机数。

    #include <stdlib.h>

    int rand(void);

    int random(int ceiling);

    rand返回一个范围在0和RAND_MAX之间的随机整数。第二个函数random返回一个范围0与ceiling之间的随机数,ceiling规定了随机数的最大值,主调函数把它传递给random函数。

     

    第7章 文件、目录和磁盘

    1. FILE结构

    C中进行文件流操作的FILE是一个结构体,一般使用FILE*指针。

    通常是使用fopen函数返回一个FILE*指针。

    大体的FILE的结构格式如下:

    2. 使用低级和高级文件I/O

    其实高级I/O就是我们常用的基于流的文件功能。而所谓的低级文件I/O就是一些系统调用。上面所列出的函数都是一些系统调用,不同的系统的实现是不一样的。这儿其实就是一个"库函数与系统调用关系"的问题。

    3、已知文件流指针,获取对应的文件描述符

    int fileno(FILE *stream);

    主要应用:如果程序先前用fopen打开了一个文件,但是又想对其进行锁定操作,

    例如 int fcntl(int fildes, int command, struct flock *flock_structure)(注意:command为F_GETLK, F_SETLK, F_SETLKW中其中一者)

    或者 int lockf(int fd, int cmd, off_t len),就得先用fileno得到对应的文件描述符后再进行fcntl/lockf操作。

    4、已知文件描述符,获取对应的文件流指针

    FILE *fdopen(int fildes, const char *type);

    将一个文件流关联到一个打开的文件描述符

    fildes可以是open,dup, dup2, creat, pipe, socket等系统调用返回的结果。

    type指定打开的方式,同fopen的"r","w","a"等等。

    fdopen的打开方式受制于fildes的打开方式,例如:open时用O_RDONLY,那么fdopen就只能用"r"方式。

    主要应用:当你不得不只能打开文件号,但却想用fprintf,fscanf等流操作进行数据读写时,就再用fdopen一次便可。

    5. 重命名文件

    C中给出了函数rename可以来进行文件的重命名或移动

    #include <stdio.h>

    int rename(const char *old, const char *new);

    6. 删除文件

    C库函数中给出了remove函数来删除文件

    #include <stdio.h>

    int remove(const char *pathname);

    同时在unix操作系统中还提供了函数来删除文件

    #include <unistd.h>

    int unlink(const char *path);

    7. 判断程序如何访问文件

    C函数access检查指定文件是否存在,以及用户是否能按要求打开文件。

    这个一般是操作系统提供实现方式。

    8.将缓冲写入磁盘

    C中提供函数fflush将缓存中的数据写入到磁盘中去。

    #include <stdio.h>

    int fflush(FILE *stream);

    9. 获取文件流的文件句柄

    #include <stdio.h>

    int fileno(FILE *stream);

    10. 临时文件C接口

    如果在C程序中碰到文本处理,极有可能会涉及到临时文件的处理。

    在不同情境下,可能对临时文件接口有不同的需求。比如有时只是将临时文件作为临时的数据存储空间,无需与其它进程共享,这时可以直接使用tmpfile()函数。tmpfile()返回的是一个FILE *句柄,由tmpfile()创建的临时文件没有实际的文件名,这样处理的好处是,当程序结束时,文件不需要程序手动删除。

    但如果你需要与其它进程共享临时文件,或是需要以临时文件的文件名作为参数调用其它程序以传递数据,tmpfile()就不能胜任了,这时就需要用到mkstemp()。mkstemp()通过传入的模板字符串生成一个不存在的文件名,同时创建该文件,将文件句柄做为函数返回值返回,而文件名可以从被修改了的模板字符串中得到。

    以上两个函数算是比较现代的了,如果对于历史感兴趣,可以看看下面三个函数。

    mktemp()函数用于生成一个不存在的文件名。这个函数现在已经不提倡使用,在POSIX.1-2008中甚至已经将其删除了。从glibc mktemp(3)中可以了解到,不提倡使用mktemp()的主要原因是mktemp()只是生成一个当前不存在的文件名,而没有直接创建该文件。而如果需要创建这个文件,那么在mktemp()和creat()之间可能这个临时文件被其它进程创建,从而导致文件创建失败。

    tmpnam()函数有与mktemp()一样的问题,同时,当传入参数为NULL时,由于需要用到static变量,所以不是线程安全的。在POSIX.1-2008中已经不建议使用。

    tempnam()与tmpnam()相似,只是参数更多,可控性更高。同样,在POSIX.1-2008中已不建议使用。

    11. 每次读写一个字

    C中提供了函数getw和putw来读写一个字

    #include <stdio.h>

    int getw(FILE *stream);

    int putw(int w, FILE *stream);

     

    12. 读写结构体

    低级的read和write函数

    高级fread和fwrite函数都可以进行结构体读写

    13. 把文件句柄和文件流联系起来

    可以使用fdopen函数来晶文件句柄和文件流联系起来:

    #include <stdio.h>

    FILE *fdopen(int fd, const char *mode);

    14. 目录操作

    打开目录:opendir

    读取目录:readdir

    重置目录列表:rewinddir

     

    15. 按行读取和写文本

    使用函数fgets和fputs

     

    16. 为什么不能使用fgets和fputs来复制二进制文件

    因为在fgets函数在读取文本时,fgets把CTRL+Z(ASCII值为26)当作文件结尾。因为二进制文件中很可能多次出现数值26,fgets将在第一次遇到26时就结束拷贝过程。所以要想可靠的拷贝二进制文件的话,必须使用C 的低级I/O函数。

    17. 判断文件结尾

    当fgets函数遇到文件结尾时,它返回NULL,同样当fgetc遇到文件结尾时返回EOF。所以在程序进行某些特定操作之前,很有必要判断文件指针是否处于文件尾端。一般使用函数feof。

    #include <stdio.h>

    int feof(FILE *stream);

    18. 获取文件句柄信息

    #include <sys/types.h>

    #include <sys/stat.h>

    #include <unistd.h>

    int stat(const char *path, struct stat *buf);

    int fstat(int fd, struct stat *buf);

    int lstat(const char *path, struct stat *buf);

    stat结构体

    struct stat {

    dev_t st_dev; /* ID of device containing file */

    ino_t st_ino; /* inode number */

    mode_t st_mode; /* protection */

    nlink_t st_nlink; /* number of hard links */

    uid_t st_uid; /* user ID of owner */

    gid_t st_gid; /* group ID of owner */

    dev_t st_rdev; /* device ID (if special file) */

    off_t st_size; /* total size, in bytes */

    blksize_t st_blksize; /* blocksize for file system I/O */

    blkcnt_t st_blocks; /* number of 512B blocks allocated */

    time_t st_atime; /* time of last access */

    time_t st_mtime; /* time of last modification */

    time_t st_ctime; /* time of last status change */

    };

     

     

  • 相关阅读:
    python--向钉钉群发送消息(亲测可用)
    python--注册钉钉回调事件(亲测可用)
    Gradle
    SpringBoot 中thymeleaf模板引擎的使用
    SpringBoot对静态资源的映射规则
    SpringBoot的日志使用
    rsync实现文件同步
    python学习: 优秀Python学习资源收集汇总--转
    Python高级特性: 12步轻松搞定Python装饰器
    Python常见问题
  • 原文地址:https://www.cnblogs.com/xkfz007/p/2425612.html
Copyright © 2011-2022 走看看