C和指针day5

101 阅读10分钟

第十五章 输入/输出函数

错误报告

perror void perror (char const *message)//打印错误信息

终止执行

exit void exit(int status)//在stdlib.h中定义 常见的预定义符号: EXIT_SUCCESS 和 EXIT_FAILURE

ANSI I/O 概念

  • 绝大多数流是完全缓冲的,从缓冲区来回读写,缓冲区只有写满的时候才会被输出。 如果想printf()之后立即输出则用fflush();

    • 文本流

      在MS-DOS系统中,文本文件约定以一个回车符和一个换行符结尾 在UNIX中,只用一个换行符结尾

    • 二进制流

      不会改变文件的内容

  • 文件

    FILE结构,每个ANSI C 程序运行时候会有三个流: stdin stdout stderr

  • 标准IO常量

    一个程序能打开多少个文件,和编译器有关,FOPEN_MAX个文件。

流IO总览

声明指针变量FILE* fopen 初始化 FILE 读取或者写入 fclose 关闭流

  • 执行字符、文本行、二进制IO函数

    字符: gerchar putchar 读取(写入)单个字符 文本行: gets scanf puts printf 文本行未格式化和格式化输入输出 二进制数据:fread fwrite 读取(写入)二进制数据

打开流

FILE *fopen(char const *name,char const *mode) 参数二: r 读取 w 写入 a 追加 a+ 允许读和写操作

FILE* file1;
file1 = fopen("123.txt", "w");
if (file1 == NULL)
{
	perror("data3");
	exit(EXIT_FAILURE);
}
fclose(file1);
FILE* file2;
file2 = freopen("123.txt", "w", file1);
if (file2 == NULL)
{
	perror("data4");
	exit(EXIT_FAILURE);
}

关闭流

int fclose(FILE *f) 执行成功返回零值,否则返回EOF

字符IO

int fgetc(FILE *stream); int getc(FILE *stream); int getchar(void); 如果流不存在更多的字符,则返回EOF(int类型) int fputc(int ,FILE *stream); int putc(int ,FILE *stream); int putchar(int character); 写入失败也会EOF

撤销字符IO

int ungetc(int character,FILE *stream)

while((ch = getchar())!=EOF && isdigit(ch)){
	value *= 10;
	value += ch - '0';
}
ungetc(ch,stdin);//将最后一次读取的非字符退还给stdin

未格式化的行IO

原型: char *fgets(char *buffer,int size,FILE *stream)//NUL添加到尾部 读取完毕则返回NULL 否则返回第一个参数 char *gets(char *buffer);

int fputs(char const *buffer,FILE *stream)//如果不包含换行符则不会自己添加换行符 int puts (char const *buffer)

