C和指针第十五章编程练习

这篇博客介绍了如何使用C语言编程,通过命令行接收文件名并读取文件内容。内容包括利用fread函数逐字节读取文件,每次读取16个字节,并将读取到的数据以十六进制和原始形式展示。文章详细阐述了代码实现过程,包括处理标准输入和文件流,以及如何使用strcat函数追加内容到显示区域。
摘要由CSDN通过智能技术生成

15.22.1

#include <stdio.h>
int main(void)
{
    int ch;
    while((ch = getchar()) != EOF)
        putchar(ch);
    return 0;
}

15.22.2

#include <stdio.h>
int main(void)
{
    char temp[81];
    while(fgets(temp, 80, stdin))
        fputs(temp, stdout);
    return 0;
}

15.22.3

#include <stdio.h>
#include <string.h>
int main(void)
{
    char temp[256], * temp1 = temp;
    while(fgets(temp, 256, stdin))
    {
        if(strlen(temp) > 80)
        {
            int i;
            for(i = 0; i < strlen(temp) - 80; i++)
            {
            	if(i != 0 && i % 40 == 0)
            		putchar('\n');
                putchar(*temp1++);
            }
            putchar('\n');
        }
        fputs(temp1, stdout);
    }
    return 0;
}

15.22.4

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(void)
{
    FILE * fp1 = NULL, * fp2 = NULL;
    char filename[40], filename1[40], temp[256], * temp1 = temp;
    puts("请输入读取文件名:");
    if(!(gets(filename)) && !(filename[0]))
    {
        perror("filename");
        exit(1);
    }
    if(!(fp1 = fopen(filename, "r")))
    {
        perror("fp1");
        exit(1);
    }
    puts("请输入输出文件名:");
    if(!(gets(filename1)) && !(filename1[0]))
    {
        perror("filename1");
        exit(1);
    }
    if(!(fp2 = fopen(filename1, "w")))
    {
        perror("fp2");
        exit(1);
    }
    while(fgets(temp, 256, fp1))
    {
        if(strlen(temp) > 80)
        {
            int i;
            for(i = 0; i < strlen(temp); i++)
            {
                if(i % 40 == 0 && i != 0)
                    putc('\n', fp2);
                putc(*temp1++, fp2);
            }
            putc('\n', fp2);
        }
        fputs(temp1, fp2);
    }
    if(fclose(fp1) != 0 && fclose(fp2) != 0)
    {
        perror("fclose");
        exit(1);
    }
    return 0;
}

15.22.5

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(void)
{
    int sum = 0;
    FILE * fp1 = NULL, * fp2 = NULL;
    char filename[40], filename1[40], temp[256], * temp1 = temp;
    puts("请输入读取文件名:");
    if(!(gets(filename)) && !(filename[0]))
    {
        perror("filename");
        exit(1);
    }
    if(!(fp1 = fopen(filename, "r")))
    {
        perror("fp1");
        exit(1);
    }
    puts("请输入输出文件名:");
    if(!(gets(filename1)) && !(filename1[0]))
    {
        perror("filename1");
        exit(1);
    }
    if(!(fp2 = fopen(filename1, "w")))
    {
        perror("fp2");
        exit(1);
    }
    while(fgets(temp, 256, fp1))
    {
        if(*temp1 >= '0' && *temp1 <= '9')
            sum += *temp1 - '0';
        if(strlen(temp) > 80)
        {
            int i;
            for(i = 0; i < strlen(temp); i++)
            {
                if(i % 40 == 0 && i != 0)
                    putc('\n', fp2);
                putc(*temp1++, fp2);
            }
            putc('\n', fp2);
        }
        fputs(temp1, fp2);
    }
    char num[10];
    itoa(sum, num, 10);
    fputs(num, fp2);
    if(fclose(fp1) != 0 && fclose(fp2) != 0)
    {
        perror("fclose");
        exit(1);
    }
    return 0;
}

15.22.6

