争渡

Be my self

那些不明白
还是不明白
我还是不会
为了谁失去自由自在
我想你明白
我想你明白
  menu
55 文章
0 浏览
0 当前访客
ღゝ◡╹)ノ❤️

《C Primer Plus》手记二

  

手记一

11.文件

 1// 标准文件
 2// C会自动打开三个文件 standard input 标准输入 standard output 标准输出 standard
 3// error output 标准错误输出 standard input  通常为键盘 standard output
 4// 通常为显示器 通常标准输入为程序提供输入 getchar() scanf() 标准输出
 5// putchar(),puts(),printf()
 6
 7#include <stdio.h>
 8#include <stdlib.h>
 9
10int main(int argc, char *argv[]) {
11  // 读取文件时存储每个字符
12  int ch;
13  // 文件指针
14  FILE *fp;
15  // 记录文件行数
16  unsigned long count = 0;
17  // 效验传入参数
18  if (argc == 0) {
19    printf("Usage: %s filename\n", argv[0]);
20    exit(EXIT_FAILURE);
21  }
22  // 效验是否有文件,如果没有,指针就指不上
23  if ((fp = fopen(argv[1], "r")) == NULL) {
24    printf("Can't Open %s \n", *(argv + 1));
25  }
26  //循环读 char
27  while ((ch = getc(fp)) != EOF) {
28    // 输出char
29    putc(ch, stdout);
30    count++;
31  }
32  // 关闭文件
33  fclose(fp);
34  printf("File %s has %lu characters \n", *(argv + 1), count);
35  return 0;
36}
37
38// 打开方式 fopen 第二个参数
39// r 读模式打开
40// w 写模式打开,文件不存在则创建一个新的文件
41// a 写模式打开,把现有的文件长度截为0,不存在则创建一个新文件
42// r+ 更新模式打开,r+w
43// w+ 更新模式打开文件,如果文件存在则将其长度截为0,不存在则新建一个文件
44// a+ 更新模式打开文件 可以读整个文件但只能在末尾添加内容
45// rb 读模式打开二进制
46// wb 写模式打开二进制
47// x
48// rwax 和 b进行组合
49File file1.c has 1533 characters

  getc() 和 putc()
getc() - getchar()
putc() - putchar()
不同点在于要告诉 getc 和 putc 函数使用哪一个文件,

1//从标准输入中获取一个字符
2ch = getchar();
3// 从fp指向的文件中获取一个字符
4ch = getc(fp);
5// 把ch放入fpout指向的文件中
6putc(ch,fpout);

  指向标准文件的指针

