PAT乙级

爱己者,人恒爱之

类型范围

  类型名称                  取值范围
    int                 -2^31~(2^31-1unsigned int             0~(2^32-12^31=2,147,483,648      10^9数量级
2^32=4,294,967,296      10^9数量级



          类型名称                       取值范围
      long long (_int64)              -2^63~(2^63-1unsigned 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;
}

区别总结

  1. 数据类型

    • <string>:处理 std::string 类对象。
    • <cstring>:处理 C 风格字符串(字符数组)。
  2. 内存管理

    • <string>:自动内存管理。
    • <cstring>:手动内存管理。
  3. 函数和方法

    • <string>:提供丰富的成员函数和运算符重载。
    • <cstring>:提供基本的字符串处理函数。
  4. 使用场景

    • <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 容器,需要包含 头文件。虽然在代码中使用了 #include <bits/stdc++.h>,但在实际开发中更推荐显式地包含所需的头文件,这样可以提高代码的可读性和编译效率。

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("");
  • 这条语句的作用是:如果当前不是最后一个测试用例,则输出一个换行符。

题目
image

代码示例
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;:整型变量,用于存储学生的成绩。

题目
image
代码示例
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;
}

题目
image
代码示例

#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

处理过程如下:

  1. 将字符串"123456789"转换为向量A,即[9, 8, 7, 6, 5, 4, 3, 2, 1]
  2. 逐位计算商和余数:
    • 从最高位开始,将当前值乘以10并加上当前位的值,更新t
    • t除以b的商存入向量B中。
    • 更新t为余数,继续下一位的计算。
  3. 将商的向量B反转并去除前导零。
  4. 输出商和余数。

计算结果是:

  • 商:1003713
  • 余数:93

输出:

1003713 93

这段代码实现了大整数除法,通过逐位模拟手工除法的过程,将大整数的每一位处理成向量中的元素,逐位计算商和余数,并最终输出结果。

题目
image

这个程序实现了大整数除法,即将一个大整数(以字符串形式输入)除以一个整数,然后输出商和余数。程序使用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;
}

使用场景示例

  1. 从字符串中提取文件扩展名:
#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;
}
  1. 从字符串中提取 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;
}

注意事项

  1. 越界问题

    • 如果 pos 大于字符串的长度,将抛出 out_of_range 异常。
    • 如果 len 超过了从 pos 开始的剩余字符数,substr 会返回从 pos 到字符串末尾的所有字符。
  2. 默认参数

    • pos 默认值为 0,即从字符串开头开始。
    • len 默认值为 npos,即到字符串末尾。

1029 旧键盘(20)

toupper 函数将小写字母转换为大写字母,非字母字符不变

tolower 大写转为小写

题目
image

代码示例

#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 字符统计

image

#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;
}

未完待续...

posted @   邹木木  阅读(15)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 一个费力不讨好的项目,让我损失了近一半的绩效!
· 清华大学推出第四讲使用 DeepSeek + DeepResearch 让科研像聊天一样简单!
· 实操Deepseek接入个人知识库
· CSnakes vs Python.NET:高效嵌入与灵活互通的跨语言方案对比
· Plotly.NET 一个为 .NET 打造的强大开源交互式图表库
点击右上角即可分享
微信分享提示