格式化的行IO

  • scanf家族

    int fscanf(FILE *stream,char const *format,...) int scanf(char const *format,...) int sscanf(char const *string,char const *format,...); fscanf 从流中读取 scanf 从stdin读取 sscanf 从参数1读取

    • 限定符

      d、i、n:"h"short,"l"long o、u、x:"h"unsigned short,"l" unsigned long e、f、g:"l"double,"L"long double

    • 格式码

  • printf家族

    int fprintf(FILE *stream,char const *format,...); int printf(char const *format,...); int sprintf(char *buffer,char const *format,...);//输入到buffer中

  • 二进制IO

    size_t fread (void *buffer,size_t size,size_t count ,FILE *stream) size_t fwrite(void *buffer,size_t size,size_t count ,FILE *stream) 可以避免在转换时候出现精度损失

  • 刷新和定位函数

    int fflush (FILE *stream)//刷新流 long ftell(FILE *stream)//返回当前位置 int fseek(FILE *stream,long offset,int from)//定位位置 参数3:SEEK_SET SEEK_CUR SEEK_END

    void rewind(FILE *stream) 将读写指针回到初始位置 int fgetpos(FILE *stream,fpos_t *position) 此函数的position参数保存了当前stream的位置 int fsetpos(FILE *stream,fpos_t const *position) 此函数的position参数设置stream位置

  • 改变缓冲方式

    可以用于对缓冲方式进行修改,只有当指定的流被打开且没有执行任何操作前设置。 void setbuf(FILE *stream,char *buf); int setvbuf(FILE *stream,char *buf,int mode,size_t size); 最好不要使用自动数组,使用malloc,使用BUFSIZ大小或者整数倍 参数三: _IOFBF 完全缓冲流 _IONBF不缓冲流 _IOLBF行缓冲流

  • 流错误函数

    int feof(FILE *stream)//流处于结尾的时候返回真 int ferror(FILE *stream)//写入错误的时候返回真 void clearerr(FILE *stream)//对指定流的错误标志进行重置

  • 临时文件

    FILE *rmpfile(void) 以wb+的方式创建一个文件,并且关闭程序时候删除该文件 char *tmpnam(char *name) 如果参数为NULL则返回静态数组的指针说明被创建的文件名

  • 文件操作函数

    int remove(char const *filename) int rename(char const *oldname,char const *newname) 两个函数都是,成功返回0,失败返回非零值

第十六章 标准函数库

整型函数

  • 算数<stdlib.h>

    • int abs (int value)

      返回绝对值

    • long labs (long value)

      返回绝对值,针对长整型

    • div_t div(int numbertor,int denominator)

      参数1是分子,参数2是分母,返回商和余数 div_t->int quot //商 div_t->int rem//余数

    • ldiv_t ldiv(long numbertor,long denominator)

  • 随机数<stdlib.h>

    int rand(void); void srand(unsigned int sedd); 一般先srand,重置随机数,然后调用rand srand((unsigned int )time(NULL))//需要添加 time.h

  • 字符串转换<stdlib.h>

    • int atoi(char const *string)

      int a = atoi(" 1f22");//此时的a 值是1

    • long int atol(char const *string)

    • long int strtol(char const *string,char **unused,int base)

      参数1 -- 要转换为长整数的字符串。 参数2 -- 对类型为 char* 的对象的引用,其值由函数设置为 参数1 中数值后的下一个字符。 参数3 -- 基数,必须介于 2 和 36(包含)之间,或者是特殊值 0。如果设置为12则有效数字为0-C

    • unsigned long int strtoul

浮点型函数

  • 三角函数

    • double sin(double angle)
    • double cos(double angle)
    • double tan(double angle)
    • double asin(double angle)
    • double acos(double angle)
    • double atan(double angle)
    • double atan2(double x,double y)
  • 双曲函数

    • double sinh(double angle)
    • double cosh(double angle)
    • double tanh(double angle)
  • 对数和指数函数

    • double exp(double x)
    • double log(double x)
    • double log10(double x)
  • 浮点表示形式

    • double frexp(double value,int *exponent)

    • double ldexp(double fractione ,int exponent)

    • double modf(double value,double *ipart)

      浮点数的整数部分和小数部分分离: 整数部分存储在第二个参数中 小数直接返回

    • double pow(double x,double y)
    • double sqrt(double x)
  • 底数,顶数,绝对值和余数

    • double floor(double x)

    • double ceil(double x)

    • double fabs(double x)

    • double fmod(double x, double y)

      x/y所得到的余数

  • 字符串转换

    • double atof(char const*string)
    • double strtod(char const *string,char **unused)

