任务描述 本关任务:定义一个包含图书信息(书号、书名、价格)的顺序表,读入相应的图书数据来完成图书信息表的创建,然后根据指定的最爱图书的名字,查找最爱的图书,输出相应图书的信息。 编程要求 输入 总计n+m+2行。首先输入n+1行,其中,第一行是图书数目n,后n行是n本图书的信息(书号、书名、价格),每本图书信息占一行,书号、书名、价格用空格分隔,价格之后没有空格。其中书号和书名为字符串类型,价格为浮点数类型。然后输入m+1行,其中,第一行是一个整数m,代表查找m次,后m行是每次待查找的最爱图书名字。 输出 若查找成功: 总计输出m*(k+1)行,对于每一次查找,第一行是最爱图书数目(同一书名的图书可能有多本),后k行是最爱图书的信息(书号、书名、价格),每本图书信息占一行,书号、书名、价格用空格分隔,其中价格输出保留两位小数。 若查找失败: 只输出以下提示:抱歉,没有你的最爱! 测试说明 平台会对你编写的代码进行测试: 测试输入: 8 9787302257646 Data-Structure 35.00 9787302164340 Operating-System 50.00 9787302219972 Software-Engineer 32.00 9787302203513 Database-Principles 36.00 9787810827430 Discrete-Mathematics 36.00 9787302257800 Data-Structure 62.00 9787811234923 Compiler-Principles 62.00 9787822234110 The-C-Programming-Language 38.00 2 Java-Programming-Language Data-Structure 预期输出: Sorry,there is no your favourite! 2 9787302257646 Data-Structure 35.00 9787302257800 Data-Structure 62.00 帮我用以上的条件补齐下面的代码:#include<iostream> #include<string.h> #include<iomanip> #define OK 1 #define ERROR 0 #define OVERFLOW -2 #define MAXSIZE 1000 //图书表可能达到的最大长度 using namespace std; typedef struct {//图书信息定义 char no[20]; //图书ISBN char name[50]; //图书名字 float price; //图书价格 }Book; typedef struct {//图书表的顺序存储结构类型为SqList Book *elem; //存储空间的基地址 int length; //图书表中当前图书个数 }SqList; int InitList_Sq(SqList &L) {//构造一个空的顺序表L L.elem=new Book[MAXSIZE]; //为顺序表分配一个大小为MAXSIZE的数组空间 if(!L.elem)exit(OVERFLOW); //存储分配失败退出 L.length=0; //空表长度为0 return OK; } int Input_Sq(SqList &L) {//顺序表的输入 int n; cin>>n; //图书数目n for(int i=0;i<n;i++) { cin>>L.elem[i].no>>L.elem[i].name>>L.elem[i].price; L.length++; } return OK; } int FindFavorite_Sq(SqList L) {//最爱图书的查找并输出数据 /**************begin************/ /**************end************/ } int main() { SqList L; //定义一个SqList类型的变量L InitList_Sq(L); //初始化一个空的顺序表L Input_Sq(L); //输入数据 FindFavorite_Sq(L); //最爱图书的查找并输出数据 return 0; }
首先,我得理解程序的要求。输入分为两部分:n本图书的信息,然后m次查找。每次查找需要输出对应书名的所有图书的数量和详细信息,如果没找到则输出提示。
用户给出的代码主函数里调用了FindFavorite_Sq(L),但根据编程要求,输入的m次查找应该是在这个函数里处理。那函数内部需要读取m的值,然后循环处理每个查询。
那在FindFavorite_Sq函数中,第一步应该读取m的值。然后对于每个查询的书名,遍历顺序表,统计匹配的数量,并记录这些图书的位置或信息。之后根据数量是否为0来决定输出什么。
具体步骤:
- 输入m,即查找次数。
- 对于每次查找: a. 输入待查找的书名。 b. 遍历顺序表L的所有元素,比较书名是否相同。 c. 统计匹配的数量,并记录所有匹配的图书的信息。 d. 如果数量为0,输出“抱歉,没有你的最爱!”。 e. 否则,先输出数量,然后依次输出每本书的信息。
需要注意的问题:
- 字符串比较要用strcmp函数,因为书名是char数组,不能直接用==比较。
- 输出价格要保留两位小数,使用fixed和setprecision(2)。
- 每次查找前要重置统计的计数器和存储结构,或者动态记录位置。例如,可以用一个数组保存匹配的索引,或者直接在遍历时输出。但根据输出要求,需要先输出数目,再输出所有条目,所以需要先收集所有匹配的条目,或者两次遍历:第一次统计数量,第二次输出。或者更高效的方式是一次遍历记录所有符合条件的元素的位置。
考虑到MAXSIZE是1000,可以预先定义一个数组来保存匹配的索引。或者,更简单的方式,在第一次遍历时统计数量,然后在第二次遍历时输出符合条件的条目。不过这样需要遍历两次。但因为数据量不大,这样做是可行的。
例如:
对于每个查找的名字:
count = 0; 遍历所有L中的书: 如果书名等于目标,count++ 输出count 如果count>0: 再次遍历,输出每个符合条件的书的信息 否则: 输出提示
或者,可以在一次遍历中收集所有符合条件的元素的下标,然后输出。不过这样可能需要额外的存储空间。但考虑到最多可能有MAXSIZE个元素,用一个数组存储索引是可行的。
不过,对于本题来说,两次遍历可能更简单,因为不需要存储索引,只需在第二次遍历时再次检查条件。这样代码可能更简洁。
那在FindFavorite_Sq函数中,大致流程如下:
输入m。 循环m次: 输入目标书名。 count = 0; for i从0到L.length-1: 如果 strcmp(L.elem[i].name, 目标) ==0 → count++ if count ==0 → 输出抱歉信息。 else: 输出count 再次遍历,将所有匹配的图书的信息输出,价格保留两位小数。
那这样代码的结构就比较清晰了。但需要注意,输入的时候可能会有多个测试用例,比如第一次查找失败,第二次成功,需要分别处理。
现在考虑如何实现输入。在FindFavorite_Sq函数中,首先需要读取m的值,然后循环读取m次书名。例如:
在函数里:
int FindFavorite_Sq(SqList L) { int m; cin >> m; for (int i=0; i<m; i++) { char target[50]; cin >> target; int count =0; // 第一次遍历统计数量 for(int j=0; j<L.length; j++) { if (strcmp(L.elem[j].name, target)==0) { count++; } } if (count ==0) { cout << "Sorry,there is no your favourite!" << endl; } else { cout << count << endl; // 第二次遍历输出 for(int j=0; j<L.length; j++) { if (strcmp(L.elem[j].name, target)==0) { // 输出书号、书名、价格,价格保留两位小数 cout << L.elem[j].no << " " << L.elem[j].name << " " << fixed << setprecision(2) << L.elem[j].price << endl; } } } } return OK; }
这里需要注意的点:
- 输入目标书名的方式:因为书名可能包含空格吗?题目中的测试输入例子中的书名都是不带空格的,比如Data-Structure,所以题目中的输入是用空格分隔的。所以书名的输入可以用cin直接读取,因为cin遇到空格会停止。那这样是否有问题?
比如,用户输入的测试输入中的书名都是不带空格的,比如Data-Structure,所以每个书名在输入的时候用cin读取没问题。但如果书名本身包含空格,比如"Data Structure",那么用cin只能读取到第一个单词,这样就会出错。但题目中的测试用例中的情况应该不会有这种情况,所以假设书名是没有空格的,用cin来读取是没问题的。所以,在代码中,使用cin >> target来读取待查找的书名是正确的。
但是,如果题目中存在书名含有空格的情况,那就会出错。但根据题目给出的测试样例,可能不需要考虑这种情况。所以按照题目的描述,这里应该用cin来读取。
那代码中的处理是正确的。
另外,输出价格的时候需要用fixed和setprecision(2),这需要包含头文件
此外,输出时,每本书的信息占一行,价格保留两位小数,例如35.00,这在测试用例中的输出示例也是这样要求的。
所以,这样的代码应该可以满足要求。
现在检查用户提供的代码是否有其他需要注意的地方。比如,结构体中的char数组是否足够大?题目中的书号长度是例如9787302257646,长度是13,但定义的是char no[20],足够。书名是50字符,测试中的书名如The-C-Programming-Language可能较长,但示例中的可能不超过50字符。所以结构体定义是正确的。
另外,在Input_Sq函数中,输入n后循环n次,每次读取三个数据:no、name、price。这部分是正确的。
现在,将上述逻辑写入代码中的FindFavorite_Sq函数的指定区域。注意代码中的注释部分需要替换。
所以,最终的FindFavorite_Sq函数应该如上述思路编写。
综上,正确的代码应该是在函数内部处理m次查询,每次查询遍历两次链表,第一次统计数量,第二次输出具体信息。```cpp
#include
// 第一次遍历统计匹配数量
for(int j = 0; j < L.length; j++) {
if(strcmp(L.elem[j].name, target) == 0) {
count++;
}
}
if(count == 0) {
cout << "Sorry,there is no your favourite!" << endl;
} else {
cout << count << endl;
// 第二次遍历输出详细信息
for(int j = 0; j < L.length; j++) {
if(strcmp(L.elem[j].name, target) == 0) {
cout << L.elem[j].no << " " << L.elem[j].name << " "
<< fixed << setprecision(2) << L.elem[j].price << endl;
}
}
}
}
return OK;
/**************end************/
} int main() { SqList L; //定义一个SqList类型的变量L InitList_Sq(L); //初始化一个空的顺序表L Input_Sq(L); //输入数据 FindFavorite_Sq(L); //最爱图书的查找并输出数据 return 0; } ```