15.List the Books——列出书籍

本文介绍了一个图书排序程序的设计与实现,程序使用结构体存储图书信息,并通过三种不同的排序标准(名称、年份、价格)对图书进行排序。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Description

Jim is fond of reading books, and he has so many books that sometimes it's hard for him to manage them. So he is asking for your help to solve this problem. Only interest in the name, press year and price of the book, Jim wants to get a sorted list of his books, according to the sorting criteria.

Input

The problem consists of multiple test cases. In the first line of each test case, there's an integer n that specifies the number of books Jim has. n will be a positive integer less than 100. The next n lines give the information of the books in the format Name Year Price. Name will be a string consisting of at most 80 characters from alphabet, Year and Price will be positive integers. Then comes the sorting criteria, which could be Name, Year or Price. Your task is to give out the book list in ascending order according to the sorting criteria in non-ascendent order. Note: That Name is the first criteria, Year is the second, and Price the third. It means that if the sorting criteria is Year and you got two books with the same Year, you'd sort them according to their Name. If they equals again, according to their Price. No two books will be same in all the three parameters. Input will be terminated by a case with n = 0.

Output

For each test case, output the book list, each book in a line. In each line you should output in the format Name Year Price, the three parameters should be seperated by just ONE space. You should output a blank line between two test cases.

Sample Input

3
LearningGNUEmacs 2003 68
TheC++StandardLibrary 2002 108
ArtificialIntelligence 2005 75
Year
4
GhostStory 2001 1
WuXiaStory 2000 2
SFStory 1999 10
WeekEnd 1998 5
Price
0

Sample Output

TheC++StandardLibrary 2002 108
LearningGNUEmacs 2003 68
ArtificialIntelligence 2005 75

GhostStory 2001 1
WuXiaStory 2000 2
WeekEnd 1998 5
SFStory 1999 10

中文翻译:

描述

吉姆喜欢读书,他有很多书,有时他很难管理。所以他要求你的帮助来解决这个问题。根据分类标准,吉姆只想对书籍的名称,印刷年份和价格感兴趣,希望得到他的书籍的分类清单。

输入

问题包括多个测试用例。在每个测试用例的第一行中,有一个整数n,它指定了Jim拥有的书籍数量。n将是一个小于100的正整数。接下来的n行以Name Year Price格式给出书籍的信息。名称将是一个字符串,由字母表中的最多80个字符组成,Year和Price将为正整数。然后是排序标准,可以是姓名,年份或价格。您的任务是根据非上升顺序的排序标准按升序发出图书清单。注意:该名称是第一个标准,年份是第二个,价格是第三个。这意味着如果排序标准是年份并且您有两本同一年份的书籍,您可以根据他们的名称对它们进行排序。如果他们再次等于他们的价格。在这三个参数中,没有两本书是相同的。输入将由n = 0的情况终止。

产量

对于每个测试用例,输出书籍列表,每本书都在一行中。在每行中,您应该以Name Year Price格式输出,这三个参数应该只分隔一个空格。您应该在两个测试用例之间输出一个空行。

样本输入

3 
LearningGNUEmacs 2003 68 
TheC ++ StandardLibrary 2002 108 
ArtificialIntelligence 2005 75 
Year 
4 
GhostStory 2001 1 
WuXiaStory 2000 2 
SFStory 1999 10 
WeekEnd 1998 5 
Price 
0

样本输出

TheC ++ StandardLibrary 2002 108 
LearningGNUEmacs 2003 68 
ArtificialIntelligence 2005 75 

GhostStory 2001 1 
WuXiaStory 2000 2 
WeekEnd 1998 5 
SFStory 1999 10

对于这道题,题目中描述了一本书包含了三个信息,首先想到的是利用结构体来进行存储,这样方便在接下来进行排序,整个题很简单,但是代码比较繁琐,尤其是在按照题目要求的三种排序方式上的处理需要写三个sort来进行操作。