日期和时间函数

  • 处理器时间

    • clock_t clock(void)

      CLOCKS_PER_SEC 返回值除上面的宏才能得出秒

  • 当天时间

    • time_t time(time_t *returned_value)

      不能用来计算秒数

  • 日期和时间转换

    • char *ctime(time_t const *time_value)

      得到的字符串格式: Sun Jul 4 04:02:48 1976\n\0

      也可以用: asctime (localtime( time_t time_value))来实现

    • double difftime(time_t timel,time_t time2)

      计算两个时间的时间差,结果是秒

    • struct tm *gmtime(time_t const *time_value);

    • struct tm *localtime(time_t const *time_value);

    • struct tm

      int tm_sec; // seconds after the minute - [0, 60] including leap second int tm_min; // minutes after the hour - [0, 59] int tm_hour; // hours since midnight - [0, 23] int tm_mday; // day of the month - [1, 31] int tm_mon; // months since January - [0, 11] int tm_year; // years since 1900 int tm_wday; // days since Sunday - [0, 6] int tm_yday; // days since January 1 - [0, 365] int tm_isdst; // daylight savings time flag

    • char *asctime(struct tm const *tm_ptr)

    • size_t strftime(char *string,size_t maxsize,char const *format,struct tm const *tm_ptr)

    • time_t mktime(struct tm *tm_ptr)

      把tm转换成 time_t

非本地跳转<setjmp.h>

setjmp和longjmp函数提供了类似goto语句,但是不局限于函数。常用于深层嵌套的函数调用链。

setjmp(restart);然后别处的 longjmp(restart,value);此时回去之后,在setjmp()会接收到value去判断运行哪个操作

  • int setjmp(jmp_buf state)
  • void longjmp(jmp_buf state,int value)

信号

SIGABRT 程序异常终止。 SIGFPE 算术运算出错,如除数为 0 或溢出。 SIGILL 非法函数映象,如非法指令。 SIGINT 中断信号,如 ctrl-C。 SIGSEGV 非法访问存储器,如访问不存在的内存单元。 SIGTERM 发送给本程序的终止请求信号。

  • int raise(int sig)

    信号发生器,发生sig信号 程序默认执行动作 程序忽略 程序执行自定义的动作

  • void (*signal(int sig, void (*func)(int)))(int)

    先省略返回类型 signal(int sig,void (* handler)(int)) 参数1是信号值 参数2是回调函数

    现在省略参数 void (*signal())(int)

  • 案例

    int main() { signal(SIGINT, sighandler);

    while(1) { printf("开始休眠一秒钟...\n"); sleep(1); }

    return(0); }

    void sighandler(int signum) { printf("捕获信号 %d,跳出...\n", signum); exit(1); }

打印可变参数列表<stdarg.h>

  • int vprintf(char const *format,va_list arg)
  • int vfprintf(FILE *stream,char const *format,va_list arg);
  • int vsprintf(char *buffer,char const *format,va_list arg);

执行环境

  • 终止执行

    • void abort(void)

      触发 SIGABRT 信号 可以忽略此信号

    • void atexit(void (func)(void))

      将一些函数注册为退出函数,执行exit()或者return的时候会执行此函数作为收尾

    • void exit(int status)

  • 断言

    • void assert(int expression)

      assert(value != NULL)//如果为假则会输出错误信息 Assertion failed :value != NULL,file.c line 274

      #define NDEBUG 此宏可以忽略所有断言判断

  • 环境

    • char *getenv(char const *name)

      查找编译器定义的名字/值

  • 执行系统命令

    • void system(char const *command);
  • 排序和查找

    • void qsort(void *base, size_t nitems, size_t size, int (*compar)(const void , const void))

      base -- 指向要排序的数组的第一个元素的指针。 nitems -- 由 base 指向的数组中元素的个数。 size -- 数组中每个元素的大小,以字节为单位。 compar -- 用来比较两个元素的函数。

    • void *bsearch(const void *key, const void *base, size_t nitems, size_t size, int (*compar)(const void *, const void *))

      key -- 指向要查找的元素的指针,类型转换为 void*。 base -- 指向进行查找的数组的第一个对象的指针,类型转换为 void*。 nitems -- base 所指向的数组中元素的个数。 size -- 数组中每个元素的大小,以字节为单位。 compar -- 用来比较两个元素的函数。 返回找到元素的void *类型的地址

