PAT乙级
爱己者,人恒爱之
类型范围
类型名称 取值范围
int -2^31~(2^31-1)
unsigned int 0~(2^32-1)
2^31=2,147,483,648 10^9数量级
2^32=4,294,967,296 10^9数量级
类型名称 取值范围
long long (_int64) -2^63~(2^63-1)
unsigned long long (unsigned_int64) 0~(2^64-1)
2^63=9,223,372,036,854,775,808 10^18数量级
2^64=18,446,744,073,709,551,616 10^19数量级
**long long 的输出是 %lld
string 和 cstring 的区别
在C++中,头文件<string>
和<cstring>
是不一样的。它们提供了不同的功能,适用于不同的用途。
<string>
头文件
- C++标准库:
<string>
是 C++ 标准库的一部分,提供了std::string
类,用于处理和操作字符串对象。 - 面向对象:
std::string
是一个面向对象的类,提供了丰富的成员函数和运算符重载来处理字符串操作。 - 动态分配:
std::string
类会自动管理内存分配和释放,方便处理动态大小的字符串。 - 功能强大:
std::string
提供了大量的成员函数,如length()
,substr()
,find()
,append()
,compare()
,c_str()
等。
示例:
#include <iostream>
#include <string>
int main() {
std::string str1 = "Hello";
std::string str2 = "World";
std::string str3 = str1 + " " + str2;
std::cout << str3 << std::endl; // 输出: Hello World
return 0;
}
<cstring>
头文件
- C标准库:
<cstring>
是 C 标准库头文件<string.h>
的 C++ 版本,提供了处理 C 风格字符串的函数。 - C 风格字符串:这些函数处理的是以空字符
\0
结尾的字符数组,即 C 风格字符串。 - 低级操作:函数如
strlen()
,strcpy()
,strcat()
,strcmp()
,memset()
,memcpy()
等提供了对字符数组的低级操作。 - 手动管理内存:使用 C 风格字符串时,内存管理需要手动进行。
示例:
#include <iostream>
#include <cstring>
int main() {
char str1[20] = "Hello";
char str2[] = "World";
strcat(str1, " ");
strcat(str1, str2);
std::cout << str1 << std::endl; // 输出: Hello World
return 0;
}
区别总结
-
数据类型:
<string>
:处理std::string
类对象。<cstring>
:处理 C 风格字符串(字符数组)。
-
内存管理:
<string>
:自动内存管理。<cstring>
:手动内存管理。
-
函数和方法:
<string>
:提供丰富的成员函数和运算符重载。<cstring>
:提供基本的字符串处理函数。
-
使用场景:
<string>
:推荐在 C++ 程序中使用,特别是需要动态字符串处理和复杂字符串操作时。<cstring>
:在需要与 C 代码兼容或进行低级别字符串操作时使用。
了解这两者的区别有助于根据具体需求选择合适的字符串处理方法。
1003 我要通过!
总结
1. map<char, int> mp; 语句解释
(1) map 的基本概念
map 是C++标准模板库(STL)中的一种关联容器,用于存储键值对(key-value pairs)。在 map 中,每个键是唯一的,并且每个键都关联到一个值。map 会根据键自动进行排序,默认情况下使用键的 < 操作符进行比较。
(2) map<char, int> 的定义
在这条语句中,map<char, int> 声明了一个 map,它的键类型是 char,值类型是 int。这意味着这个 map 将字符映射到整数。
- 键类型(char): 键是字符类型,表示我们将使用字符作为 map 的键。
- 值类型(int): 值是整数类型,表示我们将使用整数来存储与每个字符相关联的值。
(3)变量 mp 的声明
mp 是这个 map 类型的变量名。mp 将用来存储字符及其对应的出现次数。例如,如果我们插入键值对 ('A', 3) 到 mp 中,这意味着字符 A 出现了3次。
(4)具体用法
在这个程序中,map<char, int> mp; 主要用于统计字符串中每个字符的出现次数。
map<char, int> mp;
for(int i = 0; i < s.size(); i++)
mp[s[i]]++;
在这段代码中,程序遍历字符串 s 中的每个字符 s[i],并将该字符作为键插入到 mp 中。如果字符已经在 mp 中存在,则对应的值(出现次数)增加1。如果字符不在 mp 中,则自动创建一个新的键值对,并将出现次数初始化为1。
map总结
map<char, int> mp; 定义了一个 map,用于将字符映射到整数(出现次数)。
- mp 用于存储并统计字符串中每个字符的出现次数。
- map 自动处理插入和更新操作,使得统计字符出现次数变得简洁高效。
通过这种方式,程序可以快速统计并访问每个字符的出现次数,从而用于后续的逻辑判断。
为了使用 map 容器,需要包含
2.bool flag = false; 语句解释
(1) 布尔类型(bool)
bool 是C++中的一种基本数据类型,用于表示布尔值。布尔类型只有两个可能的取值:
-
true:表示真
-
false:表示假
布尔类型常用于条件判断和控制流程中。
(2)变量声明和初始化
bool flag = false; 这条语句同时进行了变量的声明和初始化:
- 声明变量:bool flag 声明了一个名为 flag 的布尔变量。此时,flag 是一个可以存储布尔值的变量。
- 初始化变量:= false 将布尔变量 flag 初始化为 false。这意味着在这条语句执行完毕后,flag 的初始值为 false。
(3) 变量 flag 的作用
在你的程序中,flag 变量用于表示字符串是否符合特定的条件。它起到了标志(flag)的作用,用于控制后续的逻辑判断和输出。
3.puts(""); 语句解释
(1)puts 函数
puts 是C标准库中的一个函数,用于向标准输出(通常是屏幕)输出一个字符串,并在字符串的末尾自动添加一个换行符。它的原型定义在头文件 <stdio.h> 中:
int puts(const char *str);
(2) 参数
puts 函数的参数是一个指向以 \0 结尾的字符串(C字符串)的指针。
- const char *str:指向要输出的字符串的指针。
(3)返回值
puts 函数的返回值是一个整型:
- 成功时,返回一个非负值(通常是一个正整数)。
- 失败时,返回 EOF(通常为 -1)。
(4)作用
当你调用 puts(""); 时,传递给 puts 函数的参数是一个空字符串 ""。因此,puts 会输出一个空行。具体来说,它会在标准输出上打印一个换行符 \n。
puts(""); 在此题程序中的作用
在程序中,puts(""); 用于在输出 YES 或 NO 之后输出一个换行符,但只在不是最后一个测试用例时使用。这是为了确保每个输出结果都在新的一行上,而在最后一个测试用例后不会多输出一个空行。
if(i != n) puts("");
- 这条语句的作用是:如果当前不是最后一个测试用例,则输出一个换行符。
题目
代码示例
C++版本
#include<iostream>
#include<string>
#include<map>
using namespace std;
//使用命名空间 std 以简化代码编写,
//避免使用标准库中的函数和对象时每次都写 "std::"。
int main()
{
int n; //测试用例的数量
cin >> n;
for( int i = 1 ; i <= n ; i++) //循环处理每个测试用例
{
string s; //定义测试用例
cin >> s;
map<char, int>mp;
// 统计字符串中每个字符的出现次数。
// 声明一个"map",用于存储每个字符出现的次数。
// "map"的键是字符char,值是字符char出现的次数
bool flag = false;
// bool 是C++中的一种基本数据类型,用于表示布尔值。
// 布尔类型只有两个可能的取值:true:表示真;false:表示假
// 布尔类型常用于条件判断和控制流程中。
for(int j = 0 ; j < s.size() ; j++ )//遍历字符串"s",将每个字符存入"map"中并条机出现次数
mp[s[j]]++;
if(mp.size() == 3 && mp['p'] == 1 && mp['A'] == 1 && mp['T'] ==1 )
{ //字符类型为3 P出现一次 A出现一次 T出现一次
int p = s.find('P'); //找到P和T在字符串s中的位置,分别赋值给"p"、"t"。
int t = s.find('T');
int len1 = p; //计算p左侧字符数量
int len2 = t - p - 1; //P和T之间字符数量
int len3 = s.size() - t - 1; //T右侧字符数量
if(t - 1 > 1 && len1 * len2 == len3 )
flag = true ;
}
if(flag)
cout << "YES";
else
cout << "NO";
if(i != n)
puts(""); //输出一个换行符。这是为了确保每个输出结果都在新的一行上
}
}
- C语言版本
#include<stdio.h>
#include<string.h>
int main(){
int n;
scanf("%d",&n);
for(int i = 0 ; i < n ; i++ )
{
char s[101];
int countP = 0,countA = 0, countT = 0; // 定义记录出现的次数
int len1 = 0, len2 = 0, len3 = 0;//定义记录P左边的值,PT之间的值,T右边的值
int l = -1 ,r = -1;
int flag = 0;
scanf("%s",s);
int len = strlen(s);
for(int j = 0 ; j<len ;j++)
{
if(s[j] == 'P'){
countP++;
l = j;
}else if(s[j] == 'A'){
countA++;
}else if(s[j] == 'T'){
countT++;
r = j;
}else{
flag = 0;
break;
}
}
if( countP == 1 && countA >0 && countT == 1 && r-l > 1)
{
len1 = l;
len2 = r - l - 1;
len3 =len - r - 1;
if(len1 * len2 == len3){
flag = 1;
}
}
if( flag == 1 ){
printf("YES");
}else{
printf("NO");
}
if(i != n-1){
printf("\n");
}
}
return 0;
}
1004 成绩排名
总结
定义结构体 Student
struct Student {
char name[11];
char id[11];
int score;
};
结构体
结构体(structure)是一种用户自定义的数据类型,它允许将不同类型的数据组合在一起。结构体在处理一组相关的数据时非常有用。
定义 Student 结构体
- char name[11];:字符数组,用于存储学生的姓名,假设姓名的最大长度为10个字符,加上一个结束符 \0,所以定义长度为11。
- char id[11];:字符数组,用于存储学生的学号,假设学号的最大长度为10个字符,加上一个结束符 \0,所以定义长度为11。
- int score;:整型变量,用于存储学生的成绩。
题目
代码示例
C语言版本
#include<stdio.h>
#include<string.h>
struct Student {
char name[11];
char id[11];
int score;
};
int main()
{
int n;
int min = 0,max = 0;
scanf("%d",&n);
struct Student students[n];
for(int i = 0 ; i<n ; i++){
scanf("%s %s %d",students[i].name ,students[i].id ,&students[i].score );
if(students[i].score > students[max].score ){
max = i;
}
if(students[i].score < students[min].score ){
min = i;
}
}
printf("%s %s\n",students[max].name , students[max].id);
printf("%s %s\n",students[min].name , students[min].id);
return 0;
}
1009 说反话(20)
总结:
1. getline(cin, s);
功能
- getline 是一个标准库函数,用于从输入流 cin 中读取一整行,直到遇到换行符('\n')。
- 读取的内容存储在字符串 s 中。
使用场景
- 常用于读取包含空格的整行输入,例如读取用户输入的一句话、一段文本等。
代码示例
#include <iostream>
#include <string>
int main() {
std::string s;
getline(std::cin, s); // 从标准输入中读取一整行
std::cout << "You entered: " << s << std::endl;
return 0;
}
2. stringstream l(s);
功能
- stringstream 是标准库中的一个类,用于将字符串 s 转换为字符串流 l。
- 这样做之后,可以像操作输入流一样操作字符串 s,例如使用提取运算符 >> 从流中读取数据。
使用场景
- 常用于将一个字符串分解为单独的单词或其他子字符串,以便逐个处理。
- 适用于从包含空格或其他分隔符的字符串中提取数据。
代码示例
#include <sstream>
#include <iostream>
#include <string>
int main() {
std::string s = "This is a test";
std::stringstream l(s); // 将字符串转换为字符串流
std::string word;
while (l >> word) {
std::cout << word << std::endl; // 逐个输出单词
}
return 0;
}
3. while (l >> x)
功能
- while (l >> x) 是一个循环结构,使用提取运算符 >> 从字符串流 l 中读取数据,并存储在变量 x 中。
- 每次读取成功时,循环体中的代码块 { ... } 被执行。
使用场景
- 常用于逐个提取字符串中的单词或其他数据,直到流中没有更多数据为止。
代码示例
#include <sstream>
#include <iostream>
#include <string>
int main() {
std::string s = "123 456 789";
std::stringstream l(s); // 将字符串转换为字符串流
int number;
while (l >> number) { // 从字符串流中逐个读取整数
std::cout << number << std::endl; // 逐个输出整数
}
return 0;
}
题目
代码示例
#include<cstdio>
#include<vector>
#include<string>
#include<iostream>
#include<sstream>//stringstream l(s);
using namespace std;
int main()
{
string s,x;
vector<string> ver;
getline(cin,s);//从输入流中获取一个s
stringstream l(s);//#include<sstream>;将s作为一个输入流,输入到l字符串流
while(l>>x){
ver.push_back(x);
}
for(int i =ver.size()-1 ; i >= 0 ; i-- ){
cout << ver[i];
if(i) cout << " ";
}
return 0;
}
1017 A除以B(20)
大整数除法
大整数除法是指将一个非常大的数除以一个较小的数,计算它们的商和余数。在这段代码中,我们通过模拟手动除法的方式实现了这一过程。以下是对代码的逐行详细解释。
包含头文件和命名空间
#include<cstdio>
#include<iostream>
#include<vector>
#include<string>
#include<algorithm>
using namespace std;
#include<cstdio>
:用于标准C的输入输出函数。#include<iostream>
:用于标准C++的输入输出流。#include<vector>
:用于使用vector
容器。#include<string>
:用于使用string
类。#include<algorithm>
:用于使用标准算法,如reverse
。
定义全局变量
vector<int> A, B;
vector<int> A
:用于存储被除数(大整数)的每一位。vector<int> B
:用于存储商的每一位。
主函数
int main(void)
{
string a;
int b;
cin >> a >> b;
string a
:用于存储输入的大整数。int b
:用于存储输入的除数。cin >> a >> b
:从标准输入读取大整数和除数。
将字符串转化为整数数组
for (int i = a.size() - 1; i >= 0; i--)
A.push_back(a[i] - '0');
a.size() - 1
:获取字符串的长度并转换为索引。A.push_back(a[i] - '0')
:将字符串中的每一位字符转换为对应的整数并存入vector A
中,顺序是从高位到低位。
初始化并计算商和余数
int t = 0;
for (int i = A.size() - 1; i >= 0; i--)
{
t = t * 10 + A[i];
B.push_back(t / b);
t = t % b;
}
int t = 0
:初始化临时变量t
,用于存储当前计算的部分被除数。for (int i = A.size() - 1; i >= 0; i--)
:从最高位(数组的最后一位)开始循环。t = t * 10 + A[i]
:将当前位的值加到t
中,相当于逐位构造当前的被除数。B.push_back(t / b)
:将t
除以b
的商存入vector B
中。t = t % b
:更新t
为余数,准备进行下一位的计算。
反转向量B
reverse(B.begin(), B.end());
reverse(B.begin(), B.end())
:反转vector B
,因为计算出的商是从低位到高位存储的,需要将其反转为正常顺序。
去除前导零
while (B.size() > 1 && B.back() == 0)
B.pop_back();
while (B.size() > 1 && B.back() == 0)
:删除向量末尾的零,直到只剩下一个元素或遇到非零元素为止。
输出结果
for (int i = B.size() - 1; i >= 0; i--)
cout << B[i];
cout << " " << t << endl;
return 0;
for (int i = B.size() - 1; i >= 0; i--)
:从向量的最后一个元素(高位)开始输出每一个元素,得到商。cout << " " << t << endl
:输出余数t
。return 0
:表示程序成功结束。
运行示例
假设输入是:
123456789 123
处理过程如下:
- 将字符串
"123456789"
转换为向量A
,即[9, 8, 7, 6, 5, 4, 3, 2, 1]
。 - 逐位计算商和余数:
- 从最高位开始,将当前值乘以10并加上当前位的值,更新
t
。 - 将
t
除以b
的商存入向量B
中。 - 更新
t
为余数,继续下一位的计算。
- 从最高位开始,将当前值乘以10并加上当前位的值,更新
- 将商的向量
B
反转并去除前导零。 - 输出商和余数。
计算结果是:
- 商:1003713
- 余数:93
输出:
1003713 93
这段代码实现了大整数除法,通过逐位模拟手工除法的过程,将大整数的每一位处理成向量中的元素,逐位计算商和余数,并最终输出结果。
题目
这个程序实现了大整数除法,即将一个大整数(以字符串形式输入)除以一个整数,然后输出商和余数。程序使用C++标准库中的向量(vector
)来存储中间计算结果。下面是详细的解释:
代码示例
#include<cstdio>
#include<iostream>
#include<vector>
#include<string>
#include<algorithm>
using namespace std;
int main(){
string num;
int n;
cin>>num>>n;
int t = 0;
vector<int> a,b;
for(int i = 0 ; i < num.size() ; i++)
{
a.push_back(num[i] - '0') ;//字符型变成 正序整数型 123
//cout << a.back() ;
}
for(int i = 0 ; i < a.size() ;i++){//从高位开始除
t = t*10 + a[i];
b.push_back( t / n );
t = t % n;
}
reverse(b.begin(),b.end() );//倒过来为下一步去掉前面的0提供了便利
while(b.size() > 1 && b.back() == 0){
b.pop_back() ;
}
for(int i = b.size() - 1 ; i >= 0 ; i--){
cout << b[i];
}
cout << " " << t ;
return 0;
}
1019 数字黑洞(20)
总结:
1、将字符串转换为整数 stoi
头文件是#include <algorithm>
int num = stoi(str1) //stoi()升序排序
2、 数转换为字符串//to_string--头文件是<string>
string str = to_string(pi);
3、翻转reverse
reverse(a.begin(),a.end());
*/
1、将字符串转换为整数
#include <algorithm>
int num = stoi(str1) //stoi()升序排序
2、 数转换为字符串//to_string--头文件是<string>
string str = to_string(pi);
3、翻转
reverse(a.begin(),a.end());
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
#include<cstdio>
#include<iostream>
#include<algorithm>//包含sort函数
#include<string>
using namespace std;
int main(){
string a,b;
cin >> a;
int a1,b1,c;
while(c != 6174)
{
while( a.size() < 4 ){ a = '0'+ a ;}//补前导零
sort(a.begin() ,a.end() );//排序 ,sort默认排序是升序的
b = a; //被减数是升序的
reverse(a.begin() ,a.end() );//减数是要降序的,reverse反转变成降序
a1 = stoi(a); //stio()将字符串转换成整数型
b1 = stoi(b);
if(a1 == b1){
printf("%04d - %04d = 0000",a1,b1);break;
}
if( c != 6174){
printf("%04d - %04d = %04d\n",a1,b1,a1-b1);
}
c=a1-b1;
a = to_string(c);
}
return 0;
}
1024 科学计数法(20)
substr
substr
是 C++ 标准库 string
类的成员函数,用于从字符串中提取子字符串。它的使用方法如下:
string substr (size_t pos = 0, size_t len = npos) const;
pos
是子字符串开始的位置。len
是子字符串的长度。npos
是一个静态常量,表示最大长度(通常是字符串末尾)。
示例代码
下面是一些使用 substr
的示例代码:
#include <iostream>
#include <string>
using namespace std;
int main() {
string str = "Hello, World!";
// 从位置 0 开始,提取 5 个字符
string sub1 = str.substr(0, 5);
cout << "sub1: " << sub1 << endl; // 输出: Hello
-----------------------------------
// 从位置 7 开始,提取 5 个字符
string sub2 = str.substr(7, 5);
cout << "sub2: " << sub2 << endl; // 输出: World
// 从位置 7 开始,提取到字符串末尾
string sub3 = str.substr(7);
cout << "sub3: " << sub3 << endl; // 输出: World!
----------------------------------
// 从位置 0 开始,提取到字符串末尾
string sub4 = str.substr();
cout << "sub4: " << sub4 << endl; // 输出: Hello, World!
return 0;
}
使用场景示例
- 从字符串中提取文件扩展名:
#include <iostream>
#include <string>
using namespace std;
int main() {
string filename = "example.txt";
size_t pos = filename.find('.');
if (pos != string::npos) {
string extension = filename.substr(pos + 1);
cout << "File extension: " << extension << endl; // 输出: txt
}
return 0;
}
- 从字符串中提取 URL 的域名:
#include <iostream>
#include <string>
using namespace std;
int main() {
string url = "https://www.example.com/page";
size_t pos_start = url.find("://") + 3;
size_t pos_end = url.find('/', pos_start);
string domain = url.substr(pos_start, pos_end - pos_start);
cout << "Domain: " << domain << endl; // 输出: www.example.com
return 0;
}
注意事项
-
越界问题:
- 如果
pos
大于字符串的长度,将抛出out_of_range
异常。 - 如果
len
超过了从pos
开始的剩余字符数,substr
会返回从pos
到字符串末尾的所有字符。
- 如果
-
默认参数:
pos
默认值为0
,即从字符串开头开始。len
默认值为npos
,即到字符串末尾。
1029 旧键盘(20)
toupper 函数将小写字母转换为大写字母,非字母字符不变
tolower 大写转为小写
题目
代码示例
#include<cstdio>
#include<iostream>
#include<map>
#include<string>
using namespace std;
int main(){
string a, b;
cin>>a>>b;
map<char,int> mp;
for(int i = 0; i<b.size(); i++){
b[i] = toupper(b[i]);//toupper 函数将小写字母转换为大写字母,非字母字符不变
mp[b[i]] = 1;// 将字符存入 map 中,标记为已处理
}
for(int i = 0; i<a.size();i++){
a[i] = toupper(a[i]);// 将字符转换为大写
if(!mp[a[i]]){ // 如果字符在 map 中不存在(即未处理过)
cout<<a[i]; // 输出该字符
mp[a[i]] = 1; // 将该字符标记为已处理
}
}
return 0;
}
1042 字符统计
#include<cstdio>
#include<iostream>
#include<cstring>
#include<sstream>
#include<map>
using namespace std;
int main(){
string s;
char c,max_c;
map<char,int>mp;
int ans = 0;
getline(cin,s);//以一行输入字符串s,回车结束
stringstream l(s);//头文件:include<sstream>;将字符串s转换为字符串流l
while(l>>c){// 字符串中逐个读取字符c
c = tolower(c);//tolower字母变小写,toupper字母变大写
if(c>='a' && c<='z' ){
mp[c]++;
if(mp[c] > ans || ((mp[c] == ans && c < max_c))){
max_c = c;
ans = mp[max_c];
}
}
}
cout<<max_c<<" "<<ans;
return 0;
}
未完待续...
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】博客园社区专享云产品让利特惠,阿里云新客6.5折上折
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 一个费力不讨好的项目,让我损失了近一半的绩效!
· 清华大学推出第四讲使用 DeepSeek + DeepResearch 让科研像聊天一样简单!
· 实操Deepseek接入个人知识库
· CSnakes vs Python.NET:高效嵌入与灵活互通的跨语言方案对比
· Plotly.NET 一个为 .NET 打造的强大开源交互式图表库