做了两道“字符串”的题目
题目一:《浮点数加法》
该题为典型例题!!!熟练掌握可以轻松解决各种“位数极多”的运算
题目链接:浮点数加法_牛客题霸_牛客网
答案链接:例题0401
我的代码如下:
//经典例题
#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<string>
using namespace std;
void fraction_add(string A,string B,int &carry,string &fraction) {//carry表示进位
//先对齐
int A_size = A.size();
int B_size = B.size();
int size;
//if (size < B.size()) {//即B的size更大
// size = B.size();
// //则A需进行尾部零填充
// //for (int i = 0; i < (B.size() - A.size()); i++) {
// // A.push_back('0');
// //}
//}
//else {
// for (int i = 0; i < (A.size() - B.size()); i++) {
// B.push_back('0');
// }
//}
//上面代码编写错误,在补零的过程中A.size()和B.size()都是变化的量,这边认为用size()函数放在“补零”操作的判断语句中是严重的错误!!!
if (A_size < B_size) {//即B的size更大
size = B_size;
//则A需进行尾部零填充
for (int i = 0; i < (B_size - A_size); i++) {
A.push_back('0');
}
}
else {
size = A_size;
for (int i = 0; i < A_size - B_size; i++) {
B.push_back('0');
}
}
fraction.resize(size);//预先分配空间
//做加法(从尾部开始)
for (int i = size - 1; i >= 0; i--) {
//A[i],B[i]
//"0"的值和0不一样,"0"="0"
//"3"="0"+3
//说明字符元素之间的加减依靠类似于一套ascll码的机制。虽然"0"和0用int来解释,其值不同,但是0与其他整数(eg:x)的偏移量=="x"与"0"间的偏移量
//"3"+"4"="0"+3+"0"+4,故"7"="3"+"4"-"0"
if (A[i] + B[i] - '0'+ carry <= '9') {//没有进位
fraction[i] = A[i] + B[i] +carry - '0';
//fraction.insert(0, temp);
carry = 0;
}
else {
//'6'+'6'="0"+6+"0"+6
fraction[i] = A[i] + B[i] +carry - '0' -10;
carry = 1;
}
}
}
void integer_add(string A, string B, int carry, string &integer) {
//从低位开始进行遍历
integer.clear();
for (int i = A.size() - 1, j = B.size() - 1; i >= 0 || j >= 0 || carry == 1; i--, j--) {
//从右向左进行遍历
if (i >= 0 && j >= 0) {
if (A[i] + B[j] - '0' + carry <= '9') {//没有进位
char temp = A[i] + B[j] + carry - '0' ;
//'1'+'1'='0'+1+'0'+1
integer.insert(integer.begin(), temp);
carry = 0;
}
else {
char temp = A[i] + B[j] + carry - '0' - 10;
integer.insert(integer.begin(), temp);
carry = 1;
}
}
else if (i < 0 && j >= 0) {
if ( B[j] - '0' + carry <= '9') {//没有进位
char temp = B[j] + carry ;
//'2'='0'+2
integer.insert(integer.begin(), temp);
carry = 0;
}
else {
//'9'+1='10'='0'+10
char temp = B[j] + carry - 10;
integer.insert(integer.begin(), temp);
carry = 1;
}
}
else if (j < 0 && i >= 0) {
if (A[i] - '0' + carry <= '9') {//没有进位
char temp = A[i] + carry;
//'2'='0'+2
integer.insert(integer.begin(), temp);
carry = 0;
}
else {
//'9'+1='10'='0'+10
char temp = A[i] + carry - 10;
integer.insert(integer.begin(), temp);
carry = 1;
}
}
else {//用以处理最高位进位
if (carry == 1) {
char temp = '1';
integer.insert(integer.begin(), carry);
}
}
}
}
int main() {
char a[1000];
char b[1000];
while (scanf("%s %s", a, b) != EOF) {
//char a[1000] = "13.1452 ";
//char b[1000] = "211.985";
// 225.1302
//加法分两步进行,一个是小数部分,一个是整数部分
string A = a;
string B = b;
//区分研究对象的整数部分和小数部分,需使用substr()函数来提取子串
string A_integer = A.substr(0, A.find('.'));
string A_fraction = A.substr(A.find('.') + 1, A.size() - A.find('.'));
string B_integer = B.substr(0, B.find('.'));
string B_fraction = B.substr(B.find('.') + 1, B.size() - B.find('.'));
string temp_fraction;
int carry = 0;
fraction_add(A_fraction, B_fraction, carry, temp_fraction);
string temp_integer;
integer_add(A_integer, B_integer, carry, temp_integer);
printf("%s.%s\n", temp_integer.c_str(), temp_fraction.c_str());
}
return 0;
}
心得:
1、string类型和vector<int>可调用的函数一样。支持.size(),.push_back()(注:两者同样不支持push_front()的操作),两者均可以用“[ ]”对其中的元素进行访问。
2、要慎重考虑将.size()函数放到循环判断语句中!!!,上面代码中的函数fraction_add()的编写就没考虑到这个,导致调试半天!
3、字符串中的"+","-"和">","<"等有关比较都是基于其背后的ascii。
4、用字符串进行高精度的数值计算实现的基本数学原理如下:
'3'+'4'='0'+3+'0'+4,故'7'='3'+'4'-'0'
题目二:W的密码
题目答案:例题0402
我的代码如下:
#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<string>
#include<vector>
using namespace std;
//第一组: _(95) a(97) b c d e f g h i
//第二组:j k l m n o p q r
//第三组:s t u v w x y z
void Partition(string A,vector<int>& vec_1, vector<int>& vec_2, vector<int>&vec_3) {
for (int i = 0; i < A.size(); i++) {
if (A[i] >= 'a' && A[i] <= 'i') {
vec_1.push_back(i);
}
else if (A[i] >= 'j' && A[i] <= 'r') {
vec_2.push_back(i);
}
else {
vec_3.push_back(i);
}
}
}
void Rightrotate(string &A,vector<int> vec ,int offset){
//eg:abcd offset=2
// 0123
//result:cdab 保存下标为:[offset,A.size()),将下标为[0,offset)的元素从右往左依次转移
if (vec.size() == 0) {
return;
}
//边界条件
vector<int>::iterator it;
string temp;//用以保存后面几个元素
int offset_temp;
offset_temp = offset % (vec.size());
it = vec.end() - offset_temp;//0+1
for (; it != vec.end(); it++) {
temp.push_back(A[*it]);
}
//转移前面的元素
vector<int>::iterator it_back=vec.end() - 1;
vector<int>::iterator it_front=vec.end() - offset_temp - 1;
//abcdef
//需要后移的元素个数为A.size()-offset
int count = 0;
for (int i = 0; i < vec.size() - offset_temp; i++) {
A[*it_back] = A[*it_front];
count += 1;
if (i != vec.size() - offset_temp - 1) {
it_back--, it_front--;
}
}
//将temp中的值转移到A的前面
it=vec.begin();
for (int i = 0; i < offset_temp; i++) {
A[*it] = temp[i];
if(i!= offset_temp -1){
it++;
}
}
}
int main() {
int k1, k2, k3;
while (1) {
scanf("%d %d %d", &k1, &k2, &k3);
if (k1 == 0 && k2 == 0 && k3 == 0) {
break;
}
char inpute[1000];
scanf("%s", inpute);
string A = inpute;
//string A="_icuo_bfnwhoq_kxert";
//string A = "abcdefgh";
//_ic_bfh_e
//onoqkr
//uwxt
//对A进行分组(用动态数组来存储同一组的下标)
vector<int> vec_1;
vector<int> vec_2;
vector<int> vec_3;
Partition(A, vec_1, vec_2, vec_3);
Rightrotate(A, vec_1, k1);
Rightrotate(A, vec_2, k2);
Rightrotate(A, vec_3, k3);
printf("%s\n", A.c_str());
}
return 0;
}
心得:
1、犯的最大一个错误就是:懒得动笔模拟,导致走了很多弯路!!!
2、了解到如何实现“字符串”的循环移位。
3、还掌握了如何对一个字符串的非相邻“子串”进行操作(虽然非相邻,但此处我还是将其称作子串),其实现方法为,用一个数组(eg:A)对子串在原字符串中的下标进行标记,借助数组A我们就可以只研究我们感兴趣的非连续“子串”而不影响其他非连续“子串”的操作。
4、2025/2/10纠正,在本题中我忽略了某一组别的元素个数可能为“0”的边界情况。