1标准输入 stdin 键盘
2标准输出 stdout 显示器
3标准错误 stderr 显示器
 1#include <stdio.h>
 2#include <stdlib.h>
 3#include <string.h>
 4
 5#define LEN 40
 6
 7int main(int argc, char *argv[]) {
 8  FILE *in, *out;
 9  int ch;
10  char name[LEN];
11  int count = 0;
12
13  // 效验参数
14  if (argc < 2) {
15    fprintf(stderr, "Usage %s filename\n", *argv);
16    exit(EXIT_FAILURE);
17  }
18
19  // 设置输入
20  if ((in = fopen(*(argv + 1), "r")) == NULL) {
21    fprintf(stderr, "I couldn't open the file %s \n", *(argv + 1));
22    exit(EXIT_FAILURE);
23  }
24
25  // 设置输出
26  // 拷贝字符串,把第二个参数 拼接到name上,长度-5为后缀名留空间.注意\0结束符
27  strncpy(name, *(argv + 1), LEN - 5);
28  // 为文件添加后缀名
29  strcat(name, ".red");
30  // 以write方式打开文件
31  if ((out = fopen(name, "w")) == NULL) {
32    fprintf(stderr, "Cant't create output file\n");
33    exit(3);
34  }
35  while ((ch = getc(in)) != EOF) {
36    if (count++ % 3 == 0) {
37      putc(ch, out);
38    }
39  }
40  if (fclose(in) != 0 || fclose(out) != 0) {
41    fprintf(stderr, "Error in closing files\n");
42  }
43  return 0;
44}

  单词本,区分 scanf fscanf,printf,fprintf ,带 f 的需要传指针

 1#include <stdio.h>
 2#include <stdlib.h>
 3#include <string.h>
 4#define MAX 41
 5int main() {
 6
 7  FILE *p;
 8  char words[MAX];
 9
10  if ((p = fopen("wordbook", "a+")) == NULL) {
11    fprintf(stdout, "OH NO YOU CANT CREATE THE FILE");
12    exit(EXIT_FAILURE);
13  }
14
15  puts("Enter a word to add to the file;press the \"#\"");
16  // fscanf 标准输入,从键盘读取,所以不需要参数啥的
17  while ((fscanf(stdin, "%40s", words)) == 1 && *words != '#') {
18    // 标准输出,把
19    fprintf(p, "%s\n", words);
20  }
21
22  puts("File contents:\n");
23  // 返回到文件开始处
24  // p指向了文件头,所以打印出来是所有的
25  rewind(p);
26  while (fscanf(p, "%s", words) == 1)
27    puts(words);
28  puts("DONE");
29  if(fclose(p)!=0){
30    fprintf(stderr,"CANT CLOSE");
31  }
32}

  倒序输出,主要函数 fseek(),ftell()

 1#include <stdio.h>
 2#include <stdlib.h>
 3#define CNTL_Z EOF
 4#define SLEN 40
 5
 6int main(void) {
 7  char file[SLEN];
 8  char ch;
 9  FILE *fp;
10
11  long count, last;
12
13  puts("Enter the name of the file to be processed:");
14  scanf("%80s", file);
15  if ((fp = fopen(file, "rb")) == NULL) {
16    fprintf(stderr, "Error the file is NULL");
17    exit(EXIT_FAILURE);
18  }
19
20  // 定位到文件结尾
21  fseek(fp, 0L, SEEK_END);
22  // 获取指针位置
23  last = ftell(fp);
24
25  for (count = 1L; count <= last; count++) {
26    // 回退,count为偏移量,SEEK_END - count 的位置
27    fseek(fp, -count, SEEK_END);
28    ch = getc(fp);
29    if (ch != EOF) {
30      putchar(ch);
31    }
32  }
33  putchar('\n');
34  fclose(fp);
35}

  SEEK_SET 文件开始处
SEEK_CUR 当前位置
SEEK_END 文件末尾

  其他函数

1// 把c指定的字符放回输入流中,如果把字符串放回输入流,下一次读取的时候顺序是相反的
2int ungetc(int c, FILE *fp);
3// 输出缓冲区所有的为写入数据发送到fp指定的输出文件
4int fflush(FILE *fp);
5//创建缓冲区存储流,fp:待处理的流,buf缓冲区,size:数组大小,mode:_IOFBF完全缓冲,IOLBF行缓冲,_IONBF无缓冲,操作成功返回0
6int setvbuf(FILE *fp,char * restrict buf,int mode,size_t size);
 1// 处理文本信息,如果处理double类型数据,则会损失精度
 2fprintf()
 3// fread fwrite 用来处理二进制形式数据
 4// 把二进制数据写入文件,ptr:待写入数据块的地址,size为数据块儿大小,nmemb:待写入数据块儿的数量,fp:要写入的文件
 5size_t fwrite(const void * restrict ptr,size_t size,size_t nmemb,FILE * restrict fp);
 6// 保存一个大小为256字节的数据对象
 7char buffer[256];
 8fwrite(buffer,256,1,fp);
 9//保存一个内含10个double类型的数据