int numeric_palindrome(int value)
{
    int temp = value, count;
    for(count = 0; temp; count++, temp /= 10);
    int num[count], n, sum = count;
    while(value)
    {
        n = value % 10;
        num[count-- - 1] = n;
        value /= 10;
    }
    int i, j;
    for(i = 0, j = sum - 1; i < sum; i++, j--)
    {
        if(num[i] != num[j])
            return 0;
    }
    return 1;
}

15.22.7

#include <stdio.h>
#include <stdlib.h>
int main(void)
{
    FILE * fp = NULL;
    char ch;
    int sum = 0, num, count = 0, n = 0;
    if(!(fp = fopen("F:\\c_programs\\1\\bin\\Debug\\cs.txt", "r")))
    {
        perror("fopen");
        exit(1);
    }
    while(fscanf(fp, "%d", &num) == 1)
    {
        sum += num;
        count++;
        if((ch = getc(fp)) == '\n' || ch == EOF)
        {
            printf("第%d个家庭成员的平均年龄为: %5.2f\n", n + 1, (float)sum / count);
            sum = 0, count = 0;
            n++;
        }
    }
    if(fclose(fp) != 0)
    {
        perror("fclose");
        exit(1);
    }
    return 0;
}

15.22.8
思路来源于https://www.cnblogs.com/yangxunwu1992/p/5863292.html
本题的意思是让我们用命令行的方式打开一个文件并读取其中的内容再让其内容打印出来 每一行有3个打印的地方
①文件的当前偏移位置
②文件内容转换为十六进制字符区
③文件的原本内容

#include <stdio.h>
#include <stdlib.h>
int main(int argc, char * argv[])
{
    FILE * fp = NULL;
    if(argc == 1)
        fp = stdin;
    else
    {
        if(!(fp = fopen(argv[1], "r")))
        {
            perror("fopen");
            exit(1);
        }
    }
    return 0;
}

先写出这个框架 意思就是如果命令行没有跟文件名就从标准输入里面读取
继续写出

size_t readnum;
while(!feof(fp))
{
     readnum = fread(buffer, sizeof(char), 16, fp);
}

使用fread来读取 每次读取一个字节 一次读取16个 从fp流中 将成功读取的个数返回给readnum

int line;//代表行数 也就是题意的偏移
char buffer[17];//缓冲区
char hex[4];//十六进制数据临时存放区域
char hexArea[36] = {'\0'};//十六进制数据显示区域 32个数据 其中有3个空格 这里将元素初始化为'\0'是因为后面不必去判断他这个区域写入了多少
char chArea[17] = {'\0'};//字符显示区域 这里初始化目的和上面一样
int i;
size_t readnum;
while(!feof(fp))
{
     readnum = fread(buffer, sizeof(char), 16, fp);
     for(i = 0; i < readnum; i++)
     {
     	sprintf(hex, "%02X", buffer[i]);//从buffer中依次写入数据 每一个字节的数据最多占2个宽度的十六进制数据 如16进制的FF=11111111是8位
     	if(i > 0 && i % 4 == 3)//i % 4的余数判断何时插入一个空格字符
        {
            strcat(hex, " ");
            strcat(hexArea, hex);
        }
        else
            strcat(hexArea, hex);
        if(isprint(buffer[i]))//判断他是否为可打印字符 如果是就直接存入字符显示区域
          charea[i] = buffer[i];
        else//否则就用.代替
          charea[i] = '.';
     }
     printf("%06x %-36s*%-16s*\n", line * 16, hexArea, chArea);//偏移占6位然后缺失的用0补齐
     hexArea[0] = '\0';
     chArea[0] = '\0';
}