#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include<iostream>
#include<algorithm>
using namespace std;
struct B
{
    string a;
    int year;
    int price;
} b[101];
bool cmp1(B a,B b)
{
       if(a.a!=b.a)
        return a.a<b.a;
    else if(a.year!=b.year)
        return a.year<b.year;
    else
        return a.price<b.price;

}
bool cmp2(B a,B b)
{
     if(a.year!=b.year)
        return a.year<b.year;
    else if(a.a!=b.a)
        return a.a<b.a;
    return a.price<b.price;

}
bool cmp3(B a,B b)
{
    if(a.price!=b.price)
        return a.price<b.price;
    else if(a.a!=b.a)
        return a.a<b.a;
    return a.year<b.year;

}
int main()
{
    int i,j,k=1,n;
    string c;
    while(scanf("%d",&n)!=EOF)
    {
        if(n==0)
            break;
        for(i=0; i<=n-1; i++)
            cin>>b[i].a>>b[i].year>>b[i].price;
        cin>>c;
        if(c=="Name")
            {
                sort(b,b+n,cmp1);
            }
        if(c=="Year")
            {
                sort(b,b+n,cmp2);
            }
        if(c=="Price")
            {
                sort(b,b+n,cmp3);
            }
        if(k)
            k=0;
        else
            cout<<endl;
        for(i=0; i<=n-1; i++)
            cout<<b[i].a<<" "<<b[i].year<<" "<<b[i].price<<endl;
    }
}

 