10double earnings[10];
11fwrite(earnings,sizeof(double),10,fp);
12//fread
13size_t fread(void * restrict ptr,size_t size,size_t nememb,FILE * restrict fp);
14//恢复上述保存数据,这里fp是output不input
15double earnings[10];
16fread(earnings,sizeof(double),10,fp);
  1/*append*/
  2
  3#include <stdio.h>
  4#include <stdlib.h>
  5#include <string.h>
  6#define BUFSIZE 4096
  7#define SLEN 81
  8void append(FILE *source, FILE *dest);
  9char *s_gets(char *st, int n);
 10
 11// 接收一个源指针一个目标指针
 12void append(FILE *source, FILE *dest) {
 13  size_t bytes;
 14  static char temp[BUFSIZE];
 15  // 一直到拷贝的字节数小与0
 16  // fread() 把source二进制数据写入temp,temp中的一块内存占一个char的大小,整块儿大小为4096bytes
 17  while ((bytes = fread(temp, sizeof(char), BUFSIZE, source)) > 0) {
 18    // 在把temp中存入的东西写入到dest中
 19    fwrite(temp, sizeof(char), bytes, dest);
 20  }
 21}
 22
 23char *s_gets(char *st, int n) {
 24  char *ret_val;
 25  char *find;
 26  ret_val = fgets(st, n, stdin);
 27  if (ret_val) {
 28    find = strchr(st, '\n');
 29    if (find) {
 30      *find = '\0';
 31    } else {
 32      while (getchar() != '\n') {
 33        continue;
 34      }
 35    }
 36  }
 37  return ret_val;
 38}
 39
 40int main(void) {
 41  // fa指向目标文件,fs指向源文件
 42  FILE *fa;
 43  FILE *fs;
 44  // 附加的文件数量
 45  int files = 0;
 46  // 目标文件名称
 47  char file_app[SLEN];
 48  // 源文件名称
 49  char file_src[SLEN];
 50  int ch;
 51
 52  puts("Enter name of destination file:");
 53  //获取目标文件名称
 54  s_gets(file_app, SLEN);
 55  // 以a模式打开文件,如果指针为空
 56  if ((fa = fopen(file_app, "a+")) == NULL) {
 57    // 没有这个文件/不能打开这个文件
 58    fprintf(stderr, "Can't open %s\n", file_app);
 59    // 退出程序
 60    exit(EXIT_FAILURE);
 61  }
 62  // 如果验证通过证明有文件
 63  // 创建一个4096bytes的缓冲区->全缓冲:对于输出,数据在缓冲填满时被一次性写入。对于输入,缓冲会在请求输入且缓冲为空时被填充。
 64  // 如果setvbuf无法创建缓冲区,返回一个非零值
 65  // fa指针指向该缓冲区
 66  if (setvbuf(fa, NULL, _IOFBF, BUFSIZE) != 0) {
 67    // 不能创建缓冲区
 68    fputs("Can't create output buffer\n", stderr);
 69    //退出
 70    exit(EXIT_FAILURE);
 71  }
 72  puts("Enter name of first source file");
 73  //循环获取 file_src源文件名称,并以 空'\0'字符进行判断,是否结束
 74  while (s_gets(file_src, SLEN) && file_src[0] != '\0') {
 75    //对比源文件名称是否与目标文件名称一致,避免进入死循环
 76    if (strcmp(file_src, file_app) == 0) {
 77      fputs("Can't append file to itself\n", stderr);
 78    } else if ((fs = fopen(file_src, "r")) == NULL) {
 79      fprintf(stderr, "Can't open %s\n", file_src);
 80    } else {
 81      // 创建缓冲区 无缓冲:不使用缓冲。每个 I/O 操作都被即时写入。buffer 和 size 参数被忽略。
 82      // fs指向该缓冲区
 83      if (setvbuf(fs, NULL, _IONBF, BUFSIZE) != 0) {
 84        fputs("Can't append file to buffer\n", stderr);
 85        continue;
 86      }
 87    }
 88    // 将两个指针传入 append函数
 89    append(fs, fa);
 90    if (ferror(fs) != 0) {
 91      fprintf(stderr, "Error in reading file %s\n", file_src);
 92    }
 93    if (ferror(fa) != 0) {
 94      fprintf(stderr, "error in writing file %s\n", file_app);
 95    }
 96    // 关闭流
 97    fclose(fs);
 98    // 文件数自增
 99    files++;
100    printf("File %s appended.\n", file_src);
101    puts("Next file");
102  }
103  printf("Done appending,%d files appended", files);
104  // 指针指回文件开头
105  rewind(fa);
106  printf("%s contens:\n", file_app);
107  // 输入出文件
108  while ((ch = getc(fa)) != EOF) {
109    putchar(ch);
110  }
111  puts("Done dispalying");
112  // 关闭流
113  fclose(fa);
114  return 0;
115}

  随机访问

 1/* 使用二进制I/O进行随机访问 */
 2#include <stdio.h>
 3#include <stdlib.h>
 4
 5#define ARSIZE 1000
 6
 7int main() {
 8  double numbers[ARSIZE];
 9  double value;
10  const char *file = "numbers.dat";
11  int i;
12  long pos;
13  FILE *iofile;
14
15  for (i = 0; i < ARSIZE; i++) {
16    numbers[i] = 100.0 * i + 1.0 / (i + 1);
17  }
18  if ((iofile = fopen(file, "wb")) == NULL) {
19    fprintf(stderr, "Could not open %s for output. \n", file);
20    exit(EXIT_FAILURE);
21  }
22
23  fwrite(numbers, sizeof(double), ARSIZE, iofile);
24  fclose(iofile);
25
26  if ((iofile = fopen(file, "rb")) == NULL) {
27    fprintf(stderr, "Could not open %s for random access.\n", file);
28    exit(EXIT_FAILURE);
29  }
30
31  // 一共1000个位置,最后一位是\0,所以是0-999
32  printf("Enter an index in the range 0-%d.\n", ARSIZE - 1);
33
34  while (scanf("%d", &i) == 1 && i >= 0 && i < ARSIZE) {
35    //计算指针偏移量
36    pos = (long)i * sizeof(double);
37    // 定位
38    fseek(iofile, pos, SEEK_SET);
39    // 读取iofile,到value中
40    fread(&value, sizeof(double), 1, iofile);
41    printf("The value there is %f \n", value);
42    printf("Next index (out of range to quit):\n");
43  }
44  flose(iofile);
45  puts("Bye!");
46  return 0;
47}

  小结

 11.fopen()函数为标准IO打开一个文件,并创建一个用于存储文件和缓冲功能区信息的结构.并返回指向该结构的指针.
 2
 32.C把输入视为字节流
 4
 53.fread(),getc(),fgets()把每个字节看作是字符码
 6
 74.fscanf和scanf把字符码翻译并转换说明指定的其他类型
 8
 95.fwrite将二进制直接放入输出流
