20201022-成信大-C语言程序设计-20201学期《C语言程序设计B》C-trainingExercises31
P312
测试数据文件:请先登录-成信大-计算中心,再点击此链接,可能校外用户无法访问
/*
编写一程序P312.C实现以下功能
有一存储很多商品数据(每件商品的属性先后包括:
品名、规格、数量、单价,编程时相应的数据类型分别定义为字符串char(20)、字符串char(12)、long、float)的二进制文件sp.dat(即未作任何格式转换
而直接使用fwrite将商品属性写入文件),从键盘输入某种商品的品名,要求在文件中查找有无相应品名商品(可能有多条记录或没有),若有则在屏幕上显示
出相应的商品的品名、规格、数量、单价(显示时,品名、规格、数量、单价之间使用逗号(,)作分隔),若无则显示没有相应品名的商品。
单击此处下载程序运行时测试用的商品数据文件sp.dat并保存到程序P312.C所在的文件夹且文件名保持不变。
编程可用素材:
printf("Please input shang pin pin ming:");
printf("\ncha zhao qing kuang:\n");
printf("mei you shang pin :%s",inputName);
程序的运行效果应类似地如图1和图2所示,
图1中的Please input shang pin pin ming:xuebi中的xuebi
图2中的Please input shang pin pin ming:kele中的kele是从键盘输入的内容。
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define N 100
// 字符串char(20)、字符串char(12)、long、float
// 品名、规格、数量、单价
typedef struct goods
{
char name[20];
char size[12];
long count;
float price;
} GOODS;
void printGoods(GOODS goods);
int checkSameGoods(GOODS goods1, GOODS goods2);
void copyGoods(GOODS src, GOODS *dst);
void printGoodsArr(GOODS *goods, int n);
int main(void)
{
FILE *fp;
char name[20];
char inputName[20];
char size[12];
long count;
float price;
GOODS goods[N];
GOODS goodsPrint[N];
int i = 0, cnt1, j, cnt2;
int flag1 = 0; // 有无商品的标记
fp = fopen("sp.dat", "rb");
if (fp == NULL)
{
printf("open file error! \n");
exit(0);
}
printf("Please input shang pin pin ming:");
scanf("%s", inputName);
printf("\ncha zhao qing kuang:\n");
// while(!feof(fp))// 这样不好,会多读一次
/*
原因:
feof(file) 的作用是检测读取到的数据是否为文件结束。读完最后一行记录后,file->_flag 没有被置为_IOEOF,
因为已经读取到记录了, feof() 没有探测到文件结尾。
直到再次调用 fread()读取记录时,才获取文件结束标志,feof() 探测到文件结尾。
现象:
当再次调用 fread(内存地址,地址大小,1,fp); 时,“内存地址”里没有获取任何内容,还是上次读取的数据,输出时,当然是跟上次一样。
*/
while(fread(name, sizeof(name), 1, fp))// fread返回0,表示文件结束或是出错了
{
// fscanf(fp, "%s%s%ld%f", name, size, &count, &price); 当用fwrite写入时,使用fread来读
// 1 读入数据到内存
// fread(name, sizeof(name), 1, fp); // 已经在判断时读入了,拿返回值任务为循环条件
fread(size, sizeof(size), 1, fp);
fread(&count, sizeof(long), 1, fp);
fread(&price, sizeof(float), 1, fp);
// 2 封装数据到结构,并装入商品数组中
strcpy(goods[i].name, name);
strcpy(goods[i].size, size);
goods[i].count = count;
goods[i].price = price;
// printGoods(goods[i]);
i++;
}
cnt1 = i;
// 比对,看有无相应的商品名
j = 0;
for ( i = 0; i < cnt1; i++)
{
if (strcmp(goods[i].name,inputName) == 0)
{
flag1 = 1;
copyGoods(goods[i], &goodsPrint[j]);
j++;
}
}
cnt2 = j;
if (flag1) // 打印唯一的商品记录
{
printGoodsArr(goodsPrint, cnt2);
}
else // 如果没有找到,直接打印结果
{
printf("mei you shang pin :%s",inputName);
}
if (fp != NULL)
{
fclose(fp);
}
return 0;
}
/*
打印商品,一行
*/
void printGoods(GOODS goods)
{
printf("%s,%s,%ld,%.2f\n", goods.name, goods.size, goods.count, goods.price);
}
/*
检查两个商品是否一样
*/
int checkSameGoods(GOODS goods1,GOODS goods2)
{
if (strcmp(goods1.name,goods2.name)==0
&& strcmp(goods1.size,goods2.size)==0
&& goods1.count == goods2.count
&& goods1.price == goods2.price)
{
return 1;
}
else
{
return 0;
}
}
/*
复制商品
*/
void copyGoods(GOODS src, GOODS *dst)
{
strcpy(dst->name, src.name);
strcpy(dst->size, src.size);
dst->count = src.count;
dst->price = src.price;
}
/*
唯一打印商品,针对有重复记录的商品数组
*/
void printGoodsArr(GOODS *goods, int n) // 不重复的打印商品
{
int i, j;
int flag2;
printGoods(goods[0]); // 首条一定会打印
for ( i = 1; i < n; i++)
{
flag2 = 0; // 事先都认为没有打印过
for ( j = 0; j < i; j++)
{
if (checkSameGoods(goods[i],goods[j]))
{
flag2 = 1;
break;
}
}
if (flag2==0)
{
printGoods(goods[i]);
}
}
}
P264
/*
编写一程序P264.C实现以下功能
从命令行输入四个字符串,格式为:P264 串1 串2 串3 串4,按示例格式倒序输出这4个字符串。
提示与注意事项:
(1)当命令行格式不正确(参数个数不为5)时,应报错。
(2)程序的返回值(即由main函数return的值和程序使用exit终止运行时返回的值,也称退出代码)规定为:
①正常运行结束时,返回0 ②命令行格式不对返回29
(3)编程可用素材:
printf(" usage: P264 串1 串2 串3 串4\n");
printf(" 串4=%s 串3=%s 串2=%s 串1=%s\n", argv[4], argv[3], argv[2], argv[1]);
E:\Debug>P264 a278 100.123 cx5001.789 hwtcasc345
串4=hwtcasc345 串3=cx5001.789 串2=100.123 串1=a278
E:\Debug>P264 no Err ok?
usage: P264 串1 串2 串3 串4
*/
#include <stdio.h>
#include <stdlib.h>
int main(int argc, char *argv[])
{
if (argc != 5)
{
printf(" usage: P264 串1 串2 串3 串4\n");
exit(29);
}
else
{
printf(" 串4=%s 串3=%s 串2=%s 串1=%s\n", argv[4], argv[3], argv[2], argv[1]);
}
return 0;
}
P119
#include <stdio.h>
#include <stdlib.h>
/*
从命令行输入三个数,格式为:P119 数1 数2 数3,输出“数1 + (数2 + 数3) ÷ 2”之值且保留3位小数。
提示与注意事项:
(1)库函数提示:atoi, atof。
(2)当命令行格式不正确(参数个数不为4)时,应报错。
(3)程序的返回值(即由main函数return的值和程序使用exit终止运行时返回的值,也称退出代码)规定为:
①正常运行结束时,返回0 ②命令行格式不对返回8
(4)编程可用素材:printf(" usage: P119 num1 num2 num3\n")、printf(" … + (… + …) / 2 = …\n"…。
*/
int main(int argc,char *argv[])
{
int num1;
double num2, num3;
double result;
if (argc != 4)
{
printf(" usage: P119 num1 num2 num3\n");
exit(8);
}
else
{
num1 = atoi(argv[1]); // 字符串转为数值
num2 = atof(argv[2]);
num3 = atof(argv[3]);
result = num1 + (num2 + num3) / 2;
printf(" %d + (%.3lf + %.3lf) / 2 = %.3lf\n", num1, num2, num3, result);
exit(0);
}
return 0;
}
P267
/*
编写一程序P267.C实现以下功能
从命令行输入两个数(只需考虑整数),格式为:P267 数1 数2,按示例格式由小到大输出这两个数。
提示与注意事项:
(1)库函数提示:atoi。
(2)当命令行格式不正确(参数个数不为3)时,应报错。
(3)程序的返回值(即由main函数return的值和程序使用exit终止运行时返回的值,也称退出代码)规定为:
①正常运行结束时,返回0
②命令行格式不对 返回22
(4)编程可用素材:
printf(" usage: P267 num1 num2\n");
printf(" 由小到大: %d %d\n",min,max);
E:\Debug>P267 1001 800
由小到大: 800 1001
E:\Debug>P267 999
usage: P267 num1 num2
*/
#include <stdio.h>
#include <stdlib.h>
int main(int argc, char *argv[])
{
int min, max;
int tmp;
if (argc != 3)
{
printf(" usage: P267 num1 num2\n");
exit(22);
}
else
{
min = atoi(argv[1]);
max = atoi(argv[2]);
if (min>max)
{
tmp = max;
max = min;
min = tmp;
}
printf(" 由小到大: %d %d\n",min,max);
}
return 0;
}