C和指针 第十五章 习题
15.8 十六进制倾印码
#include <stdio.h> #include <stdlib.h> #include <string.h> #include <ctype.h> int main(int argc, char **argv) { //输入流 FILE *source; //左侧行号区域 int line = 0; //读入的个数 size_t readCount; //循环计数 int idx; //一个字节的16进制字符串 char hex[4]; //16进制显示区域,32个16进制加上3个空白 char hexArea[36] = {'\0'}; //字符显示区域 char alphaArea[17]; //存放读取数据 char buffer[17]; if(argc > 1){ //argv第二个是参数 source = fopen(*(argv + 1), "rb"); }else{ //如果没有文件名,标准输入当做输入源 source = stdin; } //source流检查 if(source == NULL){ printf("[%s] %d\n", *(argv + 1) , argc); perror("\n"); exit(EXIT_FAILURE); } //循环直到文件结束 while(!feof(source)){ //读取16个字节,如果没有读取剩下的字节 readCount = fread(buffer, sizeof(char), 16, source); for(idx = 0; idx < readCount; idx++){ //转换成大写16进制 sprintf(hex, "%02X", buffer[idx]); //四个字节一个空格 if(idx > 0 && (idx % 4) == 3){ strcat(hex, " "); strcat(hexArea, hex); }else{ strcat(hexArea, hex); } if(isprint(buffer[idx])){ alphaArea[idx] = buffer[idx]; }else{ alphaArea[idx] = '.'; } } alphaArea[readCount] = '\0'; printf("%06x %-36s*%-16s*\n", line * 16, hexArea, alphaArea); line++; hexArea[0] = '\0'; alphaArea[0] = '\0'; } return 0; }
/home/mao/test文件内容:
运行:
15.9 fgrep实现
#include <stdio.h> #include <string.h> #include <stdlib.h> #define MAX_BUF 510 int main(int argc, char ** argv) { FILE *file; char buff[MAX_BUF]; char search[MAX_BUF]; char currentFile[MAX_BUF]; int lineNumber; //目标字符串 strcpy(search, *(argv + 1)); if(argc > 2){ //文件打开 argv += 2; while(*(argv) != NULL){ strcpy(currentFile, *argv); file = fopen(currentFile, "r"); if(file == NULL){ perror(currentFile); exit(EXIT_FAILURE); } lineNumber = 1; while(fgets(buff, MAX_BUF, file) != NULL){ //读取文件以后,进行比对,如果找到打印信息,如果没有,继续读 if(strstr(buff, search) != NULL){ printf("%-10s:%-5d %s\n", currentFile, lineNumber, buff); } lineNumber++; } //下一个文件 argv++; } }else{ //标准输入打开 while(fgets(buff, MAX_BUF, stdin) != NULL){ if(strstr(buff, search) != NULL){ printf("%s %s\n", search, buff); }else{ printf("no found %s in %s\n", search, buff); } } } return 0; }
目录下三个文件1.txt 2.txt 3.txt,运行:
15.10 校验checkSum
#include <stdio.h> #include <string.h> #include <stdlib.h> #define MAX_BUF 100 int main(int argc, char ** argv) { FILE *file; FILE *cksFile; char cksFileName[MAX_BUF]; char currentFile[MAX_BUF]; int ch; int isToFile = 0; unsigned short int checkNum; if(argc > 1){ //文件输入,检查是否 -f if(strcmp(*(argv + 1), "-f") == 0){ isToFile = 1; //检查-f是否合法 if(argc == 2){ printf("-f illegal when reading standard input"); exit(EXIT_FAILURE); } //指向-f后的文件名 argv += 2; }else{ argv += 1; } //开始校验文件 while(*argv != NULL){ //保存当前文件名 strcpy(currentFile, *argv); if(isToFile){ //生成并打开cks文件流 strcpy(cksFileName, currentFile); strcat(cksFileName, ".cks"); cksFile = fopen(cksFileName, "w"); if(cksFile == NULL){ perror(""); exit(EXIT_FAILURE); } } //打开需要读入的文件 file = fopen(currentFile, "r"); if(file == NULL){ perror(""); exit(EXIT_FAILURE); } //开始计算checkSum checkNum = 0; while((ch = fgetc(file)) != EOF){ checkNum += ch; } //输出checkSum if(isToFile){ fprintf(cksFile, "%5s checkSum: %hu", currentFile, checkNum); fclose(cksFile); }else{ printf("%5s checkSum: %hu", currentFile, checkNum); } //关闭文件流,并准备打开下一个文件 fclose(file); argv++; } }else{ //处理标准输入 checkNum = 0; while((ch = getchar()) != EOF){ checkNum += ch; } printf("%u\n", checkNum); } return 0; }
运行:
15.11 商品存货记录
#include <stdio.h> #include <string.h> #include <stdlib.h> #define MAX_DES_BUF 40 #define MAX_BUF 20 #define SUCCESS 1 #define FAILED 0 //单件商品信息结构体 typedef struct { //商品描述 char description[MAX_DES_BUF]; //商品数量 unsigned int quantity; //商品价格 float price; //商品总价值 float totalPrice; //已售利润 float profit; //是否已删除标示 short int isDeleted; //行号 unsigned int lineNum; } GoodsMsg; //添加记录成功返回 SUCCESS 失败FAILED int newRecord(char *order, FILE *file); //购买 int buyRecord(char *order, FILE *file); //出售 int sellRecord(char *order, FILE *file); //删除 int delRecord(char *order, FILE *file); //打印 int printPartRecord(char *order, FILE *file); //打印所有 void printRecord(FILE *file); //计算总价值 float totalPrice(FILE *file); int main(int argc, char **argv) { FILE *file; char FileName[MAX_DES_BUF]; char order[MAX_DES_BUF]; //没有指定文件名,生成记录文件 if(argc == 1){ strcpy(FileName, "D:\\GoodsRecord.txt"); }else{ strcpy(FileName, *(argv + 1)); } //打开文件流,如果文件不存在,则重新生成文件 file = fopen(FileName, "rb+"); if(file == NULL){ //新建文件 file = fopen(FileName, "wb+"); if(file == NULL){ perror(""); exit(EXIT_FAILURE); }else{ printf("Create File %s", FileName); } }else{ printf("open file %s", FileName); } printf("$:"); //读取命令 while(fgets(order, 40, stdin) != NULL){ //匹配命令 if(strncmp(order, "end", 3) == 0){ //结束 printf("bye bye\n"); break; }else if(strncmp(order, "new", 3) == 0){ //添加记录 if(newRecord(order, file) == SUCCESS){ printf("\nnew success: %s\n", order); } }else if(strncmp(order, "buy", 3) == 0) { if(buyRecord(order, file) == SUCCESS){ printf("buy: %s\n", order); } }else if(strncmp(order, "sell", 4) == 0) { if(sellRecord(order, file) == SUCCESS){ printf("sell: %s\n", order); } }else if(strncmp(order, "delete", 6) == 0) { if(delRecord(order, file) == SUCCESS){ printf("del: %s\n", order); } }else if(strncmp(order, "print all", 9) == 0) { printRecord(file); }else if(strncmp(order, "print", 5) == 0) { printPartRecord(order, file); }else if(strncmp(order, "total", 5) == 0) { printf("total: %f\n", totalPrice(file)); }else{ printf("unknow order\n"); } printf("$:"); } fclose(file); return 0; } //添加记录成功返回 SUCCESS 失败FAILED int newRecord(char *order, FILE *file) { //需要写入文件商品信息结构体 GoodsMsg *good = (GoodsMsg *)malloc(sizeof(GoodsMsg)); //文件读取的临时结构体 GoodsMsg *temp = (GoodsMsg *)malloc(sizeof(GoodsMsg)); //行号 unsigned int lineNum = 1; //商品价格 float price = 0; //商品数量 unsigned int quantity; //商品描述 char descript[MAX_BUF] = {'\0'}; //重置流的位置从头开始读取 rewind(file); //将命令行格式化输入参数中 if(sscanf(order, "new %s , %u , %f\n", descript, &quantity, &price) == 3){ //初始化数据; strcpy(good -> description, descript); good -> quantity = quantity; good -> price = price; good -> totalPrice = price * quantity; good -> profit = 0; good -> isDeleted = 0; //寻找插入位置,写在已删除商品位置,还是文件末尾添加 while(fread(temp, sizeof(GoodsMsg), 1, file)){ //查找已删除产品 if(temp -> isDeleted == 1){ //定位到该条信息前,准备覆盖信息 fseek(file, -sizeof(GoodsMsg), SEEK_CUR); break; }else{ //wb+模式中,读之后如果需要写,则需定位到当前位置 fseek(file, 0L, SEEK_CUR); } lineNum++; } //添加行号 good -> lineNum = lineNum; //写入商品信息 fwrite(good, sizeof(GoodsMsg), 1, file); //写入缓冲并释放资源 fflush(file); free(temp); free(good); return SUCCESS; } return FAILED; } //购买 int buyRecord(char *order, FILE *file) { //读取的商品结构体 GoodsMsg *good = (GoodsMsg *)malloc(sizeof(GoodsMsg)); unsigned int partNumber; unsigned int quantity; float price; rewind(file); //命令符合格式 if(sscanf(order, "buy %u , %u , %f\n", &partNumber, &quantity, &price) == 3) { //查看数据更新位置 while (fread(good, sizeof(GoodsMsg), 1, file)) { //查找产品位置 if (good->lineNum == partNumber) { //定位到该条信息前 fseek(file, -sizeof(GoodsMsg), SEEK_CUR); //重新计算均价和商品总价值 good -> totalPrice = (good -> totalPrice) + quantity * price; good -> quantity = (good -> quantity) + quantity; good -> price = (good -> totalPrice) / good -> quantity; //更新商品信息 fwrite(good, sizeof(GoodsMsg), 1, file); fflush(file); return SUCCESS; } } //其他情况都返回FAILED } return FAILED; } //出售 int sellRecord(char *order, FILE *file) { GoodsMsg *temp = (GoodsMsg *)malloc(sizeof(GoodsMsg)); unsigned int partNumber; unsigned int quantity; float sellPrice; rewind(file); //命令符合格式 if(sscanf(order, "sell %u , %u , %f\n", &partNumber, &quantity, &sellPrice) == 3) { //查看数据更新位置 while (fread(temp, sizeof(GoodsMsg), 1, file)) { //查找产品 if (temp->lineNum == partNumber) { //定位到该条信息前,准备覆盖信息 fseek(file, -sizeof(GoodsMsg), SEEK_CUR); temp -> totalPrice = (temp -> totalPrice) - quantity * (temp -> price); temp -> quantity = (temp -> quantity) - quantity; temp -> profit = temp -> profit + (sellPrice - temp -> price) * quantity; fwrite(temp, sizeof(GoodsMsg), 1, file); fflush(file); return SUCCESS; } } //其他情况都返回FAILED } return FAILED; } //删除,只需将isDelete置为1 int delRecord(char *order, FILE *file) { GoodsMsg *temp = (GoodsMsg *)malloc(sizeof(GoodsMsg)); unsigned int partNumber; rewind(file); //命令符合格式 if(sscanf(order, "delete %u\n", &partNumber) == 1) { //查看数据更新位置 while (fread(temp, sizeof(GoodsMsg), 1, file)) { //查找产品 if (temp->lineNum == partNumber) { //定位到该条信息前,准备覆盖信息 fseek(file, -sizeof(GoodsMsg), SEEK_CUR); temp -> isDeleted = 1; fwrite(temp, sizeof(GoodsMsg), 1, file); fflush(file); return SUCCESS; } } //其他情况都返回FAILED } return FAILED; } //打印 int printPartRecord(char *order, FILE *file) { GoodsMsg *temp = (GoodsMsg *)malloc(sizeof(GoodsMsg)); unsigned int partNumber; rewind(file); //命令符合格式 if(sscanf(order, "print %u\n", &partNumber) == 1) { //查看数据更新位置 while (fread(temp, sizeof(GoodsMsg), 1, file)) { //在未删除产品中查找 if (temp->lineNum == partNumber && temp -> isDeleted == 0) { //打印信息 printf("\nid:%4u %u %.2f %.2f %20s\n", temp -> lineNum, temp -> quantity, temp -> price, temp -> totalPrice, temp -> description); return SUCCESS; } } //其他情况都返回FAILED } return FAILED; } //打印所有 void printRecord(FILE *file) { GoodsMsg *temp = (GoodsMsg *)malloc(sizeof(GoodsMsg)); rewind(file); printf("\nid quan price totalPric descprition\n"); //命令符合格式 while (fread(temp, sizeof(GoodsMsg), 1, file)) { //打印所有未删除商品 if(temp -> isDeleted == 0){ printf("id:%-4u%-4u %.2f %.2f\t%-20s\n", temp -> lineNum, temp -> quantity, temp -> price, temp -> totalPrice, temp -> description); } } printf("--------------------------------------------\n"); } //计算总价值 float totalPrice(FILE *file) { float totalPrice = 0; GoodsMsg *temp = (GoodsMsg *)malloc(sizeof(GoodsMsg)); rewind(file); //命令符合格式 while (fread(temp, sizeof(GoodsMsg), 1, file)) { //打印信息 totalPrice += temp -> totalPrice; } return totalPrice; }
运行:
注意:如果wb+打开文件需要读取,那么在读取之前需要fflush或文件定位函数,fseek,fsetpos, rewind。如果rb+打开文件,需要写入,必须调用文件定位函数,fseek,fsetpos, rewind。