10
116.ANSIC 提供 二进制/文本文件打开方式,二进制可以逐字节读取文件.文本会把文件内容从文本的系统表示法应设为C的表示法.
12
137.通常 输入函数 getc(),fgets(),fscanf(),fread()都从文件开始处按顺序读取文件
14
158.fseek和ftell让程序可以随机访问文件中的任意位置,fgetpos()和fsetpos()把类似的功能扩展至更大的文件.
16

12.结构和其他数据形式

  关键字:struct,union,typedef
运算符: . , ->

 1// book.c
 2//
 3
 4#include <stdio.h>
 5#include <string.h>
 6
 7char *s_gets(char *st, int n);
 8
 9// 书名的最大长度+1 有空字符 \0
10#define MAXTITL 41
11// 作者姓名的最大长度
12#define MAXAUTL 31
13// 创建类
14struct book {
15  char title[MAXTITL];
16  char author[MAXAUTL];
17  float value;
18};
19
20int main(void) {
21  // 把libaray声明为book类型的变量
22  struct book library;
23  printf("Please enter the book title.\n");
24  s_gets(library.title, MAXTITL);
25  printf("Now enter the author.\n");
26  s_gets(library.author, MAXAUTL);
27  printf("Now enter the value.\n");
28  scanf("%f", &library.value);
29  printf("%s by %s:$%2.f\n", library.title, library.author, library.value);
30  return 0;
31};
32
33char *s_gets(char *st, int n) {
34  char *ret_val;
35  char *find;
36  ret_val = fgets(st, n, stdin);
37  if (ret_val) {
38    find = strchr(st, '\n');
39    if (find) {
40      *find = '\0';
41    } else {
42      while (getchar() != '\n') {
43        continue;
44      }
45    }
46  }
47  return ret_val;
48}
 1#include <stdio.h>
 2#include <string.h>
 3#define MAXTITL 40
 4#define MAXAUTL 40
 5#define MAXBOOKS 100
 6char *s_gets(char *st, int n);
 7
 8struct book {
 9  char title[MAXTITL];
10  char author[MAXAUTL];
11  float value;
12};
13
14int main(void) {
15  // 结构数组
16  struct book library[MAXBOOKS];
17
18  int count = 0;
19  int index;
20
21  printf("Please enter the book title.\n");
22  printf("Press [enter] at the start of a line to stop.\n");
23
24  while (count < MAXBOOKS && s_gets(library[count].title, MAXTITL) != NULL &&
25         library[count].title[0] != '\0') {
26    printf("Now enter the author.\n");
27    s_gets(library[count].author, MAXAUTL);
28    printf("Now enter the value.\n");
29    scanf("%f", &library[count++].value);
30    while (getchar() != '\n') {
31      continue;
32    }
33    if (count < MAXBOOKS) {
34      printf("Enter the next title.\n");
35    }
36  }
37  if (count > 0) {
38    printf("Here is the list of your books:\n");
39    for (index = 0; index < count; index++) {
40      printf("%s by %s $ %.2f\n", library[index].title, library[index].author,
41             library[index].value);
42    }
43  } else {
44    printf("No books?Toobad .\n");
45  }
46  return 0;
47}
48
49char *s_gets(char *st, int n) {
50  char *ret_val;
51  char *find;
52  ret_val = fgets(st, n, stdin);
53  if (ret_val) {
54    find = strchr(st, '\n');
55    if (find)
56      *find = '\0';
57    else
58      while (getchar() != '\n')
59        continue;
60  }
61  return ret_val;
62}

  结构体

 1/**
 2 * @author :ferried
 3 * @time: 2019-12-4 17:27
 4 * @number: 14.4
 5 * @name: friends
 6 **/
 7#include <stdio.h>
 8#define LEN 20
 9
