习题9-4 查找书籍 (20 分) | PAT 【结构体,C的三种输入】

题目

给定n本书的名称和定价,本题要求编写程序,查找并输出其中定价最高和最低的书的名称和定价。

输入格式:
输入第一行给出正整数n(<10),随后给出n本书的信息。每本书在一行中给出书名,即长度不超过30的字符串,随后一行中给出正实数价格。题目保证没有同样价格的书。

输出格式:
在一行中按照“价格, 书名”的格式先后输出价格最高和最低的书。价格保留2位小数。

输入样例:

3
Programming in C
21.5
Programming in VB
18.5
Programming in Delphi
25.0

输出样例:

25.00, Programming in Delphi
18.50, Programming in VB

分析

题目不难,主要考察scanf和gets的使用。

scanf详细解答可以参考这篇文章scanf函数的使用

首先想象输入设备(键盘)连接折一个叫做 “缓冲”的东西,把缓冲看作是一个字符数组(不是字符串哦)。
当程序执行到scanf的时候,会从你的缓冲区读东西,如果缓冲区是空的,就阻塞住了,等待你从键盘输入。

scanf()

  1. 忽略先导空白符(空白符:空格符,制表符,回车符)
  2. 在读数据的时候看见空白符就会停止读入数据。

gets() 遇到回车符会停止读入,并将回车符转换成字符结束的标志。

getsscanf对比

  • 功能
    gets只有遇到换行符才会结束读入,scanf遇到空格符、制表符、换行符都会结束读入。
    比如输入一个字符数组: I am a fish\n
    gets 得到的 I am a fish\0
    scanf 得到的 I
  • 停止读入后,处理的方式
    比如 输入 test\nabcde
    执行 gets 后, \n 不会留在缓冲区,这时候调用getchar()得到的是 ‘a’;
    执行 scanf 后, \n 会留在缓冲区,这时候调用getchar()得到的是 ‘\n’。
    这也是为什么之后的程序里在读入n的值之后要用一个 getchar()去吸收掉 换行符的原因了。

在使用VS编译器的时候,还会遇到一个warning

warning C4013: “gets”未定义;假设外部返回 int

因为函数gets是ANSI C中的函数,其在读取时不检查边界,所以可能造成内存访问越界。例如分配了5个字节的空间,但读入了10个字节。

gets函数 在 C11 标准中已被移除.

但是如果忽视warning,使用gets函数,程序也会成功编译 运行成功。

为了安全起见,这里我们可以使用vs C++ 特有的函数 gets_s。

题解

#include <stdio.h>
#include <stdlib.h>

struct Book
{
	char c[31];
	double p;
};
typedef struct Book book;


int main()
{
	int n = 0;
	scanf("%d", &n);
	book* b = (struct Book*)malloc(n * sizeof(struct Book));//动态分配内存 开辟数组
	int i = 0, pmax = 0, pmin = 0;   //假设最大价格最小价格的下标都是 0

	for (i = 0; i < n; i++)
	{
		getchar(); //读入缓冲区的 \n 
		gets(b[i].c); //gets会一直读缓冲区中的字符,直到 \n 停止,把\n改成\0返回
		scanf("%lf", &b[i].p);

		if (b[i].p > b[pmax].p)
			pmax = i;
		if (b[i].p < b[pmin].p)
			pmin = i;
	}

	printf("%.2f, %s\n", b[pmax].p, b[pmax].c);
	printf("%.2f, %s", b[pmin].p, b[pmin].c);

	free(b);
	return 0;
}

在测试代码的时候,还有一个最长字符串的测试点,但是wrong了,然后把存放名字的数组的数组长度改为31就可以通过了。字符串长度不超过30,但是字符串末尾有一个字符串结束的标志符,所以至少需要31个的数组长度。

  • 2
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

JoyCheung-

赏颗糖吃吧~~~

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值