手记一
11.文件
// 标准文件
// C会自动打开三个文件 standard input 标准输入 standard output 标准输出 standard
// error output 标准错误输出 standard input 通常为键盘 standard output
// 通常为显示器 通常标准输入为程序提供输入 getchar() scanf() 标准输出
// putchar(),puts(),printf()
#include <stdio.h>
#include <stdlib.h>
int main(int argc, char *argv[]) {
// 读取文件时存储每个字符
int ch;
// 文件指针
FILE *fp;
// 记录文件行数
unsigned long count = 0;
// 效验传入参数
if (argc == 0) {
printf("Usage: %s filename\n", argv[0]);
exit(EXIT_FAILURE);
}
// 效验是否有文件,如果没有,指针就指不上
if ((fp = fopen(argv[1], "r")) == NULL) {
printf("Can't Open %s \n", *(argv + 1));
}
//循环读 char
while ((ch = getc(fp)) != EOF) {
// 输出char
putc(ch, stdout);
count++;
}
// 关闭文件
fclose(fp);
printf("File %s has %lu characters \n", *(argv + 1), count);
return 0;
}
// 打开方式 fopen 第二个参数
// r 读模式打开
// w 写模式打开,文件不存在则创建一个新的文件
// a 写模式打开,把现有的文件长度截为0,不存在则创建一个新文件
// r+ 更新模式打开,r+w
// w+ 更新模式打开文件,如果文件存在则将其长度截为0,不存在则新建一个文件
// a+ 更新模式打开文件 可以读整个文件但只能在末尾添加内容
// rb 读模式打开二进制
// wb 写模式打开二进制
// x
// rwax 和 b进行组合
File file1.c has 1533 characters
getc() 和 putc()
getc() - getchar()
putc() - putchar()
不同点在于要告诉 getc 和 putc 函数使用哪一个文件,
//从标准输入中获取一个字符
ch = getchar();
// 从fp指向的文件中获取一个字符
ch = getc(fp);
// 把ch放入fpout指向的文件中
putc(ch,fpout);
指向标准文件的指针
标准输入 stdin 键盘
标准输出 stdout 显示器
标准错误 stderr 显示器
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define LEN 40
int main(int argc, char *argv[]) {
FILE *in, *out;
int ch;
char name[LEN];
int count = 0;
// 效验参数
if (argc < 2) {
fprintf(stderr, "Usage %s filename\n", *argv);
exit(EXIT_FAILURE);
}
// 设置输入
if ((in = fopen(*(argv + 1), "r")) == NULL) {
fprintf(stderr, "I couldn't open the file %s \n", *(argv + 1));
exit(EXIT_FAILURE);
}
// 设置输出
// 拷贝字符串,把第二个参数 拼接到name上,长度-5为后缀名留空间.注意\0结束符
strncpy(name, *(argv + 1), LEN - 5);
// 为文件添加后缀名
strcat(name, ".red");
// 以write方式打开文件
if ((out = fopen(name, "w")) == NULL) {
fprintf(stderr, "Cant't create output file\n");
exit(3);
}
while ((ch = getc(in)) != EOF) {
if (count++ % 3 == 0) {
putc(ch, out);
}
}
if (fclose(in) != 0 || fclose(out) != 0) {
fprintf(stderr, "Error in closing files\n");
}
return 0;
}
单词本,区分 scanf fscanf,printf,fprintf ,带 f 的需要传指针
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MAX 41
int main() {
FILE *p;
char words[MAX];
if ((p = fopen("wordbook", "a+")) == NULL) {
fprintf(stdout, "OH NO YOU CANT CREATE THE FILE");
exit(EXIT_FAILURE);
}
puts("Enter a word to add to the file;press the \"#\"");
// fscanf 标准输入,从键盘读取,所以不需要参数啥的
while ((fscanf(stdin, "%40s", words)) == 1 && *words != '#') {
// 标准输出,把
fprintf(p, "%s\n", words);
}
puts("File contents:\n");
// 返回到文件开始处
// p指向了文件头,所以打印出来是所有的
rewind(p);
while (fscanf(p, "%s", words) == 1)
puts(words);
puts("DONE");
if(fclose(p)!=0){
fprintf(stderr,"CANT CLOSE");
}
}
倒序输出,主要函数 fseek(),ftell()
#include <stdio.h>
#include <stdlib.h>
#define CNTL_Z EOF
#define SLEN 40
int main(void) {
char file[SLEN];
char ch;
FILE *fp;
long count, last;
puts("Enter the name of the file to be processed:");
scanf("%80s", file);
if ((fp = fopen(file, "rb")) == NULL) {
fprintf(stderr, "Error the file is NULL");
exit(EXIT_FAILURE);
}
// 定位到文件结尾
fseek(fp, 0L, SEEK_END);
// 获取指针位置
last = ftell(fp);
for (count = 1L; count <= last; count++) {
// 回退,count为偏移量,SEEK_END - count 的位置
fseek(fp, -count, SEEK_END);
ch = getc(fp);
if (ch != EOF) {
putchar(ch);
}
}
putchar('\n');
fclose(fp);
}
SEEK_SET 文件开始处
SEEK_CUR 当前位置
SEEK_END 文件末尾
其他函数
// 把c指定的字符放回输入流中,如果把字符串放回输入流,下一次读取的时候顺序是相反的
int ungetc(int c, FILE *fp);
// 输出缓冲区所有的为写入数据发送到fp指定的输出文件
int fflush(FILE *fp);
//创建缓冲区存储流,fp:待处理的流,buf缓冲区,size:数组大小,mode:_IOFBF完全缓冲,IOLBF行缓冲,_IONBF无缓冲,操作成功返回0
int setvbuf(FILE *fp,char * restrict buf,int mode,size_t size);
// 处理文本信息,如果处理double类型数据,则会损失精度
fprintf()
// fread fwrite 用来处理二进制形式数据
// 把二进制数据写入文件,ptr:待写入数据块的地址,size为数据块儿大小,nmemb:待写入数据块儿的数量,fp:要写入的文件
size_t fwrite(const void * restrict ptr,size_t size,size_t nmemb,FILE * restrict fp);
// 保存一个大小为256字节的数据对象
char buffer[256];
fwrite(buffer,256,1,fp);
//保存一个内含10个double类型的数据
double earnings[10];
fwrite(earnings,sizeof(double),10,fp);
//fread
size_t fread(void * restrict ptr,size_t size,size_t nememb,FILE * restrict fp);
//恢复上述保存数据,这里fp是output不input
double earnings[10];
fread(earnings,sizeof(double),10,fp);
/*append*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define BUFSIZE 4096
#define SLEN 81
void append(FILE *source, FILE *dest);
char *s_gets(char *st, int n);
// 接收一个源指针一个目标指针
void append(FILE *source, FILE *dest) {
size_t bytes;
static char temp[BUFSIZE];
// 一直到拷贝的字节数小与0
// fread() 把source二进制数据写入temp,temp中的一块内存占一个char的大小,整块儿大小为4096bytes
while ((bytes = fread(temp, sizeof(char), BUFSIZE, source)) > 0) {
// 在把temp中存入的东西写入到dest中
fwrite(temp, sizeof(char), bytes, dest);
}
}
char *s_gets(char *st, int n) {
char *ret_val;
char *find;
ret_val = fgets(st, n, stdin);
if (ret_val) {
find = strchr(st, '\n');
if (find) {
*find = '\0';
} else {
while (getchar() != '\n') {
continue;
}
}
}
return ret_val;
}
int main(void) {
// fa指向目标文件,fs指向源文件
FILE *fa;
FILE *fs;
// 附加的文件数量
int files = 0;
// 目标文件名称
char file_app[SLEN];
// 源文件名称
char file_src[SLEN];
int ch;
puts("Enter name of destination file:");
//获取目标文件名称
s_gets(file_app, SLEN);
// 以a模式打开文件,如果指针为空
if ((fa = fopen(file_app, "a+")) == NULL) {
// 没有这个文件/不能打开这个文件
fprintf(stderr, "Can't open %s\n", file_app);
// 退出程序
exit(EXIT_FAILURE);
}
// 如果验证通过证明有文件
// 创建一个4096bytes的缓冲区->全缓冲:对于输出,数据在缓冲填满时被一次性写入。对于输入,缓冲会在请求输入且缓冲为空时被填充。
// 如果setvbuf无法创建缓冲区,返回一个非零值
// fa指针指向该缓冲区
if (setvbuf(fa, NULL, _IOFBF, BUFSIZE) != 0) {
// 不能创建缓冲区
fputs("Can't create output buffer\n", stderr);
//退出
exit(EXIT_FAILURE);
}
puts("Enter name of first source file");
//循环获取 file_src源文件名称,并以 空'\0'字符进行判断,是否结束
while (s_gets(file_src, SLEN) && file_src[0] != '\0') {
//对比源文件名称是否与目标文件名称一致,避免进入死循环
if (strcmp(file_src, file_app) == 0) {
fputs("Can't append file to itself\n", stderr);
} else if ((fs = fopen(file_src, "r")) == NULL) {
fprintf(stderr, "Can't open %s\n", file_src);
} else {
// 创建缓冲区 无缓冲:不使用缓冲。每个 I/O 操作都被即时写入。buffer 和 size 参数被忽略。
// fs指向该缓冲区
if (setvbuf(fs, NULL, _IONBF, BUFSIZE) != 0) {
fputs("Can't append file to buffer\n", stderr);
continue;
}
}
// 将两个指针传入 append函数
append(fs, fa);
if (ferror(fs) != 0) {
fprintf(stderr, "Error in reading file %s\n", file_src);
}
if (ferror(fa) != 0) {
fprintf(stderr, "error in writing file %s\n", file_app);
}
// 关闭流
fclose(fs);
// 文件数自增
files++;
printf("File %s appended.\n", file_src);
puts("Next file");
}
printf("Done appending,%d files appended", files);
// 指针指回文件开头
rewind(fa);
printf("%s contens:\n", file_app);
// 输入出文件
while ((ch = getc(fa)) != EOF) {
putchar(ch);
}
puts("Done dispalying");
// 关闭流
fclose(fa);
return 0;
}
随机访问
/* 使用二进制I/O进行随机访问 */
#include <stdio.h>
#include <stdlib.h>
#define ARSIZE 1000
int main() {
double numbers[ARSIZE];
double value;
const char *file = "numbers.dat";
int i;
long pos;
FILE *iofile;
for (i = 0; i < ARSIZE; i++) {
numbers[i] = 100.0 * i + 1.0 / (i + 1);
}
if ((iofile = fopen(file, "wb")) == NULL) {
fprintf(stderr, "Could not open %s for output. \n", file);
exit(EXIT_FAILURE);
}
fwrite(numbers, sizeof(double), ARSIZE, iofile);
fclose(iofile);
if ((iofile = fopen(file, "rb")) == NULL) {
fprintf(stderr, "Could not open %s for random access.\n", file);
exit(EXIT_FAILURE);
}
// 一共1000个位置,最后一位是\0,所以是0-999
printf("Enter an index in the range 0-%d.\n", ARSIZE - 1);
while (scanf("%d", &i) == 1 && i >= 0 && i < ARSIZE) {
//计算指针偏移量
pos = (long)i * sizeof(double);
// 定位
fseek(iofile, pos, SEEK_SET);
// 读取iofile,到value中
fread(&value, sizeof(double), 1, iofile);
printf("The value there is %f \n", value);
printf("Next index (out of range to quit):\n");
}
flose(iofile);
puts("Bye!");
return 0;
}
小结
1.fopen()函数为标准IO打开一个文件,并创建一个用于存储文件和缓冲功能区信息的结构.并返回指向该结构的指针.
2.C把输入视为字节流
3.fread(),getc(),fgets()把每个字节看作是字符码
4.fscanf和scanf把字符码翻译并转换说明指定的其他类型
5.fwrite将二进制直接放入输出流
6.ANSIC 提供 二进制/文本文件打开方式,二进制可以逐字节读取文件.文本会把文件内容从文本的系统表示法应设为C的表示法.
7.通常 输入函数 getc(),fgets(),fscanf(),fread()都从文件开始处按顺序读取文件
8.fseek和ftell让程序可以随机访问文件中的任意位置,fgetpos()和fsetpos()把类似的功能扩展至更大的文件.
12.结构和其他数据形式
关键字:struct,union,typedef
运算符: . , ->
// book.c
//
#include <stdio.h>
#include <string.h>
char *s_gets(char *st, int n);
// 书名的最大长度+1 有空字符 \0
#define MAXTITL 41
// 作者姓名的最大长度
#define MAXAUTL 31
// 创建类
struct book {
char title[MAXTITL];
char author[MAXAUTL];
float value;
};
int main(void) {
// 把libaray声明为book类型的变量
struct book library;
printf("Please enter the book title.\n");
s_gets(library.title, MAXTITL);
printf("Now enter the author.\n");
s_gets(library.author, MAXAUTL);
printf("Now enter the value.\n");
scanf("%f", &library.value);
printf("%s by %s:$%2.f\n", library.title, library.author, library.value);
return 0;
};
char *s_gets(char *st, int n) {
char *ret_val;
char *find;
ret_val = fgets(st, n, stdin);
if (ret_val) {
find = strchr(st, '\n');
if (find) {
*find = '\0';
} else {
while (getchar() != '\n') {
continue;
}
}
}
return ret_val;
}
#include <stdio.h>
#include <string.h>
#define MAXTITL 40
#define MAXAUTL 40
#define MAXBOOKS 100
char *s_gets(char *st, int n);
struct book {
char title[MAXTITL];
char author[MAXAUTL];
float value;
};
int main(void) {
// 结构数组
struct book library[MAXBOOKS];
int count = 0;
int index;
printf("Please enter the book title.\n");
printf("Press [enter] at the start of a line to stop.\n");
while (count < MAXBOOKS && s_gets(library[count].title, MAXTITL) != NULL &&
library[count].title[0] != '\0') {
printf("Now enter the author.\n");
s_gets(library[count].author, MAXAUTL);
printf("Now enter the value.\n");
scanf("%f", &library[count++].value);
while (getchar() != '\n') {
continue;
}
if (count < MAXBOOKS) {
printf("Enter the next title.\n");
}
}
if (count > 0) {
printf("Here is the list of your books:\n");
for (index = 0; index < count; index++) {
printf("%s by %s $ %.2f\n", library[index].title, library[index].author,
library[index].value);
}
} else {
printf("No books?Toobad .\n");
}
return 0;
}
char *s_gets(char *st, int n) {
char *ret_val;
char *find;
ret_val = fgets(st, n, stdin);
if (ret_val) {
find = strchr(st, '\n');
if (find)
*find = '\0';
else
while (getchar() != '\n')
continue;
}
return ret_val;
}
结构体
/**
* @author :ferried
* @time: 2019-12-4 17:27
* @number: 14.4
* @name: friends
**/
#include <stdio.h>
#define LEN 20
struct names {
char first[LEN];
char last[LEN];
};
struct guy {
struct names handle;
char favfood[LEN];
char job[LEN];
float income;
};
int main(void) {
struct guy fellow[2] = {
{{"Ewen", "Villard"}, "grilled salmon", "personality coach", 68112.00},
{{"a", "b"}, "c", "d", 1.00},
};
// 创建一个结构体指针
struct guy *him;
printf("address #1: %p #2: %p\n", &fellow[0], &fellow[1]);
// 将结构体数组的首地址 给 him指针
him = fellow;
// him+1 是结构体数组的第二个元素
printf("pointer #1: %p #2: %p\n",him,him+1);
// -> 是结构体指针 的 .
printf("him -> income is $%.2f. (*hime).income is $%.2f",him->income,(*him).income);
printf("him -> favfood is %s: hime-> handle.last is %s\n",him->favfood,(him->handle).last) ;
return 0;
}
/**
* @author :ferried
* @time: 2019-12-4 17:27
* @number: 14.5
* @name: funds1.c
* @desc 结构传参
**/
#include <stdio.h>
#define FUNDLEN 50
struct funds {
char bank[FUNDLEN];
double bankfund;
char save[FUNDLEN];
double savefund;
};
double sum(double, double);
int main(void) {
struct funds stan = {"Garlic-Melon Bank", 4032.27,
"Lucky's Saveings and loan", 8543.94};
printf("Stan has a total of $%.2f\n", sum(stan.bankfund, stan.savefund));
}
double sum(double i, double j) { return i + j; }
/**
* @author :ferried
* @time: 2019-12-4 17:27
* @number: 14.5
* @name: funds1.c
* @desc 结构地址传参
**/
#include <stdio.h>
#define FUNDLEN 50
struct funds {
char bank[FUNDLEN];
double bankfund;
char save[FUNDLEN];
double savefund;
};
// 参数为一个指针
double sum(const struct funds *);
int main(void) {
struct funds stan = {"Garlic-Melon Bank", 4032.27,
"Lucky's Saveings and loan", 8543.94};
printf("Stan has a total of $%.2f.\n", sum(&stan));
return 0;
}
double sum(const struct funds *stan) { return stan->bankfund + stan->savefund; }
结构体传参
#include <stdio.h>
#include <string.h>
#define NLEN 30
struct namect {
char fname[NLEN];
char lname[NLEN];
int letters;
};
void getinfo(struct namect *);
void makeinfo(struct namect *);
void showinfo(const struct namect *);
char *s_gets(char *st, int n);
int main(void) {
struct namect person;
getinfo(&person);
makeinfo(&person);
showinfo(&person);
return 0;
}
void getinfo(struct namect *pst) {
printf("Please enter your first name.\n");
s_gets(pst->fname, NLEN);
printf("Please enter your last name.\n");
s_gets(pst->lname, NLEN);
}
void makeinfo(struct namect *pst) {
pst->letters = strlen(pst->fname) + strlen((*pst).lname);
}
void showinfo(const struct namect *ppp) {
printf("%s %s,your name contains %d letters.\n", ppp->fname, ppp->lname,ppp->letters);
}
char *s_gets(char *st, int n) {
char *ret_val;
char *find;
ret_val = fgets(st, n, stdin);
if (ret_val) {
find = strchr(st, '\n');
if (find) {
*find = '\0';
} else {
while (getchar() != '\n') {
continue;
}
}
}
return ret_val;
}
复合结构字面量
#include <stdio.h>
#define MAXTITL 41
#define MAXAUTL 31
struct book {
char title[MAXTITL];
char author[MAXAUTL];
float value;
};
int main(void) {
struct book readfirst;
int score;
printf("Enter test score");
scanf("%d", &score);
if (score >= 84) {
// 复合结构字面量
readfirst =
(struct book){"Crime and Punishment", "Fyodor Dostoyevsky", 11.25};
} else {
readfirst = (struct book){"Mr.Bouncy's Nice Hat", "Fred Winsome", 5.99};
}
printf("Your assigned reading: \n");
printf("%s by %s:$%.2f\n", readfirst.title, readfirst.author, readfirst.value);
return 0;
}
结构体伸缩长度
/**
* @author :ferried
* @time: 2019-12-4 17:27
* @number: 14.12
* @name: flexmemb
* @desc 伸缩性数组成员
**/
#include <stdio.h>
#include <stdlib.h>
struct flex {
int count;
double average;
double scores[];
};
void showFlex(const struct flex *p);
int main(void) {
struct flex *pf1, *pf2;
int n = 5;
int i;
int tot = 0;
//为结构和数组分配空间
pf1 = malloc(sizeof(struct flex) + n * sizeof(double));
pf1->count = n;
for (i = 0; i < n; i++) {
pf1->scores[i] = 20.0 - i;
tot += pf1->scores[i];
};
pf1->average = tot / n;
showFlex(pf1);
n = 9;
tot = 0;
pf2 = malloc(sizeof(struct flex) + n * sizeof(double));
pf2->count = n;
for (i = 0; i < n; i++) {
pf2->scores[i] = 20.0 - i / 2.0;
tot += pf2->scores[i];
}
pf2->average = tot / n;
showFlex(pf2);
free(pf1);
free(pf2);
return 0;
}
void showFlex(const struct flex *p) {
int i;
printf("Scores: ");
for (i = 0; i < p->count; i++) {
printf("%g,", p->scores[i]);
}
printf("\nAverage:%g\n", p->average);
}
保存结构体到文件中
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MAXTITL 40
#define MAXAUTL 40
#define MAXBKS 10
char *s_gets(char *st, int n);
struct book {
char title[MAXTITL];
char author[MAXAUTL];
float value;
};
int main(void) {
// 结构数组
struct book library[MAXBKS];
int count = 0;
int index, filecount;
// 文件指针
FILE *pbooks;
// 获取 book 结构体的 长度
int size = sizeof(struct book);
// 文件指针指向 book.dat,append 和 二进制模式
if ((pbooks = fopen("book.dat", "a+b")) == NULL) {
fputs("Can't open book.dat file\n", stderr);
exit(1);
}
// 定位到文件开始
rewind(pbooks);
// 如果count 小于 最大books数量,每个元素为一个book结构体的长度,每次读一个结构体,输入指针为pbooks
while (count < MAXBKS && fread(&library[count], size, 1, pbooks) == 1) {
if (count == 0) {
puts("Current contents of book.dat:");
printf("%s by %s: $%.2f\n", library[count].title, library[count].author,library[count].value);
count++;
}
}
filecount = count;
// 如果count达到结构体数组容纳上限
if (count == MAXBKS) {
fputs("The book.dat file is full.", stderr);
exit(2);
}
puts("Please add new book titles.");
puts("Press [enter] at the start of a line to stop.");
while (count < MAXBKS && s_gets(library[count].title, MAXTITL) != NULL &&
library[count].title[0] != '\0') {
puts("Now enter the author");
s_gets(library[count].author, MAXAUTL);
puts("Now enter the value.");
scanf("%f", &library[count++].value);
while (getchar() != '\n') {
continue;
}
if (count < MAXBKS) {
puts("Enter the next title.");
}
if (count > 0) {
puts("Here is the list of your books:");
for (index = 0; index < count; index++) {
printf("%s by %s: $%.2f\n", library[index].title, library[index].author,
library[index].value);
fwrite(&library[filecount], size, count - filecount, pbooks);
}
} else {
puts("No books?Toobad.\n");
}
}
};
char *s_gets(char *st, int n) {
char *ret_val;
char *find;
ret_val = fgets(st, n, stdin);
if (ret_val) {
find = strchr(st, '\n');
if (find) {
*find = '\0';
} else {
while (getchar() != '\n') {
continue;
}
}
}
return ret_val;
}
枚举
enum levels {low = 100,medium = 500,high = 2000};
// cat = 1 lynx = 10 puma = 11 tiger = 12
enum feline {cat , lynx = 10,puma,tiger};
#include <stdbool.h>
#include <stdio.h>
#include <string.h>
#define LEN 30
char *s_gets(char *st, int n);
enum spectrum { red, orange, yellow, green, blue, violet };
const char *colors[] = {"red", "orange", "yellow", "green", "blue", "violet"};
int main(void) {
char choice[LEN];
enum spectrum color;
bool color_is_found = false;
puts("Enter a color (empty line to quit):");
while (s_gets(choice, LEN) != NULL && choice[0] != '\0') {
for (color = red; color < violet; color++) {
if (strcmp(choice, colors[color]) == 0) {
color_is_found = true;
break;
}
}
if (color_is_found) {
switch (color) {
case red:
puts("Roses are red.");
break;
case orange:
puts("Poppies are orange.");
break;
case yellow:
puts("Sunflowers are yellow.");
break;
case green:
puts("Grass is green.");
break;
case blue:
puts("Bluebells are blue.");
break;
case violet:
puts("Violets are violet.");
break;
}
}
}
return 0;
}
char *s_gets(char *st, int n) {
char *ret_val;
char *find;
ret_val = fgets(st, n, stdin);
if (ret_val) {
find = strchr(st, '\n');
if (find) {
*find = '\0';
}
else{
while(getchar()!='\n')
continue;
}
}
return ret_val;
}
指针指向函数
#include <ctype.h>
#include <stdio.h>
#include <string.h>
#define LEN 81
// 获取输入
char *s_gets(char *st, int n);
// 展示菜单
char showmenu(void);
// 清除行
void eatline(void);
// 操作输入结果并展示,第一个参数为一个指向void函数的指针*fp,参数是一个
// 指向char类型的指针 二参为一个指向char类型的指针
void show(void (*fp)(char *), char *str);
// 大写
void ToUpper(char *);
// 小写
void ToLower(char *);
// 反转
void Transponse(char *);
// 不操作
void Dummy(char *);
int main(void) {
// 初始化两个数组和一个字符
char line[LEN];
char copy[LEN];
char choice;
// 初始化一个指向 void类型并携带指针参数的函数的指针 pfun
void (*pfun)(char *);
puts("Enter a string (empty to quit):");
while (s_gets(line, LEN) != NULL && line[0] != '\0') {
// 循环获取输入,一遍展示菜单一边输入
while ((choice = showmenu()) != 'n') {
switch (choice) {
// 按照不同的输入将pfun去指向不同的函数
case 'u':
pfun = ToUpper;
break;
case 'l':
pfun = ToLower;
break;
case 't':
pfun = Transponse;
break;
case 'o':
pfun = Dummy;
break;
}
// 拷贝
strcpy(copy, line);
// 根据所选不同的函数来进行不同操作
show(pfun, copy);
}
}
}
char showmenu(void) {
char ans;
puts("Enter menu choice:");
puts("u) uppercase l)lowercase");
puts("t) transposed case o)original case");
puts("n) next string");
// 从标准输入中获取一个字符
ans = getchar();
// 将字符小写
ans = tolower(ans);
// 清理输入行
eatline();
// 如果字符不在ulton中
while (strchr("ulton", ans) == NULL) {
// 重新提示
puts("Please enter a menu item:");
// 重新输入
ans = tolower(getchar());
// 清理行
eatline();
}
return ans;
}
void eatline(void) {
while (getchar() != '\n')
continue;
}
void ToUpper(char *str) {
while (*str) {
*str = toupper(*str);
str++;
}
}
void ToLower(char *str) {
while (*str) {
*str = tolower(*str);
str++;
}
}
void Transponse(char *str) {
while (*str) {
if (islower(*str)) {
*str = toupper(*str);
}
if (isupper(*str))
*str = tolower(*str);
str++;
}
}
void Dummy(char *str) { *str = *str; }
void show(void (*fp)(char *), char *str) {
(*fp)(str);
puts(str);
}
char *s_gets(char *st, int n) {
char *ret_val;
char *find;
ret_val = fgets(st, n, stdin);
if (ret_val) {
find = strchr(st, '\n');
if (find) {
*find = '\0';
} else {
while (getchar() != '\n') {
continue;
}
}
}
return ret_val;
}
欢迎来到这里!
我们正在构建一个小众社区,大家在这里相互信任,以平等 • 自由 • 奔放的价值观进行分享交流。最终,希望大家能够找到与自己志同道合的伙伴,共同成长。
注册 关于