10struct names {
11  char first[LEN];
12  char last[LEN];
13};
14
15struct guy {
16  struct names handle;
17  char favfood[LEN];
18  char job[LEN];
19  float income;
20};
21
22int main(void) {
23  struct guy fellow[2] = {
24      {{"Ewen", "Villard"}, "grilled salmon", "personality coach", 68112.00},
25      {{"a", "b"}, "c", "d", 1.00},
26  };
27  // 创建一个结构体指针
28  struct guy *him;
29  printf("address #1: %p #2: %p\n", &fellow[0], &fellow[1]);
30  // 将结构体数组的首地址 给 him指针
31  him = fellow;
32  // him+1 是结构体数组的第二个元素
33  printf("pointer #1: %p #2: %p\n",him,him+1);
34  // -> 是结构体指针 的 .
35  printf("him -> income is $%.2f. (*hime).income is $%.2f",him->income,(*him).income);
36  printf("him -> favfood is %s: hime-> handle.last is %s\n",him->favfood,(him->handle).last) ;
37  return 0;
38}
 1/**
 2 * @author :ferried
 3 * @time: 2019-12-4 17:27
 4 * @number: 14.5
 5 * @name: funds1.c
 6 * @desc 结构传参
 7 **/
 8
 9#include <stdio.h>
10#define FUNDLEN 50
11
12struct funds {
13  char bank[FUNDLEN];
14  double bankfund;
15  char save[FUNDLEN];
16  double savefund;
17};
18
19double sum(double, double);
20
21int main(void) {
22  struct funds stan = {"Garlic-Melon Bank", 4032.27,
23                       "Lucky's Saveings and loan", 8543.94};
24
25  printf("Stan has a total of $%.2f\n", sum(stan.bankfund, stan.savefund));
26}
27
28double sum(double i, double j) { return i + j; }
 1/**
 2 * @author :ferried
 3 * @time: 2019-12-4 17:27
 4 * @number: 14.5
 5 * @name: funds1.c
 6 * @desc 结构地址传参
 7 **/
 8
 9#include <stdio.h>