<think>根据用户描述,他有一个字符串,内容为: "Image Height(mm)MTF0.428000.29960 -0.00114-0.29960-0.42800LegendTan100(lp/ mm)0.5990.6770.6680.7030.645— ——Sag100(lp /mm)0.5580.6590.6730.6880.642————"并且希望将其分割成四行,每行对应一个部分:第一行:"ImageHeight(mm)"第二行: "MTF0.428000.29960 -0.00114 -0.29960 -0.42800Legend"第三行:"Tan100(lp/ mm)0.5990.6770.6680.7030.645— ——"第四行:"Sag100(lp /mm)0.5580.6590.6730.6880.642————"但是观察字符串,实际上没有明确的分隔符。用户希望按照他提供的四个部分进行分割。然而,从字符串中我们可以看到,每一行的开始都有特定的关键字:第一行:"ImageHeight(mm)"第二行: "MTF" (紧接着第一行后面)第三行:"Tan" (紧接着第二行后面的"Legend"之后)第四行:"Sag"因此,我们可以通过寻找这些关键字来分割字符串。但是注意,第二行末尾有"Legend",第三行以"Tan"开头,第四行以"Sag"开头。具体步骤:1.第一行:从开头到"Image Height(mm)"结束,即字符串的前17个字符(因为"Image Height(mm)"长度为17)?但实际上,我们不知道具体长度,所以我们可以用字符串"MTF"作为第一行的结束标志?但是第一行后面紧跟着"MTF",所以我们可以这样:第一行:从0到"MTF"之前的索引,但是注意第一行是"ImageHeight(mm)",后面没有空格,直接跟了"MTF",所以我们可以定位到"ImageHeight(mm)"的结尾位置。2.但是,我们也可以使用正则表达式,通过匹配关键字来分割。然而,用户要求使用Qt(C++)来处理,所以我们可以用QString的成员函数。思路:我们已知四个部分的起始关键字分别是:"Image Height(mm)"、"MTF"、"Tan"、"Sag"。注意,第二行以"MTF"开始,第三行以"Tan"开始,第四行以"Sag"开始。但是,第一行是"Image Height(mm)",后面没有空格,紧接着是"MTF",所以我们可以这样分割:步骤:1.找到第一个关键字"Image Height(mm)",它从0开始,长度为len1 =17(注意:字符串中确实是17个字符,包括括号)。然后,第一行就是子串(0,17)。2.剩下的字符串从索引17开始,然后我们找到下一个关键字"Tan",因为第二行是从"MTF"开始,直到"Legend"结束,然后紧接着是"Tan"。但是注意,第二行中包含"Legend",然后紧接着是"Tan",所以我们可以用"Tan"来分割第二行和第三行。3.同样,第三行后面紧跟着"Sag",所以我们可以用"Sag"来分割第三行和第四行。但是,第二行内部也有数字和横杠,我们需要确保在分割时不会错误地将内部内容分割。具体实现:由于字符串中已经明确出现了这些关键字,我们可以这样:QString original= "Image Height(mm)MTF0.428000.29960 -0.00114 -0.29960 -0.42800LegendTan100(lp /mm)0.5990.6770.6680.7030.645—— —Sag100(lp/ mm)0.5580.6590.6730.6880.642————";1.第一行:我们已知"Image Height(mm)"的长度是17,所以:line1 =original.left(17);2.然后,剩下的字符串从第17个字符开始:remaining= original.mid(17);3.在remaining中,我们需要找到"Tan"的位置,但是注意,第二行是从"MTF"开始,到"Legend"结束,然后紧接着"Tan"。所以我们在remaining中查找"Tan",注意这个"Tan"是第三行的开始。但是,注意第三行的开始是"Tan100(lp /mm)",所以我们可以查找"Tan"(带空格)以避免可能的歧义。4.同样,在第三行中查找第四行的开始"Sag"(带空格)。所以,我们可以:int indexTan =remaining.indexOf("Tan");int indexSag= remaining.indexOf("Sag");但是,注意第二行是从索引0(即remaining的0)到indexTan之前,第三行是从indexTan到indexSag之前,第四行是从indexSag到结束。因此:line2 =remaining.left(indexTan);line3= remaining.mid(indexTan, indexSag- indexTan);line4 =remaining.mid(indexSag);但是,这里有一个问题:第二行中是否可能出现"Tan"或"Sag"?根据内容,第二行是"MTF0.428000.29960 -0.00114 -0.29960-0.42800Legend",其中没有"Tan "或"Sag ",所以可以这样分割。然而,我们为了确保准确,可以加上空格匹配,因为第三行和第四行的关键字后面都有空格。代码实现: ```cpp#include <QString> #include<QDebug>int main() {QStringoriginal ="ImageHeight(mm)MTF0.428000.29960 -0.00114 -0.29960 -0.42800LegendTan100(lp/ mm)0.5990.6770.6680.7030.645— ——Sag100(lp /mm)0.5580.6590.6730.6880.642————";//第一行:固定长度17QString line1 =original.left(17);QStringremaining =original.mid(17);//查找第三行的起始位置,即"Tan "(注意带空格)intindexTan= remaining.indexOf("Tan ");//查找第四行的起始位置,即"Sag"(注意带空格)int indexSag= remaining.indexOf("Sag");//如果找不到,则处理错误if(indexTan ==-1|| indexSag== -1){qDebug() <<"Error: cannotfind Tanor Sag";return -1;}//第二行:从0到indexTanQStringline2= remaining.left(indexTan);//第三行:从indexTan到indexSag -indexTanQString line3 =remaining.mid(indexTan,indexSag -indexTan);//第四行:从indexSag到结束QStringline4= remaining.mid(indexSag);//输出结果qDebug()<< "Line1:"<< line1;qDebug()<< "Line2:"<< line2;qDebug()<< "Line3:"<< line3;qDebug()<< "Line4:"<< line4;return0; }```但是,注意第三行和第四行的关键字我们保留了空格,所以分割出来的第三行开头是"Tan ",第四行开头是"Sag ",这符合要求。然而,我们还需要考虑一个问题:第二行中是否包含"Tan"?根据字符串,第二行是"MTF0.428000.29960 -0.00114 -0.29960 -0.42800Legend",其中没有"Tan ",所以安全。但是,如果数据变化,这种方法可能不够健壮。另一种方法是使用正则表达式匹配,但用户要求用Qt,且字符串格式固定,所以上述方法可行。运行结果预期:Line1: "Image Height(mm)"Line2:"MTF0.428000.29960-0.00114-0.29960-0.42800Legend"Line3:"Tan100(lp/ mm)0.5990.6770.6680.7030.645— ——"Line4:"Sag100(lp /mm)0.5580.6590.6730.6880.642————"注意:第三行末尾有" —— —",第四行末尾有"————",这些都被保留。但是,注意第二行中,在"Legend"后面紧接着"Tan",我们通过查找"Tan"(带空格)避免了将"Legend"中的字符误判为"Tan"。如果数据中可能出现没有空格的情况,则需要调整。但根据用户提供的字符串,第三行和第四行的关键字后面都有空格。因此,上述代码可以正确分割。但是,如果原始字符串中"Image Height(mm)"的长度不是17,那么我们需要动态获取。实际上,我们可以搜索"MTF"来作为第一行的结束,因为第一行后面紧跟着"MTF"。但是注意,第一行是"ImageHeight(mm)",后面没有空格,所以我们可以这样:int indexImageEnd= original.indexOf("MTF");if (indexImageEnd ==-1) {...错误处理... }line1 =original.left(indexImageEnd);remaining= original.mid(indexImageEnd);//这样remaining以"MTF"开头然后,在remaining中查找"Tan ",注意此时remaining中第二行是以"MTF"开头的,所以查找"Tan "不会受到第一行影响。修改后的代码: ```cpp#include <QString> #include<QDebug>int main() {QStringoriginal ="ImageHeight(mm)MTF0.428000.29960-0.00114-0.29960-0.42800LegendTan100(lp/ mm)0.5990.6770.6680.7030.645— ——Sag100(lp /mm)0.5580.6590.6730.6880.642————";//找到第一行结束的位置(即"MTF"的开始位置)int indexMTF= original.indexOf("MTF");if (indexMTF ==-1) {qDebug()<< "Error:cannot findMTF";return -1;}QStringline1= original.left(indexMTF);QStringremaining =original.mid(indexMTF);//查找第三行的起始位置,即"Tan"(注意带空格)int indexTan =remaining.indexOf("Tan");//查找第四行的起始位置,即"Sag "(注意带空格)int indexSag= remaining.indexOf("Sag");if(indexTan ==-1|| indexSag== -1){qDebug() <<"Error: cannotfind Tanor Sag";return -1;}QStringline2= remaining.left(indexTan);QStringline3= remaining.mid(indexTan, indexSag- indexTan);QStringline4= remaining.mid(indexSag);qDebug()<< "Line1:"<< line1;qDebug()<< "Line2:"<< line2;qDebug()<< "Line3:"<< line3;qDebug()<< "Line4:"<< line4;return0; }```这样更健壮,因为即使"Image Height(mm)"的长度变化,我们也能正确分割。运行结果:Line1:"ImageHeight(mm)"Line2: "MTF0.428000.29960 -0.00114 -0.29960 -0.42800Legend"Line3: "Tan100(lp /mm)0.5990.6770.6680.7030.645—— —"Line4: "Sag100(lp/ mm)0.5580.6590.6730.6880.642————"注意:第三行和第四行开头有空格(因为查找时用了"Tan "和"Sag ",分割时保留了空格),如果不需要开头的空格,可以在分割后去除,但这里原字符串中关键字后面有空格,所以保留。如果希望去除每行开头和结尾的空格,可以使用`trimmed()`函数,但根据需求,我们是要保留原格式,所以不进行去除。因此,这个解决方案可以满足要求。注意:如果数据中可能没有空格(例如"Tan100"),那么我们需要调整查找的字符串(比如去掉空格),但根据用户提供的字符串,是有空格的。如果用户提供的数据格式发生变化,可能需要调整关键字。所以,我们假设数据格式是固定的。最后,将分割后的四行存储到QStringList中,或者直接使用四个QString变量。以上代码在Qt环境中可以运行。注意:如果字符串中没有空格,我们可以尝试匹配"Tan"而不带空格,但这样可能会在第二行中误匹配(例如第二行中的某个数字部分出现"Tan")。但根据用户提供的数据,第二行中没有"Tan",所以可以。但为了安全,我们使用带空格的版本。如果确实没有空格,那么我们可以考虑匹配"Tan100"?但这样也不可靠,因为第三行是"Tan100(lp /mm)",中间有空格。所以,我们使用"Tan "(注意后面有空格)是合理的。同样,第四行使用"Sag "。因此,代码如上。如果用户希望更灵活,可以使用正则表达式,但这里用QString的查找函数已经足够。输出结果:Line1:"ImageHeight(mm)"Line2:"MTF0.428000.29960-0.00114-0.29960-0.42800Legend"Line3: "Tan100(lp /mm)0.5990.6770.6680.7030.645—— —"Line4:"Sag100(lp /mm)0.5580.6590.6730.6880.642————"符合要求。注意:第二行中,在"MTF"后面没有空格,直接跟数字,这是原字符串的格式,我们保留了。所以,这个方案是可行的。</think>### 解决方案:分割固定格式的字符串 您需要将一个连续字符串分割成四行,每行对应特定的数据段。根据您的描述,字符串结构如下: ``` Image Height(mm)MTF0.428000.29960 - 0.00114 - 0.29960 - 0.42800LegendTan 100(lp / mm)0.5990.6770.6680.7030.645— — —Sag 100(lp / mm)0.5580.6590.6730.6880.642———— ``` 需要分割为: 1. `Image Height(mm)` 2. `MTF0.428000.29960 - 0.00114 - 0.29960 - 0.42800Legend` 3. `Tan 100(lp / mm)0.5990.6770.6680.7030.645— — —` 4. `Sag 100(lp / mm)0.5580.6590.6730.6880.642————` 以下是使用Qt/C++实现的解决方案: ```cpp #include <QString> #include <QStringList> #include <QDebug> QStringList splitTableData(const QString& data) { QStringList result; // 1. 定位第一行结束位置(Image Height(mm)) int imageEnd = data.indexOf("MTF"); if (imageEnd == -1) return QStringList(); // 未找到标识符 // 提取第一行 result << data.left(imageEnd).trimmed(); // 2. 定位第二行结束位置(Legend后) int legendEnd = data.indexOf("Tan", imageEnd); if (legendEnd == -1) return QStringList(); // 提取第二行(从MTF到Legend) result << data.mid(imageEnd, legendEnd - imageEnd).trimmed(); // 3. 定位第三行结束位置(— — —后) int tanEnd = data.indexOf("Sag", legendEnd); if (tanEnd == -1) return QStringList(); // 提取第三行(从Tan到— — —) result << data.mid(legendEnd, tanEnd - legendEnd).trimmed(); // 4. 提取第四行剩余部分 result << data.mid(tanEnd).trimmed(); return result; } // 使用示例 int main() { QString data = "Image Height(mm)MTF0.428000.29960 - 0.00114 - 0.29960 - 0.42800LegendTan 100(lp / mm)0.5990.6770.6680.7030.645— — —Sag 100(lp / mm)0.5580.6590.6730.6880.642————"; QStringList lines = splitTableData(data); if (lines.size() == 4) { qDebug() << "Line 1:" << lines[0]; qDebug() << "Line 2:" << lines[1]; qDebug() << "Line 3:" << lines[2]; qDebug() << "Line 4:" << lines[3]; } else { qDebug() << "分割失败,请检查数据格式"; } return 0; } ``` ### 代码解释: 1. **关键标识符定位**: - `MTF`:标识第一行结束和第二行开始 - `Tan`:标识第二行结束和第三行开始 - `Sag`:标识第三行结束和第四行开始 2. **分割逻辑**: - `indexOf()`:查找关键标识符的位置 - `left()`:截取字符串开头部分 - `mid()`:截取字符串中间部分 - `trimmed()`:移除首尾空白字符 3. **错误处理**: - 检查每个关键标识符是否存在 - 返回空列表表示分割失败 4. **输出示例**: ``` Line 1: "Image Height(mm)" Line 2: "MTF0.428000.29960 - 0.00114 - 0.29960 - 0.42800Legend" Line 3: "Tan 100(lp / mm)0.5990.6770.6680.7030.645— — —" Line 4: "Sag 100(lp / mm)0.5580.6590.6730.6880.642————" ``` ### 增强方案(处理格式变化): 如果数据格式可能变化,可以使用更灵活的正则表达式方法: ```cpp #include <QRegularExpression> QStringList regexSplitTableData(const QString& data) { QRegularExpression re( "(Image Height\\(mm\\))" // 第一行 "(MTF[\\d\\s\\-\\.]+Legend)" // 第二行 "(Tan[\\d\\s\\-\\./]+— — —)" // 第三行 "(Sag[\\d\\s\\-\\./]+————)" // 第四行 ); QRegularExpressionMatch match = re.match(data); if (match.hasMatch()) { return { match.captured(1).trimmed(), match.captured(2).trimmed(), match.captured(3).trimmed(), match.captured(4).trimmed() }; } return QStringList(); } ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值