将上面代码合并
流程大致为
判断流-----将字节数据写入进一个临时存放区域------用strcat函数追加进真正的显示区域------将字符写入进字符区域------打印该行------将2个显示区域首元素置位’\0’方便下次追加

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
int main(int argc, char * argv[])
{
    FILE * fp = NULL;
    if(argc == 1)
        fp = stdin;
    else
    {
        if(!(fp = fopen(argv[1], "r")))
        {
            perror("fopen");
            exit(1);
        }
    }
    int line = 0;//代表行数 也就是题意的偏移
	char buffer[17];//缓冲区
	char hex[4];//十六进制数据临时存放区域
	char hexArea[36] = {'\0'};//十六进制数据显示区域 32个数据 其中有3个空格 这里将元素初始化为'\0'是因为后面不必去判断他这个区域写入了多少
	char chArea[17] = {'\0'};//字符显示区域 这里初始化目的和上面一样
	int i;
	size_t readnum;
	while(!feof(fp))
	{
	     readnum = fread(buffer, sizeof(char), 16, fp);
	     for(i = 0; i < readnum; i++)
	     {
	     	sprintf(hex, "%02X", buffer[i]);//从buffer中依次写入数据 每一个字节的数据最多占2个宽度的十六进制数据 如16进制的FF=11111111是8位
	     	if(i > 0 && i % 4 == 3)//i % 4的余数判断何时插入一个空格字符
	        {
	            strcat(hex, " ");
	            strcat(hexArea, hex);
	        }
	        else
	            strcat(hexArea, hex);
	        if(isprint(buffer[i]))//判断他是否为可打印字符 如果是就直接存入字符显示区域
	          chArea[i] = buffer[i];
	        else//否则就用.代替
	          chArea[i] = '.';
	     }
	     printf("%06x %-36s*%-16s*\n", line++ * 16, hexArea, chArea);//偏移占6位然后缺失的用0补齐
	     hexArea[0] = '\0';
	     chArea[0] = '\0';
	}
    return 0;
}

15.22.9

#include <stdio.h>
#include <stdlib.h>
int str_str(FILE * fp, char * str);
int main(int argc, char * argv[])
{
	FILE * fp = NULL;
	int i, line;
	if(argc < 2)
	{
		perror("argc < 2");
		exit(1);
	}
	else if(argc == 2)
	{
		fp = stdin;
		if(line = str_str(fp, argv[1]))
			printf("第%d行找到该字符串\n", line);
	}
	for(i = 3; i <= argc; i++)
	{
		if(!(fp = fopen(argv[i - 1], "r")))
		{
			perror("fopen");
			exit(1);
		}
		if(line = str_str(fp, argv[1]))
			printf("%s文件中第%d行找到该字符串\n", argv[i - 1], line);
		if(fclose(fp))
		{
			perror("fclose");
			exit(1);
		}
	}
	return 0;
}
int str_str(FILE * fp, char * str)
{
	int ch;
	int line = 1;
	char * temp = str;
	while((ch = getc(fp)) != EOF)
	{
		while(ch == *str)
		{
			ch = getc(fp);
			str++;
			if(*str == '\0')
				return line;
		}
		if(ch == '\n')
			line++;
	}
	return 0;
}

15.22.10
运行之后发现似乎书上的少了一点 ?

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(int argc, char * argv[])
{
	FILE * fp = NULL, * fp1 = NULL;
	int sign = 0;
	int ch;
	unsigned short int checkNum = 0;
	if(argc == 1)
	{
		while((ch = getchar()) != EOF)
			checkNum += ch;
		printf("checkNum: %hu\n", checkNum);
	}
	else
	{
		if(!strcmp(*(argv + 1), "-f"))
		{
			if(argc == 2)
			{
				printf("-f illegal when reading standard input\n");
               			exit(1);
			}
			sign = 1;
			argv += 2;
		}
		else
			argv += 1;
		char name[30];
		while(*argv)
		{
			if(sign)
			{
				strcpy(name, *argv);
				strcat(name, ".cks");
				if(!(fp1 = fopen(name, "w")))
				{
					perror("fp1");
					exit(1);
				}
			}
			if(!(fp = fopen(*argv, "r")))
			{
				perror("fp");
				exit(1);
			}
			while((ch = getc(fp)) != EOF)
				checkNum += ch;
			if(sign)
			{
				fprintf(fp1, "%s checkNum: %d\n", *argv, checkNum);
				fclose(fp1);
			}
			else
				printf("%s checkNum: %d\n", *argv, checkNum);
			fclose(fp);
			argv++;
		}
	}
	return 0;
}