10#define FUNDLEN 50
11
12struct funds {
13  char bank[FUNDLEN];
14  double bankfund;
15  char save[FUNDLEN];
16  double savefund;
17};
18
19// 参数为一个指针
20double sum(const struct funds *);
21
22int main(void) {
23  struct funds stan = {"Garlic-Melon Bank", 4032.27,
24                       "Lucky's Saveings and loan", 8543.94};
25
26  printf("Stan has a total of $%.2f.\n", sum(&stan));
27  return 0;
28}
29
30double sum(const struct funds *stan) { return stan->bankfund + stan->savefund; }

  结构体传参

 1#include <stdio.h>
 2#include <string.h>
 3
 4#define NLEN 30
 5
 6struct namect {
 7  char fname[NLEN];
 8  char lname[NLEN];
 9  int letters;
10};
11
12void getinfo(struct namect *);
13void makeinfo(struct namect *);
14void showinfo(const struct namect *);
15char *s_gets(char *st, int n);
16
17int main(void) {
18  struct namect person;
19  getinfo(&person);
20  makeinfo(&person);
21  showinfo(&person);
22  return 0;
23}
24
25void getinfo(struct namect *pst) {
26  printf("Please enter your first name.\n");
27  s_gets(pst->fname, NLEN);
28  printf("Please enter your last name.\n");
29  s_gets(pst->lname, NLEN);
30}
31
32void makeinfo(struct namect *pst) {
33  pst->letters = strlen(pst->fname) + strlen((*pst).lname);
34}
35
36void showinfo(const struct namect *ppp) {
37  printf("%s %s,your name contains %d letters.\n", ppp->fname, ppp->lname,ppp->letters);
38}
39
40char *s_gets(char *st, int n) {
41  char *ret_val;
42  char *find;
43  ret_val = fgets(st, n, stdin);
44  if (ret_val) {
45    find = strchr(st, '\n');
46    if (find) {
47      *find = '\0';
48    } else {
49      while (getchar() != '\n') {
50        continue;
51      }
52    }
53  }
54  return ret_val;
55}

  复合结构字面量

 1#include <stdio.h>
 2#define MAXTITL 41
 3#define MAXAUTL 31
 4
 5struct book {
 6  char title[MAXTITL];
 7  char author[MAXAUTL];
 8  float value;
 9};
10
11int main(void) {
12  struct book readfirst;
13  int score;
14
15  printf("Enter test score");
16  scanf("%d", &score);
17  if (score >= 84) {
18    // 复合结构字面量
19    readfirst =
20        (struct book){"Crime and Punishment", "Fyodor Dostoyevsky", 11.25};
21  } else {
22    readfirst = (struct book){"Mr.Bouncy's Nice Hat", "Fred Winsome", 5.99};
23  }
24
25  printf("Your assigned reading: \n");
26  printf("%s by %s:$%.2f\n", readfirst.title, readfirst.author, readfirst.value);
27  return 0;
28}

  结构体伸缩长度

 1/**
 2 * @author :ferried
 3 * @time: 2019-12-4 17:27
 4 * @number: 14.12
 5 * @name: flexmemb
 6 * @desc 伸缩性数组成员
 7 **/
 8
 9#include <stdio.h>
