题目描述
输出一个词组中每个单词的首字母的大写组合。
输入描述
输入的第一行是一个整数n,表示一共有n组测试数据。(输入只有一个n,没有多组n的输入)
接下来有n行,每组测试数据占一行,每行有一个词组,每个词组由一个或多个单词组成;每组的单词个数不超过10个,每个单词有一个或多个大写或小写字母组成;
单词长度不超过10,由一个或多个空格分隔这些单词。
输出描述
请为每组测试数据输出规定的缩写,每组输出占一行。
输入示例
1
ad dfa fgs
输出示例
ADF
提示信息
注意:单词之间可能有多个空格
本节课你讲学到的内容
- 字符大小的比较、字符运算、字符拼接
- ASCII码
getchar()函数的使用- 函数的定义和使用
- 函数的形参和实参
- 引用
&
1.字符大小的比较、字符运算、字符拼接
字符串是由一个个字符组合而成的, 比如字符串"hello", 是由字符(char)类型'h'、'e'、'l'、'l'、'0'组成的,我们可以通过索引来访问每一个字符。
2.ASCII码
字符的大小是根据它们在字符集中的ASCII码值来确定的。
比如
'a'对应的ASCII码是97,'A'对应的ASCII码是65
3.代码编写
1.getchar()函数的使用
getchar()函数来吸收一个回车符,因为在输入n之后,还需要输入回车符,才会输入下一行。
#include <bits/stdc++.h>
using namespace std;
int main(){
//接收n行测试数据
int n;
cin >> n;
//输入中获取一个字符
getchar();
return 0;
}
2.getline()函数的使用
用while循环来处理n行数据,每一行数据用getline(cin,n)来进行接收。
//接收每行输入的字符串
string s;
while(n--){
//输入读取一行字符串,存储在字符串变量s中
getline(cin,s);
//定义变量result,用来输出经过处理之后的结果
string result;
}
3.处理首字符
- 如果是大写字符,直接拼接
- 如果是小写字符,转化为大写字符,再拼接
a-z的ASCII码在97-122之间,A-Z的ASCII码在65-90之间,小写字符比大写字符大32
//如果是小写字符则转化为大写字符
if(s[0] >= 'a' && s[0] <= 'z'){
s[0] -= 32;
}
//将每行的第一个字符转换成大写后添加到result中
result += s[0];
4.处理剩下的字符
for(int i = 1;i < s.size()-1; i++){
if(s[i] == ' ' && s[i + 1] != ' '){
if(s[i + 1] >= 'a' && s[i + 1] <= 'z'){
s[i + 1] -= 32;
}
result += s[i + 1];
}
}
5.输出
cout << result << endl;
6.完整代码
#include <bits/stdc++.h>
using namespace std;
int main(){
int n;
cin >> n;
getchar();
while(n--){
string s;
getline(cin ,s);
string result;
if(s[0] >= 'a' && s[0] <= 'z'){
s[0] -= 32;
}
result += s[0];
for(int i = 1;i < s.size() - 1; i++){
if(s[i] == ' ' && s[i + 1] != ' '){
if(s[i + 1] >= 'a' && s[i + 1] <= 'z'){
s[i + 1] -= 32;
}
result += s[i + 1];
}
}
cout << result << endl;
}
return 0;
}
4.函数的使用
代码过于冗余,如果后面还需要小写变成大写,还需要再写一次
if (s[0] >= 'a' && s[0] <= 'z'){
s[0] -= 32;
}
if (s[i + 1] >= 'a' && s[i + 1] <= 'z'){
s[i + 1] -= 32;
}
所以我们将写一个函数来实现该功能
1.函数的定义和使用
需要满足以下条件
- 返回类型:返回结果是经过转换后的大写字符,所以返回类型为
char - 函数名:自定义,这里以
changeChar为例 - 形参列表:之前形参列表为空,这里需要接收一个字符,所以形参列表类型为
char类型,参数名为a。此时需要修改a的参数,所以需要加&传递符号。
char changeChar(char &a){
if(a >= 'a' && a <= 'z'){
a -= 32;
}
return a;
}
2.函数的形参和实参
- 形参和实参的概念
形参是函数定义中声明的参数,位于函数的参数列表中。形参的定义只在函数执行期间有效,在函数执行完毕后会被销毁。
实参是函数调用中传递给函数的具体值或变量,实参传递的值必须与函数的形参类型匹配,否则会发生类型错误
- 形参和实参的用法
2.1形参
//a和b是传递的形参,只在函数体{}中有效
void printSum(int a, int b){
int sum = a + b;
cout << sum << endl;
}
2.2实参
int main(){
int x = 3;
int y = 4;
//这里进行函数调用,x和y是实参。
printSum(x, y);
cout << x << y << endl;
return 0;
}
2.3当函数执行时,实参的值会复制一份给形参,函数中的修改只会影响形参的值,不会影响传递的实参
//a 和 b 是传递的实参
//当函数执行时,实参的值会复制一份给a,b
//a = 1,b = 2;
void printSum(int a, int b){
int sum = a + b;
a++;
b--;
cout << a << endl;//2
cout << b << endl;//1
}
int main(){
int x = 1,y = 2;
printSum(x , y);
cout << x << endl;//1
cout << y << endl;//2
}
3.引用&
- 引用上的操作会影响到所指向的变量。
- 在声明引用时,需要在变量名前使用
&符号。引用必须在声明时进行初始化,就不能改变引用的目标。
int a = 10;
int &n = a;
- 引用常常做为函数参数来使用,以便于函数内部修改函数调用时传递的变量。
当函数传递参数时,通常会创建参数的副本。使用引用参数可以避免不必要的参数复制,这对于大型数据结构(如数组)尤其有用,因为复制这些数据结构会产生显著的开销。
例如:
#include <iostream>
#include <algorithm> // 用于std::copy
using namespace std;
// 定义一个包含大型数组的结构体
struct LargeData {
int data[1000]; // 假设存储1000个整数的数组
LargeData() {
fill(data, data + 1000, 1); // 初始化数组
}
// 拷贝构造函数(用于跟踪复制行为)
LargeData(const LargeData& other) {
copy(other.data, other.data + 1000, data);
cout << "拷贝构造函数被调用,数据被复制!" << endl;
}
};
// 按值传递:触发拷贝构造,产生副本
void processByValue(LargeData arr) {
cout << "处理按值传递的数据(副本)" << endl;
}
// 按常量引用传递:无拷贝,直接操作原数据
void processByRef(const LargeData& arr) {
cout << "处理引用传递的数据(无副本)" << endl;
}
int main() {
LargeData bigArray; // 创建原始数据
cout << "--- 按值传递测试 ---" << endl;
processByValue(bigArray); // 调用时触发拷贝构造
cout << "\n--- 按引用传递测试 ---" << endl;
processByRef(bigArray); // 无拷贝构造
return 0;
}
输出结果:
--- 按值传递测试 ---
拷贝构造函数被调用,数据被复制!
处理按值传递的数据(副本)
--- 按引用传递测试 ---
处理引用传递的数据(无副本)
代码解析:
- 结构体
LargeData:
- 包含一个大小为1000的整型数组,模拟大型数据结构。
- 显式定义拷贝构造函数,输出提示信息以验证复制行为。
- 函数
processByValue:
- 参数按值传递,调用时会触发拷贝构造函数,生成数据的完整副本。
- 适用于需要操作数据副本的场景,但复制大数组效率低下。
- 函数
processByRef:
- 参数使用
const LargeData&,即常量引用,避免复制。 - 直接操作原始数据,无拷贝开销,提升性能。
const确保函数内不会修改原数据,保证安全性。
核心结论:
- 按值传递:适合小型数据或需要独立副本的场景,但大型数据复制成本高。
- 引用传递:避免复制,提升效率,尤其适合数组、对象等大型数据。常量引用(
const &)在只读场景中进一步保障数据安全。
- 引用的作用域通常在声明他的函数内,超过作用域后引用将无效。
#include <bits/stdc++.h>
using namespace std;
void changeValue(int &a){
a = 100;
}
int main(){
int x= 10;
cout << x << endl;//10
changeValue(x);//传递x的引用给函数
cout << x << endl;//100
return 0;
}
5.代码优化
#include <bits/stdc++.h>
using namespace std;
char changeChar(char &a){
if(a >= 'a' && a <= 'z'){
a -= 32;
}
return a;
}
int main(){
int n;
cin >> n;
getchar();
while(n--){
string s;
getline(cin,s);
string result;
result += changeChar(s[0]);
for(int i = 1;i < s.size()-1; i++){
if(s[i] == ' ' && s[i + 1] != ' '){
result += changeChar(s[i + 1]);
}
}
cout << result << endl;
}
return 0;
}