C++中用scanf读入string以及输出

本文详细介绍了使用C++进行字符串操作的方法,包括定义、读取和输出字符串的具体实现。通过实例讲解了如何调整字符串大小,如何使用scanf读取字符串,以及如何用printf和cout进行输出。对于使用cout输出时,默认使用空格补全定义时的size这一细节也进行了说明。

定义:

string id;
id.resize(15);

读入:

scanf("%s", &id[0]);

输出:

printf("%s", id.c_str());

若用cout输出,则会默认用空格补全定义时的size。

<think>题目要求:多组测试数据,每组数据第一行是整数n,然后n行,每行是一个字符串(教学楼名称)和一个非负实数(高度)。我们需要根据高度从小到大排序,然后输出排序后的教学楼名称,以空格分隔。 思路: 1. 使用循环来处理多组数据,直到文件结束。 2. 对于每组数据: a. 读取整数n。 b. 读取n行,每行一个字符串和一个浮点数。 c. 将每行的数据存储在一个结构体(或对象)中,包含名称和高度。 d. 根据高度对这些结构体进行升序排序。 e. 按顺序输出结构体中的名称,用空格分隔。 编程语言选择:这里我将使用C++和Java分别实现,因为题目中提到了C/C++和Java的输入方式。 但是题目要求只输出教学楼名称,并且按高度升序排序。 注意:题目要求多组数据,且每组数据输出一行。 由于题目没有明确说明,但示例输出中,第一组输出两个名称,第二组输出三个名称,且都是按高度升序排列。 示例输入第一组: 2 yijiao 1.2 erjiao 1.1 排序后:erjiao(1.1) < yijiao(1.2) -> 输出 "erjiao yijiao" 第二组: 3 sijiao 2.3 liujiao 5.2 wujiao 4.71 排序后:sijiao(2.3) < wujiao(4.71) < liujiao(5.2) -> 输出 "sijiao wujiao liujiao" 注意:题目要求非负实数,所以用double类型存储。 实现: C++实现: 使用vector和pair,或者自定义结构体,然后使用sort函数排序。 由于题目要求读取到文件结束,因此使用while循环读取n,直到遇到EOF。 具体步骤: while (scanf("%d", &n) != EOF) { vector<pair<string, double>> buildings; 或者用结构体vector 然后循环n次,读取字符串和浮点数。 注意:浮点数在输入时,用%lf读取,但C++的cin也可以,但题目要求用scanf,所以用C风格。 但是字符串是长度小于20的,所以可以用char数组,也可以使用string(然后用cin读,但混合输入要注意)。 由于题目没有限定输入方式,我们两种都可以,但考虑到多组数据且要求处理到文件结束,建议使用C风格读字符串以避免缓冲区问题。 然而,题目说输入格式是:每组数据第一行有一个数n,然后是n行,每行有一个字符串和一个非负实数。 我们可以这样读: for (int i=0; i<n; i++) { char name[25]; double height; scanf("%s %lf", name, &height); 然后存入vector } 然后使用sort函数,自定义比较函数(按高度升序)。 最后遍历vector,输出每个元素的字符串,注意空格分隔(最后一个后面没有空格,但题目要求一行内以空格分割,所以可以用循环控制输出空格)。 另一种方法:使用结构体,然后重载比较运算符,或者写一个比较函数。 例如: struct Building { string name; double height; }; 然后写比较函数: bool cmp(const Building &a, const Building &b) { return a.height < b.height; } 然后 sort(vec.begin(), vec.end(), cmp); 输出时,注意空格:第一个名称单独输出,后面的先输出空格再输出名称;或者全部输出后最后一个不带空格。我们可以用一个循环,从第一个到最后一个,第一个不输出空格,后面每个前面输出空格。或者使用一个flag,但最简单的是: for (int i=0; i<vec.size(); i++) { if (i>0) cout << " "; cout << vec[i].name; } cout << endl; 但是题目要求每组数据输出一行。 注意:题目要求输出名称,而且输入中名称是连续的字符串(没有空格),所以用scanf的%s读取没问题。 但是注意:使用C++string可能会更方便,而且题目说字符串长度小于20,所以用char数组也可以。 这里给出两种方式,为了通用性,我使用string(因为题目没有说不能用C++string,且C++string更方便)。 但是注意:如果使用string,在C++中使用cin读取,但是当与scanf混用时,要注意输入缓冲区的问题。因为第一行读取n时用了scanf,后面使用cin会出错吗?不会,因为第一行scanf读取n后,换行符还在,而cin读字符串会自动跳过空白字符(包括换行符和空格)。所以可以混合使用。 但是为了安全,也可以统一使用C风格。 由于题目要求多组数据,并且输入量不大(每组最多20个,但组数少于20组),所以性能不是问题。 我选择使用cin和cout,但要注意:cin和cout可能会慢,但数据量小可以接受。如果使用ios::sync_with_stdio(false)可以加速。 但是题目要求输入多组,且处理到文件结束。所以我们可以使用: ios::sync_with_stdio(false); cin.tie(0); 但是题目没有要求速度,而且数据量很小,所以可以不用。 下面给出C++代码: 注意:由于题目要求多组测试数据,且每组数据的n可能不同,我们需要在每组数据开始重新定义一个vector。 代码框架: #include <iostream> #include <vector> #include <algorithm> #include <cstdio> // 如果使用scanf,则要包含这个,但这里我们使用cin using namespace std; struct Building { string name; double height; }; bool cmp(Building a, Building b) { return a.height < b.height; } int main() { int n; while (cin >> n) { // 读取n,直到遇到文件结束 vector<Building> buildings; for (int i=0; i<n; i++) { string name; double height; cin >> name >> height; buildings.push_back({name, height}); } sort(buildings.begin(), buildings.end(), cmp); for (int i=0; i<buildings.size(); i++) { if (i>0) cout << " "; cout << buildings[i].name; } cout << endl; } return 0; } 但是题目中有多组数据,我们使用cin读n,当遇到文件结束,cin会返回false,从而退出循环。 然而,题目没有说明输入方式,但示例输入是标准的。因此,上述代码可以。 但是,在C++中,使用while(cin>>n)可以处理到文件结束。 另外,题目要求少于20组,所以没问题。 但是,有时候在比赛中,使用C++的cin和cout可能比scanf和printf慢,但这里数据量很小,所以没关系。 下面再给出使用C语言风格的C++代码(使用scanf和printf,避免缓冲区问题): #include <iostream> #include <cstdio> #include <vector> #include <cstring> #include <algorithm> using namespace std; struct Building { char name[25]; double height; }; bool cmp(Building a, Building b) { return a.height < b.height; } int main() { int n; while (scanf("%d", &n) != EOF) { vector<Building> buildings; for (int i=0; i<n; i++) { Building b; scanf("%s %lf", b.name, &b.height); buildings.push_back(b); } sort(buildings.begin(), buildings.end(), cmp); for (int i=0; i<buildings.size(); i++) { if (i>0) printf(" "); printf("%s", buildings[i].name); } printf("\n"); } return 0; } 两种方式都可以。这里我选择第二种,因为题目输入描述中使用了scanf,避免混合输入。 但是注意:结构体中用char数组,这样使用scanf读入字符串是安全的,因为题目说长度小于20,所以25的数组足够。 现在给出Java的解决方案: Java:使用Scanner,然后处理多组数据。 题目提示:Java语言可以用: while (scanner.hasNext()) { n = scanner.nextInt(); // 处理本组的n行数据 } 具体步骤: import java.util.*; class Building { String name; double height; public Building(String name, double height) { this.name = name; this.height = height; } } public class Main { public static void main(String[] args) { Scanner scanner = new Scanner(System.in); while (scanner.hasNext()) { int n = scanner.nextInt(); List<Building> list = new ArrayList<>(); for (int i=0; i<n; i++) { String name = scanner.next(); double height = scanner.nextDouble(); list.add(new Building(name, height)); } // 根据高度排序 Collections.sort(list, new Comparator<Building>() { @Override public int compare(Building o1, Building o2) { // 升序 if (o1.height < o2.height) { return -1; } else if (o1.height > o2.height) { return 1; } else { return 0; } } }); // 输出 for (int i=0; i<list.size(); i++) { if (i>0) { System.out.print(" "); } System.out.print(list.get(i).name); } System.out.println(); } } } 注意:Java中,使用Scanner读取double用nextDouble(),读取字符串用next(),它会读取下一个以空白符分隔的字符串。 另外,排序可以使用lambda表达式(如果使用较新的Java版本): Collections.sort(list, (a, b) -> Double.compare(a.height, b.height)); 这样更简洁。 由于题目没有指定Java版本,我们使用兼容性较好的匿名内部类。 但是,为了代码简洁,也可以使用Double.compare: Collections.sort(list, new Comparator<Building>() { public int compare(Building a, Building b) { return Double.compare(a.height, b.height); } }); 这样避免浮点数比较的精度问题。 现在,我们按照要求,给出代码和解释。 由于题目没有指定语言,这里我将给出C++和Java两种代码,但实际提交时,用户可以选择其中一种。 但题目要求只给出一种解决方案,因此我选择C++(因为题目描述中C++的输入方式在前)。 下面提供C++代码(使用C风格字符串和scanf/printf): </think>### 解决方案 以下是使用C++实现的解决方案,通过读取多组测试数据,根据教学楼高度进行升序排序,并输出排序后的教学楼名称。 #### C++代码实现 ```cpp #include <iostream> #include <vector> #include <algorithm> #include <cstdio> using namespace std; struct Building { char name[25]; // 存储教学楼名称(长度小于20,使用25保证安全) double height; // 存储教学楼高度 }; bool cmp(Building a, Building b) { return a.height < b.height; // 按高度升序排序 } int main() { int n; while (scanf("%d", &n) != EOF) { // 读取每组数据的n,直到文件结束 vector<Building> buildings; // 存储当前组的数据 // 读取n行数据 for (int i = 0; i < n; i++) { Building b; scanf("%s %lf", b.name, &b.height); // 读取名称和高度 buildings.push_back(b); } // 按高度升序排序 sort(buildings.begin(), buildings.end(), cmp); // 输出排序后的名称(空格分隔) for (int i = 0; i < buildings.size(); i++) { if (i > 0) printf(" "); // 非首个元素前加空格 printf("%s", buildings[i].name); } printf("\n"); // 每组数据输出后换行 } return 0; } ``` #### 代码解释 1. **数据结构**: - `Building`结构体包含`name`(字符串)和`height`(浮点数),用于存储每栋教学楼的信息。 2. **输入处理**: - 使用`while (scanf("%d", &n) != EOF)`循环读取多组数据,直到文件结束。 - 每组数据读取`n`行,每行通过`scanf("%s %lf", ...)`读取名称和高度。 3. **排序逻辑**: - 自定义比较函数`cmp`,按`height`升序排序。 - 使用`sort`函数对`vector<Building>`进行排序。 4. **输出格式**: - 遍历排序后的数组,依次输出名称。 - 在非首元素前添加空格,实现名称间的空格分隔。 - 每组数据输出后换行。 #### 输入输出示例 - **输入**: ``` 2 yijiao 1.2 erjiao 1.1 3 sijiao 2.3 liujiao 5.2 wujiao 4.71 ``` - **输出**: ``` erjiao yijiao sijiao wujiao liujiao ``` ### 相关问题
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值