10#include <stdlib.h>
11
12struct flex {
13  int count;
14  double average;
15  double scores[];
16};
17
18void showFlex(const struct flex *p);
19
20int main(void) {
21  struct flex *pf1, *pf2;
22  int n = 5;
23  int i;
24  int tot = 0;
25
26  //为结构和数组分配空间
27  pf1 = malloc(sizeof(struct flex) + n * sizeof(double));
28  pf1->count = n;
29
30  for (i = 0; i < n; i++) {
31    pf1->scores[i] = 20.0 - i;
32    tot += pf1->scores[i];
33  };
34
35  pf1->average = tot / n;
36  showFlex(pf1);
37
38  n = 9;
39  tot = 0;
40  pf2 = malloc(sizeof(struct flex) + n * sizeof(double));
41  pf2->count = n;
42  for (i = 0; i < n; i++) {
43    pf2->scores[i] = 20.0 - i / 2.0;
44    tot += pf2->scores[i];
45  }
46  pf2->average = tot / n;
47  showFlex(pf2);
48  free(pf1);
49  free(pf2);
50  return 0;
51}
52
53void showFlex(const struct flex *p) {
54  int i;
55  printf("Scores: ");
56  for (i = 0; i < p->count; i++) {
57    printf("%g,", p->scores[i]);
58  }
59  printf("\nAverage:%g\n", p->average);
60}

  保存结构体到文件中

 1#include <stdio.h>
 2#include <stdlib.h>
 3#include <string.h>
 4#define MAXTITL 40
 5#define MAXAUTL 40
 6#define MAXBKS 10
 7
 8char *s_gets(char *st, int n);
 9struct book {
10  char title[MAXTITL];
11  char author[MAXAUTL];
12  float value;
13};
14
15int main(void) {
16  // 结构数组
17  struct book library[MAXBKS];
18  int count = 0;
19  int index, filecount;
20  // 文件指针
21  FILE *pbooks;
22  // 获取 book 结构体的 长度
23  int size = sizeof(struct book);
24  // 文件指针指向 book.dat,append 和 二进制模式
25  if ((pbooks = fopen("book.dat", "a+b")) == NULL) {
26    fputs("Can't open book.dat file\n", stderr);
27    exit(1);
28  }
29  // 定位到文件开始
30  rewind(pbooks);
31  // 如果count 小于 最大books数量,每个元素为一个book结构体的长度,每次读一个结构体,输入指针为pbooks
32  while (count < MAXBKS && fread(&library[count], size, 1, pbooks) == 1) {
33    if (count == 0) {
34      puts("Current contents of book.dat:");
35      printf("%s by %s: $%.2f\n", library[count].title, library[count].author,library[count].value);
36      count++;
37    }
38  }
39
40  filecount = count;
41  // 如果count达到结构体数组容纳上限
42  if (count == MAXBKS) {
43    fputs("The book.dat file is full.", stderr);
44    exit(2);
45  }
46
47  puts("Please add new book titles.");
48  puts("Press [enter] at the start of a line to stop.");
49  while (count < MAXBKS && s_gets(library[count].title, MAXTITL) != NULL &&
50         library[count].title[0] != '\0') {
51    puts("Now enter the author");
52    s_gets(library[count].author, MAXAUTL);
53    puts("Now enter the value.");
54    scanf("%f", &library[count++].value);
55    while (getchar() != '\n') {
56      continue;
57    }
58    if (count < MAXBKS) {
59      puts("Enter the next title.");
60    }
61    if (count > 0) {
62      puts("Here is the list of your books:");
63      for (index = 0; index < count; index++) {
64        printf("%s by %s: $%.2f\n", library[index].title, library[index].author,
65               library[index].value);
66        fwrite(&library[filecount], size, count - filecount, pbooks);
67      }
68    } else {
69      puts("No books?Toobad.\n");
70    }
71  }
72};
73
74char *s_gets(char *st, int n) {
75  char *ret_val;
76  char *find;
77  ret_val = fgets(st, n, stdin);
78  if (ret_val) {
79    find = strchr(st, '\n');
80    if (find) {
81      *find = '\0';
82    } else {
83      while (getchar() != '\n') {
84        continue;
85      }
86    }
87  }
88  return ret_val;
89}

  枚举

1enum levels {low = 100,medium = 500,high = 2000};
2// cat = 1 lynx = 10 puma = 11 tiger = 12
3enum feline {cat , lynx = 10,puma,tiger};
 1#include <stdbool.h>
 2#include <stdio.h>
 3#include <string.h>
 4
 5#define LEN 30
 6
 7char *s_gets(char *st, int n);
 8enum spectrum { red, orange, yellow, green, blue, violet };
 9const char *colors[] = {"red", "orange", "yellow", "green", "blue", "violet"};