locale

LC_ALL 设置下面的所有选项。 LC_COLLATE 影响 strcoll 和 strxfrm 函数。 LC_CTYPE 影响所有字符函数。 LC_MONETARY 影响 localeconv 函数提供的货币信息。 LC_NUMERIC 影响 localeconv 函数提供的小数点格式化和信息。 LC_TIME 影响 strftime 函数。

  • 数值和货币格式

    • struct lconv *localeconv(void)

      数值和货币的书写格式每个地方都不同,

  • lconv

    • decimal_point 用于非货币值的小数点字符。
    • thousands_sep 用于非货币值的千位分隔符。
    • grouping 一个表示非货币量中每组数字大小的字符串。每个字符代表一个整数值,每个整数指定当前组的位数。值为 0 意味着前一个值将应用于剩余的分组。
    • int_curr_symbol 国际货币符号使用的字符串。前三个字符是由 ISO 4217:1987 指定的,第四个字符用于分隔货币符号和货币量。
    • currency_symbol 用于货币的本地符号。
    • mon_decimal_point 用于货币值的小数点字符。 mon_thousands_sep 用于货币值的千位分隔符。
    • mon_grouping 一个表示货币值中每组数字大小的字符串。每个字符代表一个整数值,每个整数指定当前组的位数。值为 0 意味着前一个值将应用于剩余的分组。
    • positive_sign 用于正货币值的字符。
    • negative_sign 用于负货币值的字符。
    • int_frac_digits 国际货币值中小数点后要显示的位数。
    • frac_digits 货币值中小数点后要显示的位数。
    • p_cs_precedes 如果等于 1,则 currency_symbol 出现在正货币值之前。如果等于 0,则 currency_symbol 出现在正货币值之后。
    • p_sep_by_space 如果等于 1,则 currency_symbol 和正货币值之间使用空格分隔。如果等于 0,则 currency_symbol 和正货币值之间不使用空格分隔。
    • n_cs_precedes 如果等于 1,则 currency_symbol 出现在负货币值之前。如果等于 0,则 currency_symbol 出现在负货币值之后。
    • n_sep_by_space 如果等于 1,则 currency_symbol 和负货币值之间使用空格分隔。如果等于 0,则 currency_symbol 和负货币值之间不使用空格分隔。
    • p_sign_posn 表示正货币值中正号的位置。
    • n_sign_posn 表示负货币值中负号的位置。

    p_sign_posn 和 n_sign_posn:值描述

  1. 0 | 封装值和 currency_symbol 的括号。
  2. 1 | 放置在值和 currency_symbol 之前的符号。
  3. 2 | 放置在值和 currency_symbol 之后的符号。
  4. 3 | 紧挨着放置在值和 currency_symbol 之前的符号。
  5. 4 | 紧挨着放置在值和 currency_symbol 之后的符号。
  • char *setlocale(int category, const char *locale)

    • category -- 这是一个已命名的常量,指定了受区域设置影响的函数类别。

    • LC_ALL 包括下面的所有选项。

    • LC_COLLATE 字符串比较。参见 strcoll()。//和strcmp有点类似

    • LC_CTYPE 字符分类和转换。例如 strtoupper()。

    • LC_MONETARY 货币格式,针对 localeconv()。

    • LC_NUMERIC 小数点分隔符,针对 localeconv()。

    • LC_TIME 日期和时间格式,针对 strftime()。

    • LC_MESSAGES 系统响应。

    • locale -- 如果 locale 是 NULL 或空字符串 "",则区域名称将根据环境变量值来设置,其名称与上述的类别名称相同。

第十七章 经典抽象数据类型

内存分配

  • 静态数组
  • 动态分配的数组
  • 动态分配的链式结构

堆栈(栈)

先进后出

队列

先进先出

树(二叉树)

ADT泛型编程