一、小S求解特殊算术
1.1 题目描述
现有若干整数相加的公式,例如:123+3456L2+789R4+502S,需要编写程序计算其结果。
其中:
-
每个加数可能带有后缀,后缀含义如下:
Lx表示将该加数向左循环移位x次后再参与运算。Rx表示将该加数向右循环移位x次后再参与运算。S表示将该加数翻转(即数字逆序)后再参与运算。- 无后缀的加数直接参与运算。
-
整数的左移和右移说明:
- 数字
AB...CD向右循环移位 1 次,将变为DAB...C。 - 数字
AB...CD向左循环移位 1 次,将变为B...CDA。
- 数字
-
输入的公式中整数的个数不超过 20,且均为正整数,移位次数不会超出整数位数,所有计算不会超过 int 型数据范围。
输入格式
一行,给出一个加法公式,公式中的加数为正整数,可能附带后缀。
输出格式
计算这些整数的相加和。
输入样例
123+3456L2+789R4+502S
输出样例
6940
1.2 思路分析
-
解析输入公式:
- 将输入公式按照加号(
+)分割成多个部分,每部分是一个数字及其可能的后缀(如Lx、Rx、S)。 - 使用字符串分割函数(如
strtok)解析每个加数及其后缀。
- 将输入公式按照加号(
-
处理后缀操作:
-
判断每个加数是否带有后缀,后缀表示操作类型:
Lx:向左循环移位 x 次。Rx:向右循环移位 x 次。S:翻转数字。
-
对于无后缀的加数,直接参与计算。
-
-
实现移位和翻转逻辑:
-
循环移位:
- 使用字符串操作,将数字转为字符串后进行移位,最后将移位结果转回整数。
- 左移时,将前面的数字移到后面;右移时,将后面的数字移到前面。
-
翻转数字:
- 将数字转为字符串,倒序后再转换回整数。
-
-
累加结果:
- 逐步处理每个加数,按照规则转换后将结果累加。
-
输出最终结果:
- 计算完所有加数后,输出累加和。
1.3 题目解答(C语言)
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
// 函数:将数字向左循环移位
int leftRotate(int num, int times) {
char str[20];
sprintf(str, "%d", num); // 将数字转换为字符串
int len = strlen(str);
times = times % len; // 确保移位次数不超过长度
char rotated[20];
for (int i = 0; i < len; i++) {
rotated[i] = str[(i + times) % len];
}
rotated[len] = '\0'; // 添加字符串结束符
return atoi(rotated); // 转换为整数返回
}
// 函数:将数字向右循环移位
int rightRotate(int num, int times) {
char str[20];
sprintf(str, "%d", num); // 将数字转换为字符串
int len = strlen(str);
times = times % len; // 确保移位次数不超过长度
char rotated[20];
for (int i = 0; i < len; i++) {
rotated[(i + times) % len] = str[i];
}
rotated[len] = '\0'; // 添加字符串结束符
return atoi(rotated); // 转换为整数返回
}
// 函数:将数字翻转
int reverseNumber(int num) {
char str[20];
sprintf(str, "%d", num); // 将数字转换为字符串
int len = strlen(str);
char reversed[20];
for (int i = 0; i < len; i++) {
reversed[i] = str[len - 1 - i];
}
reversed[len] = '\0'; // 添加字符串结束符
return atoi(reversed); // 转换为整数返回
}
// 主函数
int main() {
char input[100];
scanf("%s", input); // 读取输入的加法公式
int result = 0; // 存储最终结果
char *token = strtok(input, "+"); // 以 '+' 分割公式
while (token != NULL) {
int num;
char suffix[10] = ""; // 存储后缀
sscanf(token, "%d%[LR0123456789S]", &num, suffix);
// 根据后缀类型处理数字
if (suffix[0] == 'L') {
int times = atoi(suffix + 1);
num = leftRotate(num, times);
} else if (suffix[0] == 'R') {
int times = atoi(suffix + 1);
num = rightRotate(num, times);
} else if (suffix[0] == 'S') {
num = reverseNumber(num);
}
// 累加结果
result += num;
token = strtok(NULL, "+"); // 获取下一个加数
}
// 输出结果
printf("%d\n", result);
return 0;
}
1.4 知识点
a. strtok 分割字符串
功能: strtok 是 C 标准库中的字符串处理函数,用于将字符串按指定分隔符分割为多个部分。
用法:
char str[] = "123+3456L2+789R4+502S";
char *token = strtok(str, "+"); // 第一次分割,使用 "+" 作为分隔符
while (token != NULL) {
printf("分割部分:%s\n", token);
token = strtok(NULL, "+"); // 获取下一个分割部分
}
输出:
分割部分:123
分割部分:3456L2
分割部分:789R4
分割部分:502S
注意:
- 第一次调用
strtok需要传入目标字符串;后续调用传入NULL以继续分割。 - 原字符串会被修改(分隔符替换为
\0)。
b. sscanf 提取数据与后缀
功能: sscanf 是从字符串中提取数据的函数。格式化字符串 "%d%[LR0123456789S]" 用于提取数字和后缀部分。
用法:
char token[] = "3456L2";
int num;
char suffix[10];
sscanf(token, "%d%[LR0123456789S]", &num, suffix);
printf("数字部分:%d\n", num);
printf("后缀部分:%s\n", suffix);
输出:
数字部分:3456
后缀部分:L2
解释:
%d:匹配整数并存储到num。%[LR0123456789S]:匹配后缀中允许的字符集,并存储到suffix。- 后缀可为空,例如对于
123,只会提取数字,suffix为空字符串。
c. 左右移动
- 左移公式:
rotated[i] = str[(i + times) % len]。 - 右移公式:
rotated[(i + times) % len] = str[i]。 - 使用
% len确保移位次数不超过字符串长度。