10
11int main(void) {
12  char choice[LEN];
13  enum spectrum color;
14  bool color_is_found = false;
15
16  puts("Enter a color (empty line to quit):");
17  while (s_gets(choice, LEN) != NULL && choice[0] != '\0') {
18    for (color = red; color < violet; color++) {
19      if (strcmp(choice, colors[color]) == 0) {
20        color_is_found = true;
21        break;
22      }
23    }
24    if (color_is_found) {
25      switch (color) {
26      case red:
27        puts("Roses are red.");
28        break;
29      case orange:
30        puts("Poppies are orange.");
31        break;
32      case yellow:
33        puts("Sunflowers are yellow.");
34        break;
35      case green:
36        puts("Grass is green.");
37        break;
38      case blue:
39        puts("Bluebells are blue.");
40        break;
41      case violet:
42        puts("Violets are violet.");
43        break;
44      }
45    }
46  }
47  return 0;
48}
49
50char *s_gets(char *st, int n) {
51  char *ret_val;
52  char *find;
53
54  ret_val = fgets(st, n, stdin);
55  if (ret_val) {
56    find = strchr(st, '\n');
57    if (find) {
58      *find = '\0';
59    }
60    else{
61      while(getchar()!='\n')
62        continue;
63    }
64  }
65  return ret_val;
66}

  指针指向函数

  1#include <ctype.h>
  2#include <stdio.h>
  3#include <string.h>
  4#define LEN 81
  5// 获取输入
  6char *s_gets(char *st, int n);
  7// 展示菜单
  8char showmenu(void);
  9// 清除行
 10void eatline(void);
 11// 操作输入结果并展示,第一个参数为一个指向void函数的指针*fp,参数是一个
 12// 指向char类型的指针 二参为一个指向char类型的指针
 13void show(void (*fp)(char *), char *str);
 14// 大写
 15void ToUpper(char *);
 16// 小写
 17void ToLower(char *);
 18// 反转
 19void Transponse(char *);
 20// 不操作
 21void Dummy(char *);
 22
 23int main(void) {
 24  // 初始化两个数组和一个字符
 25  char line[LEN];
 26  char copy[LEN];
 27  char choice;
 28  // 初始化一个指向 void类型并携带指针参数的函数的指针 pfun
 29  void (*pfun)(char *);
 30
 31  puts("Enter a string (empty to quit):");
 32  while (s_gets(line, LEN) != NULL && line[0] != '\0') {
 33    // 循环获取输入,一遍展示菜单一边输入
 34    while ((choice = showmenu()) != 'n') {
 35      switch (choice) {
 36        // 按照不同的输入将pfun去指向不同的函数
 37      case 'u':
 38        pfun = ToUpper;
 39        break;
 40      case 'l':
 41        pfun = ToLower;
 42        break;
 43      case 't':
 44        pfun = Transponse;
 45        break;
 46      case 'o':
 47        pfun = Dummy;
 48        break;
 49      }
 50      // 拷贝
 51      strcpy(copy, line);
 52      // 根据所选不同的函数来进行不同操作
 53      show(pfun, copy);
 54    }
 55  }
 56}
 57
 58char showmenu(void) {
 59  char ans;
 60  puts("Enter menu choice:");
 61  puts("u) uppercase  l)lowercase");
 62  puts("t) transposed case  o)original case");
 63  puts("n)  next string");
 64  // 从标准输入中获取一个字符
 65  ans = getchar();
 66  // 将字符小写
 67  ans = tolower(ans);
 68  // 清理输入行
 69  eatline();
 70  // 如果字符不在ulton中
 71  while (strchr("ulton", ans) == NULL) {
 72    // 重新提示
 73    puts("Please enter a menu item:");
 74    // 重新输入
 75    ans = tolower(getchar());
 76    // 清理行
 77    eatline();
 78  }
 79  return ans;
 80}
 81
 82void eatline(void) {
 83  while (getchar() != '\n')
 84    continue;
 85}
 86
 87void ToUpper(char *str) {
 88  while (*str) {
 89    *str = toupper(*str);
 90    str++;
 91  }
 92}
 93
 94void ToLower(char *str) {
 95  while (*str) {
 96    *str = tolower(*str);
 97    str++;
 98  }
 99}
100
101void Transponse(char *str) {
102  while (*str) {
103    if (islower(*str)) {
104      *str = toupper(*str);
105    }
106    if (isupper(*str))
107      *str = tolower(*str);
108    str++;
109  }
110}
111
112void Dummy(char *str) { *str = *str; }
113
114void show(void (*fp)(char *), char *str) {
115  (*fp)(str);
116  puts(str);
117}
118
119char *s_gets(char *st, int n) {
120  char *ret_val;
121  char *find;
122  ret_val = fgets(st, n, stdin);
123  if (ret_val) {
124    find = strchr(st, '\n');
125    if (find) {
126      *find = '\0';
127    } else {
128      while (getchar() != '\n') {
129        continue;
130      }
131    }
132  }
133  return ret_val;
134}

标题:《C Primer Plus》手记二
作者:fe
地址:https://blog.eiyouhe.com/articles/2019/11/25/1574669159322.html