15.22.11

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef struct
{
	int partnum;
	char desc[21];
	unsigned int quan;
	float price;
	float profit;
	float totalprice;
	int sign;
}part;
int new(char *, FILE *);
int buy(char *, FILE *);
int sell(char *, FILE *);
int delete(char *, FILE *);
int print(char *, FILE *);
void print_all(FILE *);
void total(FILE *);
int main(int argc, char * argv[])
{
	char filename[30];
	if(argc == 1)
		strcpy(filename, "PartData");
	else
		strcpy(filename, argv[1]);
	FILE * fp;
	if((fp = fopen(filename, "rb+")) == NULL)
	{
		if(!(fp = fopen("PartData", "wb+")))
		{
			perror("fp");
			exit(1);
		}
	}
	char temp[41];
	printf("$:");
	while(fgets(temp, 30, stdin))
	{
		if(strncmp(temp, "new", 3) == 0)
		{
			if(new(temp, fp))
				puts("添加成功");
		}
		else if(strncmp(temp, "buy", 3) == 0)
		{
			if(buy(temp, fp))
				puts("添加成功");
		}
		else if(strncmp(temp, "sell", 4) == 0)
		{
			if(sell(temp, fp))
				puts("售卖成功");
		}
		else if(strncmp(temp, "delete", 6) == 0)
		{
			if(delete(temp, fp))
				puts("删除成功");
		}
		else if(strncmp(temp, "print all", 9) == 0)
			print_all(fp);
		else if(strncmp(temp, "print", 5) == 0)
        {
			if(print(temp, fp))
				puts("打印成功");
		}
		else if(strncmp(temp, "total", 5) == 0)
			total(fp);
		else if(strncmp(temp, "end", 3) == 0)
			break;
		else
			puts("无效输入");
		printf("$:");
	}
	puts("Bye!");
	if(fclose(fp))
	{
		perror("fclose");
		exit(1);
	}
	return 0;
}
int new(char * str, FILE * fp)
{
	str += 4;//命令行参数往前移动4个位置
	char desc[21];//创建一个接收零件描述的字符串
	int partnum = 0;//零件号
	unsigned int quan;//零件数量
	float price;//接收零件单价的变量
	if(sscanf(str, "%s , %u , %f\n", desc, &quan, &price) == 3)//从命令行参数中读取我们需要的数据
	{
		rewind(fp);//让文件指针回到开头
		part temp, temp1;//创建2个临时结构变量
		strcpy(temp.desc, desc);//复制字符串到临时变量1
		temp.quan = quan;//接下来的操作就是复制
		temp.price = price;
		temp.totalprice = price * quan;
		temp.sign = 0;
		temp.profit = 0;
		while(fread(&temp1, sizeof(part), 1, fp))//用临时变量2来遍历是否有删除的零件
		{
			if(temp1.sign)
			{
				fseek(fp, -sizeof(part), SEEK_CUR);//找到删除零件 -的目的是回到前一个零件数据
				break;
			}
			partnum++;
		}
		temp.partnum = partnum;
		fwrite(&temp, sizeof(part), 1, fp);
		fflush(fp);//立刻刷新缓冲区写入
		return 1;
	}
	return 0;
}
int buy(char * str, FILE * fp)
{
	str += 4;//命令行参数往前移动4个位置
	int partnum;//零件号
	unsigned int quan;//零件数量
	float price;//接收零件单价的变量
	if(sscanf(str, "%d, %u, %f", &partnum, &quan, &price) == 3)//从命令行参数中读取我们需要的数据
	{
		rewind(fp);//让文件指针回到开头
		part temp;//创建临时结构变量
		while(fread(&temp, sizeof(part), 1, fp))
		{
			if(temp.partnum == partnum)
			{
				fseek(fp, -sizeof(part), SEEK_CUR);
				temp.quan = quan + temp.quan;
				temp.price = price;
				temp.totalprice = price * temp.quan;
				fwrite(&temp, sizeof(part), 1, fp);
				fflush(fp);//立刻刷新缓冲区写入
				return 1;
			}
		}
		return 0;
	}
	return 0;
}
int sell(char * str, FILE * fp)
{
	str += 5;//命令行参数往前移动5个位置
	int partnum;//零件号
	unsigned int quan;//零件数量
	float profit;//接收零件售价的变量
	if(sscanf(str, "%d, %u, %f", &partnum, &quan, &profit) == 3)//从命令行参数中读取我们需要的数据
	{
		rewind(fp);//让文件指针回到开头
		part temp;//创建临时结构变量
		while(fread(&temp, sizeof(part), 1, fp))
		{
			if(temp.partnum == partnum)
			{
				fseek(fp, -sizeof(part), SEEK_CUR);
				temp.totalprice = temp.price * (temp.quan - quan);//总价值等于当前 零件数量 * 零件单价
				temp.profit = (profit - temp.price) * quan;//零件单个利润 * 零件数量
				temp.quan = temp.quan - quan;//改变零件数量
				fwrite(&temp, sizeof(part), 1, fp);
				fflush(fp);//立刻刷新缓冲区写入
				return 1;
			}
		}
		return 0;
	}
	return 0;
}
int delete(char * str, FILE * fp)
{
	str += 7;//命令行参数往前移动7个位置
	int partnum;//零件号
	if(sscanf(str, "%d", &partnum) == 1)//从命令行参数中读取我们需要的数据
	{
		rewind(fp);//让文件指针回到开头
		part temp;//创建临时结构变量
		while(fread(&temp, sizeof(part), 1, fp))
		{
			if(temp.partnum == partnum)
			{
				fseek(fp, -sizeof(part), SEEK_CUR);
				temp.sign = 1;
				fwrite(&temp, sizeof(part), 1, fp);
				fflush(fp);//立刻刷新缓冲区写入
				return 1;
			}
		}
		return 0;
	}
	return 0;
}
int print(char * str, FILE * fp)
{
	str += 6;//命令行参数往前移动7个位置
	int partnum;//零件号
	if(sscanf(str, "%d", &partnum) == 1)//从命令行参数中读取我们需要的数据
	{
		rewind(fp);//让文件指针回到开头
		part temp;//创建临时结构变量
		while(fread(&temp, sizeof(part), 1, fp))
		{
			if(temp.partnum == partnum && temp.sign == 0)
			{
				printf("%10s%10s%10s%10s%10s%10s\n", "零件号", "零件单价", "零件利润", "零件总价值", "零件数量", "零件描述");
				printf("%10d%10f%10f%10f%10d%10s\n", temp.partnum, temp.price, temp.profit, temp.totalprice, temp.quan, temp.desc);
				return 1;
			}
		}
		return 0;
	}
	return 0;
}
void print_all(FILE * fp)
{
	rewind(fp);//让文件指针回到开头
	part temp;//创建临时结构变量
	while(fread(&temp, sizeof(part), 1, fp))
	{
		if(temp.sign == 0)
        {
            printf("%10s%10s%10s%10s%10s%10s\n", "零件号", "零件单价", "零件利润", "零件总价值", "零件数量", "零件描述");
            printf("%10d%10f%10f%10f%10d%10s\n", temp.partnum, temp.price, temp.profit, temp.totalprice, temp.quan, temp.desc);
        }
	}
}
void total(FILE * fp)
{
	float value = 0.0f;
	rewind(fp);//让文件指针回到开头
	part temp;//创建临时结构变量
	while(fread(&temp, sizeof(part), 1, fp))
    {
        if(temp.sign == 0)
            value += temp.totalprice;
    }
	printf("总价值为%f\n", value);
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值