PAT乙级 (字符串处理) 1006、1021、1031、1002、1009、1014、1024、1048

1006 换个格式输出整数

让我们用字母 B 来表示“百”、字母 S 表示“十”,用 12...n 来表示不为零的个位数字 n(<10),换个格式来输出任一个不超过 3 位的正整数。例如 234 应该被输出为 BBSSS1234,因为它有 2 个“百”、3 个“十”、以及个位的 4。

输入格式:

每个测试输入包含 1 个测试用例,给出正整数 n(<1000)。

输出格式:

每个测试用例的输出占一行,用规定的格式输出 n。

输入样例 1:

234

输出样例 1:

BBSSS1234

输入样例 2:

23

输出样例 2:

SS123

代码:

#include<stdio.h>
int main(){
    int num, i, digit1, digit2;
    scanf("%d", &num);
    digit1 = num % 10;//得到个位数
    num /= 10;
    digit2 = num % 10;//得到十位数
    num /= 10;//得到百位数
    for(i = 0; i < num; i ++){//打印百位
        printf("B");
    }
    for(i = 0; i < digit2; i++){//打印十位
        printf("S");
    }
    for(i = 1; i < digit1 + 1; i++){//打印个位
        printf("%d", i);
    }
    return 0;
}


1021 个位数统计

给定一个 k 位整数 N=dk−1​10k−1+⋯+d1​101+d0​ (0≤di​≤9, i=0,⋯,k−1, dk−1​>0),请编写程序统计每种不同的个位数字出现的次数。例如:给定 N=100311,则有 2 个 0,3 个 1,和 1 个 3。

输入格式:

每个输入包含 1 个测试用例,即一个不超过 1000 位的正整数 N。

输出格式:

对 N 中每一种不同的个位数字,以 D:M 的格式在一行中输出该位数字 D 及其在 N 中出现的次数 M。要求按 D 的升序输出。

输入样例:

100311

输出样例:

0:2
1:3
3:1

代码:

#include<stdio.h>
#include<string.h>
int main(){
    char str[1010];//将整数转换为字符串
    gets(str);//存储字符串
    int len = strlen(str);//得到字符串长度
    int temp;//记录当前扫描到的字符数字
    int count[10] = {0};//申明一个整型数组,用于存放每个数字出现的次数
    for (int i = 0; i < len; i++){//遍历字符串
        //当前扫描到的字符减去'0'字符的ASCII码,得到的就是当前扫描字符的数字形式
        temp = str[i] - '0';
        count[temp]++;//数组中将扫描到的数字的次数+1
    }
    for (int i = 0; i < 10; i++){//遍历数组
        if(count[i] != 0){//如果当前扫描到的元素不为0则输出
            printf("%d:%d\n", i, count[i]);
        }
    }
    return 0;
}


1031 查验身份证 

一个合法的身份证号码由17位地区、日期编号和顺序编号加1位校验码组成。校验码的计算规则如下:

首先对前17位数字加权求和,权重分配为:{7,9,10,5,8,4,2,1,6,3,7,9,10,5,8,4,2};然后将计算的和对11取模得到值Z;最后按照以下关系对应Z值与校验码M的值:

Z:0 1 2 3 4 5 6 7 8 9 10
M:1 0 X 9 8 7 6 5 4 3 2

现在给定一些身份证号码,请你验证校验码的有效性,并输出有问题的号码。

输入格式:

输入第一行给出正整数N(≤100)是输入的身份证号码的个数。随后N行,每行给出1个18位身份证号码。

输出格式:

按照输入的顺序每行输出1个有问题的身份证号码。这里并不检验前17位是否合理,只检查前17位是否全为数字且最后1位校验码计算准确。如果所有号码都正常,则输出All passed

输入样例1:

4
320124198808240056
12010X198901011234
110108196711301866
37070419881216001X

输出样例1:

12010X198901011234
110108196711301866
37070419881216001X

输入样例2:

2
320124198808240056
110108196711301862

输出样例2:

All passed

代码:

(1)

#include<stdio.h>
#include<string.h>
typedef struct {//定义一个存放字符数组的结构体
    char idnum[20];
}infor;
infor person[101];//将该结构体申明为一个数组
int indentify(int a, char b) {//判断取模后跟第18位,即最后一位,是否匹配
    if (a == 0 && b == '1') {
        return 1;
    }
    else if (a == 1 && b == '0') {
        return 1;
    }
    else if (a == 2 && b == 'X') {
        return 1;
    }
    else if (a == 3 && b == '9') {
        return 1;
    }
    else if (a == 4 && b == '8') {
        return 1;
    }
    else if (a == 5 && b == '7') {
        return 1;
    }
    else if (a == 6 && b == '6') {
        return 1;
    }
    else if (a == 7 && b == '5') {
        return 1;
    }
    else if (a == 8 && b == '4') {
        return 1;
    }
    else if (a == 9 && b == '3') {
        return 1;
    }
    else if (a == 10 && b == '2') {
        return 1;
    }
    else {
        return 0;
    }
}
int main() {
    int count, invalid = 0;//count为人数,invalid为不合法的人数
    int temp = 0;
    char num1[20];//用于暂时存放数组,因为第十八位为x,是字母,所以存放在字符数组
    scanf("%d", &count);
    int num2[20] = { 0 };
    int j = 0;
    for (int i = 0; i < count; i++) {
        scanf("%s", &num1);//循环输入身份证
        temp = 0;
        for (j = 0; j <= 17; j++) {//将身份证的前十七位存放在整数型数组中
            num2[j] = num1[j] - '0';
        }
        //得到加权乘法后的总数
        temp = 7 * num2[0] + 9 * num2[1] + 10 * num2[2] + 5 * num2[3] + 8 * num2[4] + 4 * num2[5] + 2 * num2[6] + num2[7] + 6 * num2[8];
        temp += 3 * num2[9] + 7 * num2[10] + 9 * num2[11] + 10 * num2[12] + 5 * num2[13] + 8 * num2[14] + 4 * num2[15] + 2 * num2[16];
        temp %= 11;//得到总数取模11后的结果
        //如果取模后的结果不与要求的第18位相等,则存入结构体数组中
        //并且不合法的人数加一,用当前的不合法人数作为结构体数组下标
        if (indentify(temp, num1[17]) != 1) {
            strcpy(person[invalid].idnum, num1);
            invalid++;
        }
    }
    if (invalid == 0) {//如果不合法人数为0,输出All passed
        printf("All passed");
    }
    else {//如果不合法人数不为0,则按下标顺序逐一输出身份证号
        for (int i = 0; i < invalid; i++) {
            printf("%s\n", person[i].idnum);
        }
    }
    return 0;
}

(2)优化版

#include<stdio.h>
#include<string.h>
#include<stdbool.h>
//权重
int w[20] = {7, 9, 10, 5, 8, 4, 2, 1, 6, 3, 7, 9, 10, 5, 8, 4, 2};
//校验码
char change[15] = {'1', '0', 'X', '9', '8', '7', '6', '5', '4', '3', '2'};
int main(){
    int person;//人数
    scanf("%d", &person);
    bool flag = true;//记录是否所有的分甚至都是正确的,如果全部正确,则flag = true
    char idnum[20];
    for (int i = 0; i < person; i++){
        scanf("%s", idnum);
        int j, last = 0;//last记录前17位加权和
        for (j = 0; j < 17; j++){
            if ((idnum[j] >= '0' && idnum[j] <= '9') != 1){//如果当前的字符不在数字0-9的ASCII码范围内
                break;//跳出当前循环
            }
            last = last + (idnum[j] - '0') * w[j];//各位加权得到加权和
        }
        if (j < 17){//判断循环是正常执行还是通过break跳出
            flag = false;//通过break跳出,则说明字符串中有非数字,flag改为false
            printf("%s\n", idnum);//输出该不合法的身份证号
        }else{
            if (change[last % 11] != idnum[17]){//循环正常执行,则判断取模后的数字是否与第18位字符相等
                flag = false;//不相等改为false
                printf("%s\n", idnum);//输出该身份证
            }
        }
    }
    if (flag == true){//没有不合法的身份证
        printf("All passed\n");
    }
    return 0;
}


1002 写出这个数

读入一个正整数 n,计算其各位数字之和,用汉语拼音写出和的每一位数字。

输入格式:

每个测试输入包含 1 个测试用例,即给出自然数 n 的值。这里保证 n 小于 10100。

输出格式:

在一行内输出 n 的各位数字之和的每一位,拼音数字间有 1 空格,但一行中最后一个拼音数字后没有空格。

输入样例:

1234567890987654321123456789

输出样例:

yi san wu

代码:

(1)

#include<stdio.h>
int transferNum(char* a, int* b) {//将字符数组型数字转化为整数数组型数字
    int i;
    for (i = 0; i < 110; i++) {
        if (a[i] == '\0') {//如果当前扫描的字符为终止符,则跳出循环
            break;
        }
        else {
            b[i] = a[i] - '0';
        }
    }
    return i;//返回有多少位数字
}
int printfChinese(int a) {//判断当前扫描到的数字的中文读音,并且输出
    if (a == 0) {
        printf("ling");
    }
    else if (a == 1) {
        printf("yi");
    }
    else if (a == 2) {
        printf("er");
    }
    else if (a == 3) {
        printf("san");
    }
    else if (a == 4) {
        printf("si");
    }
    else if (a == 5) {
        printf("wu");
    }
    else if (a == 6) {
        printf("liu");
    }
    else if (a == 7) {
        printf("qi");
    }
    else if (a == 8) {
        printf("ba");
    }
    else if (a == 9) {
        printf("jiu");
    }
    return 0;
}
int main() {
    char num1[110];//用于存放数字
    int num2[110] = { 0 }, sum = 0, count, res[20];//num2存放数字,sum存放总和,count存放位数,res存放每位的结果
    scanf("%s", num1);
    count = transferNum(num1, num2);//得到数字共有几位
    for (int i = 0; i < count; i++) {//遍历数组,得到总数
        sum += num2[i];
    }
    for (count = 0; sum > 0; count++) {//得到总数每一位的数字,倒序
        res[count] = sum % 10;
        sum /= 10;
    }
    for (count--; count > 0; count--){//输出每位读音
        printfChinese(res[count]);
        printf(" ");
    }
    printfChinese(res[count]);//PAT特色输出
    return 0;
}

(2)

#include<stdio.h>
#include<string.h>
int main() {
	char str[110];
	gets(str);
	int len = strlen(str);
	int sum = 0;//用于存放所用数位之和
	for (int i = 0; i < len; i++) {
		sum += str[i] - '0';//将每一位累加
	}
	int num = 0, ans[10];//num表示sum的位数
	while (sum != 0) {
		//将sum中每一位存到数组中,sum的低位存到ans[]的低位
		ans[num] = sum % 10;
		num++;
		sum /= 10;
	}
	//定义二维数组,即change[0] = "ling",change[1] = "yi"……
	char change[10][5] = { "ling", "yi", "er", "san", "si", "wu", "liu", "qi", "ba", "jiu" };
	for (int i = num - 1; i >= 0; i--) {
		printf("%s", change[ans[i]]);
		if (i != 0) {
			printf(" ");
		}
		else {
			printf("\n");
		}
	}
	return 0;
}


1009 说反话

给定一句英语,要求你编写程序,将句中所有单词的顺序颠倒输出。

输入格式:

测试输入包含一个测试用例,在一行内给出总长度不超过 80 的字符串。字符串由若干单词和若干空格组成,其中单词是由英文字母(大小写有区分)组成的字符串,单词之间用 1 个空格分开,输入保证句子末尾没有多余的空格。

输出格式:

每个测试用例的输出占一行,输出倒序后的句子。

输入样例:

Hello World Here I Come

输出样例:

Come I Here World Hello

代码:

#include<stdio.h>
#include<string.h>
int main() {
    char str[100];//保存字符串
    gets(str);
    int len = strlen(str);//得到字符长度
    char reverse[90][90];//定义一个二维数组,用于保存每个单词
    int j = 0, k = 0;//j为单词个数,k为单词长度
    for (int i = 0; i < len; i++) {//将字符串的每个单子保存到二维数组中
        //如果当前扫描到的字符串的字符为空格,则为当前二维数组加上'\0'终止符,并且移动到下个数组
        if (str[i] == ' ') {
            reverse[j][k] = '\0';
            j++;
            k = 0;
        }
        else {//如果当前扫描到的字符串的字符不是空格,则一次保存到二维数组中,并且长度+1
            reverse[j][k] = str[i];
            k++;
        }
    }
    reverse[j][k] = '\0';//执行循环后,为最后一个单词加上终止符'\0'
    while (j >= 0) {//循环输出,PAT特色输出
        if (j != 0) {
            printf("%s ", reverse[j]);
        }
        else {
            printf("%s", reverse[j]);
        }
        j--;
    }
    return 0;
}


1014 福尔摩斯的约会

大侦探福尔摩斯接到一张奇怪的字条:

我们约会吧! 
3485djDkxh4hhGE 
2984akDfkkkkggEdsb 
s&hgsfdk 
d&Hyscvnm

大侦探很快就明白了,字条上奇怪的乱码实际上就是约会的时间星期四 14:04,因为前面两字符串中第 1 对相同的大写英文字母(大小写有区分)是第 4 个字母 D,代表星期四;第 2 对相同的字符是 E ,那是第 5 个英文字母,代表一天里的第 14 个钟头(于是一天的 0 点到 23 点由数字 0 到 9、以及大写字母 A 到 N 表示);后面两字符串第 1 对相同的英文字母 s 出现在第 4 个位置(从 0 开始计数)上,代表第 4 分钟。现给定两对字符串,请帮助福尔摩斯解码得到约会的时间。

输入格式:

输入在 4 行中分别给出 4 个非空、不包含空格、且长度不超过 60 的字符串。

输出格式:

在一行中输出约会的时间,格式为 DAY HH:MM,其中 DAY 是某星期的 3 字符缩写,即 MON 表示星期一,TUE 表示星期二,WED 表示星期三,THU 表示星期四,FRI 表示星期五,SAT 表示星期六,SUN 表示星期日。题目输入保证每个测试存在唯一解。

输入样例:

3485djDkxh4hhGE 
2984akDfkkkkggEdsb 
s&hgsfdk 
d&Hyscvnm

输出样例:

THU 14:04

注意点:

  1. 判断星期数的时候,仅需'A'-'G'
  2. 判断小时数的时候,仅需'0'-'9'和'A'-'N'

测试点示例:

测试一
3485djDkxh4hhG0 
2984akDfkkkkgg0dsb 
s&hgfdkiggggs
d&Hycvnmzzzzs

输出
THU 00:12

测试二:
HcCO2eA
HcCO2eB
cCaseC
cCaseD

输出
WED 02:00

代码:

(1)

#include<stdio.h>
#include<string.h>
char DAY[10][5] = { "MON", "TUE", "WED", "THU", "FRI", "SAT", "SUN" };//定义输出星期几的数组
char transferDay[10] = { 'A', 'B', 'C', 'D', 'E', 'F', 'G' };//定义星期天数的顺序,方便输出下标
//定义小时数的顺序,方便输出下标
char transferHour[25] = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N' };
const int dayMax = 7;//一个星期天数的最大值
const int hourMax = 24;//一天小时数的最大值
char match1(char* a, char* b, int c, int* d) {//匹配星期几
    int i;
    for (i = 0; i < c; i++) {
        if (a[i] >= 'A' && a[i] <= 'G') {//当前扫描到ASCII码中'A'-'G'时判断
            if (a[i] == b[i]) {//如果两个数组的下标相同的字符相等
                break;//跳出循环
            }
        }
    }
    *d = i;//保存下标
    return a[i];//返回相同的字符
}
char match2(char* a, char* b, int c, int d) {//匹配小时数
    int i;
    for (i = c + 1; i < d; i++) {//从上次相同的字符的下一个元素开始遍历
        if ((a[i] >= '0' && a[i] <= '9') || (a[i] >= 'A' && a[i] <= 'N')) {//当前扫描的元素为'0'-'9'或者'A'-'N'时
            if (a[i] == b[i]) {//如果两个数组的下标相同的字符相等
                break;//跳出循环
            }
        }
    }
    return a[i];//返回相同的元素
}
int match3(char* a, char* b, int c) {//判断分钟数
    int i;
    for (i = 0; i < c; i++) {
        if ((a[i] >= 'a' && a[i] <= 'z') || (a[i] >= 'A' && b[i] <= 'Z')) {//当前扫描的元素是'a'-'z'或'A'-'Z'时
            if (a[i] == b[i]) {//如果两个数组的下标相同的字符相等
                break;//跳出循环
            }
        }
    }
    return i;//返回数组元素下标
}
int transferDaySequence(char a, char* b) {//判断当前的字符在星期的顺序数
    int i;
    for (i = 0; i < dayMax; i++) {
        if (a == b[i]) {//扫描到的字符相等
            break;//跳出循环
        }
    }
    return i;
}
int transferHourSequence(char a, char* b) {//判断输出小时数
    int i;
    for (i = 0; i < hourMax; i++) {
        if (a == b[i]) {//扫描到的字符相等
            break;//跳出循环
        }
    }
    return i;
}
int main() {
    char str[4][80];
    gets(str[0]);
    gets(str[1]);
    gets(str[2]);
    gets(str[3]);
    int len0 = strlen(str[0]);
    int len1 = strlen(str[1]);
    int len2 = strlen(str[2]);
    int len3 = strlen(str[3]);
    len0 = (len0 < len1) ? len0 : len1;//保存两个数组中更小的长度
    int firstMatch = 0;//保存第一次扫描到的数组下标
    char daySequence = match1(str[0], str[1], len0, &firstMatch);//得到相同字符
    int day = transferDaySequence(daySequence, transferDay);//得到星期数的顺序下标
    char resDay[5];
    strcpy(resDay, DAY[day]);//拷贝字符串得到最终结果
    char hourSequence = match2(str[0], str[1], firstMatch, len0);//得到相同字符
    int resHour = transferHourSequence(hourSequence, transferHour);//得到小时数
    len2 = (len2 < len3) ? len2 : len3;//保存两个数组中更小的长度
    int resMinute = match3(str[2], str[3], len2);//得到分钟数
    printf("%s %02d:%02d", resDay, resHour, resMinute);
    return 0;
}

(2)

#include<stdio.h>
#include<string.h>
int main(){
    char week[7][5] = {
        "MON", "TUE", "WED", "THU", "FRI", "SAT", "SUN"
    };
    char str1[70], str2[70], str3[70], str4[70];
    gets(str1);
    gets(str2);
    gets(str3);
    gets(str4);
    int len1 = strlen(str1);
    int len2 = strlen(str2);
    int len3 = strlen(str3);
    int len4 = strlen(str4);
    int i;
    //寻找str1和str2中第一队相同位置的A-G的大写字母
    for (i = 0; i < len1 && i < len2; i++){
        if(str1[i] == str2[i] && str1[i] >= 'A' && str1[i] <= 'G'){
            printf("%s ", week[str1[i] - 'A']);//输出星期几
            break;
        }
    }
    //往后寻找第二个相同元素,范围为0-9或A-N
    for (i++; i < len1 && i < len2; i++){
        if(str1[i] == str2[i]){
            if(str1[i] >= '0' && str1[i] <= '9'){
                printf("%02d:", str1[i] - '0');//输出0-9
                break;
            }
            else if(str1[i] >= 'A' && str1[i] <= 'N'){
                printf("%02d:", str1[i] - 'A' + 10);//输出10-23
                break;
            }
        }
    }
    //寻找str3和str4第一对相同元素,范围为A-Z或a-z
    for (i = 0; i < len3 && i < len4; i++){
        if(str3[i] == str4[i]){
            if((str3[i] >= 'A' && str3[i] <='Z') || (str3[i] >= 'a' && str3[i] <= 'z')){
                printf("%02d", i);//输出当前下标
                break;
            }
        }
    }
    return 0;
}


1024 科学计数法

科学计数法是科学家用来表示很大或很小的数字的一种方便的方法,其满足正则表达式 [+-][1-9].[0-9]+E[+-][0-9]+,即数字的整数部分只有 1 位,小数部分至少有 1 位,该数字及其指数部分的正负号即使对正数也必定明确给出。

现以科学计数法的格式给出实数 A,请编写程序按普通数字表示法输出 A,并保证所有有效位都被保留。

输入格式:

每个输入包含 1 个测试用例,即一个以科学计数法表示的实数 A。该数字的存储长度不超过 9999 字节,且其指数的绝对值不超过 9999。

输出格式:

对每个测试用例,在一行中按普通数字表示法输出 A,并保证所有有效位都被保留,包括末尾的 0。

输入样例 1:

+1.23400E-03

输出样例 1:

0.00123400

输入样例 2:

-1.2E+10

输出样例 2:

-12000000000

代码:

(1)

#include<stdio.h>
#include<string.h>
int main() {
    char num[10020];//指数绝对值不超过9999,测试点6
    gets(num);
    int i, locateE, locatePoint, power = 0;//locateE用来存储E的位置,locatePoint用来存储.的位置,power用来存储指数
    int len = strlen(num);//得到字符串的长度
    for (i = 0; i < len; i++) {//确定E和小数点的位置 
        if (num[i] == 'E') {
            locateE = i;
        }
        if (num[i] == '.') {
            locatePoint = i;
        }
    }
    if (num[0] == '-') {//如果是负数,则输入负号
        printf("-");
    }
    for (int j = locateE + 2; j < len; j++) {//得到指数
        power *= 10;
        power += num[j] - '0';
    }
    if (num[locateE + 1] == '+') {//如果指数是正数
        if (power >= locateE - locatePoint - 1) {//判断指数是否大于小数的位数
            for (int j = 1; j < locateE; j++) {//输出所有数字,包括小数
                if (num[j] != '.') {//判断当前的字符是不是.
                    printf("%c", num[j]);
                }
            }
            for (int j = 0; j < power - locateE + locatePoint + 1; j++) {//输出多余的0
                printf("0");
            }
        }
        else {
            for (int j = 1; j < locatePoint + power + 1; j++) {//输出整数部分
                if (num[j] != '.') {
                    printf("%c", num[j]);
                }
            }
            printf(".");//输出.
            for (int j = locatePoint + power + 1; j < locateE; j++) {//输出小数部分
                printf("%c", num[j]);
            }
        }
    }
    else {//如果幂次方是负数
        if (power == 0) {//如果指数为0
            for (int j = 1; j < locateE; j++) {
                printf("%c", num[j]);//输出本来的数字
            }
        }
        else if (power >= 1) {//如果指数大于1
            printf("0.");//输出0.前缀
            for (int j = 0; j < power - 1; j++) {//输出多余的0
                printf("0");
            }
            for (int j = 1; j < locateE; j++) {//输出数字
                if (num[j] != '.') {
                    printf("%c", num[j]);
                }
            }
        }
    }
    return 0;
}

(2)

#include<stdio.h>
#include<string.h>
int main(){
    char str[10010];
    gets(str);
    int len = strlen(str);
    if (str[0] == '-'){//如果是负数,输出负号
        printf("-");
    }
    int pos = 0;//pos存放字符串中E的位置
    while (str[pos] != 'E'){
        pos++;
    }
    int exp = 0;//exp保存指数
    for (int i = pos + 2; i < len; i++){
        exp = exp * 10 + (str[i] - '0');
    }
    if (exp == 0){//判断指数为0
        for (int i = 1; i < pos; i++){
            printf("%c", str[i]);
        }
    }
    if (str[pos + 1] == '-'){//如果指数为负
        printf("0.");
        for (int i = 0; i < exp - 1; i++){//输出(exp - 1)个0
            printf("0");
        }
        printf("%c", str[1]);//输出除了小数点意外的数字
        for (int i = 3; i < pos; i++){
            printf("%c", str[i]);
        }
    }
    else{//如果指数为正
        for (int i = 1; i < pos; i++){
            if(str[i] == '.'){//略过原小数点
                continue;
            }
            printf("%c", str[i]);//输出当前数位
            if(i == exp + 2 && pos - 3 != exp){//小数点加上位置(exp + 2)上
                //原小数点和E之间的数字个数(pos -3)不能等于小数点右移位数exp
                printf(".");
            }
        }
        //如果指数exp更大,输出多余的0
        for (int i = 0; i < exp - (pos - 3); i++){
            printf("0");
        }
    }
    return 0;
}


1048 数字加密 

本题要求实现一种数字加密方法。首先固定一个加密用正整数 A,对任一正整数 B,将其每 1 位数字与 A 的对应位置上的数字进行以下运算:对奇数位,对应位的数字相加后对 13 取余——这里用 J 代表 10、Q 代表 11、K 代表 12;对偶数位,用 B 的数字减去 A 的数字,若结果为负数,则再加 10。这里令个位为第 1 位。

输入格式:

输入在一行中依次给出 A 和 B,均为不超过 100 位的正整数,其间以空格分隔。

输出格式:

在一行中输出加密后的结果。

输入样例:

1234567 368782971

输出样例:

3695Q8118

代码:

(1)

#include<stdio.h>
#include<string.h>
char odd[15] = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'J', 'Q', 'K' };
char oddNum(char* a, char* b, int c, int d) {//奇数位
    int temp = a[c] - '0' + b[d] - '0';//得到两个数列相应元素数字的合
    temp %= 13;//对13取余
    return odd[temp];//返回odd数列的结果
}
int evenNum(char* a, char* b, int c, int d) {//偶数位
    int temp = b[d] - '0' - a[c] + '0';//B - A
    if (temp < 0) {//如果结果为负数,+10
        temp += 10;
    }
    return temp;
}
int main() {
    char str1[110], str2[110];
    scanf("%s", str1);
    scanf("%s", str2);
    int len1 = strlen(str1);
    int len2 = strlen(str2);
    int temp1;
    char temp2;
    if (len2 > len1) {//当B的长度 > A时
        for (int i = 0; i < len2 - len1; i++) {//输出B比A长的部分
            printf("%c", str2[i]);
        }
        for (int i = 0, j = len2 - len1; i < len1; i++, j++) {//遍历A和B剩余的字符串
            if ((len1 - i) % 2 != 0) {//奇数
                temp2 = oddNum(str1, str2, i, j);
                printf("%c", temp2);
            }
            else {//偶数
                temp1 = evenNum(str1, str2, i, j);
                printf("%d", temp1);
            }
        }
    }
    else {//B长度 <= A时
        int j;
        char str3[110];
        for (j = 0; j < len1 - len2; j++) {//补str1和str2长度差额的0
            str3[j] = '0';
        }
        str3[j] = '\0';//添加终止符
        strcat(str3, str2);//将str2的字符串内容添加到str3后
        for (int i = 0; i < len1; i++) {//遍历字符串,因为str1和str3长度相等,仅需遍历str1
            if ((len1 - i) % 2 != 0) {//奇数
                temp2 = oddNum(str1, str3, i, i);
                printf("%c", temp2);
            }
            else {//偶数
                temp1 = evenNum(str1, str3, i, i);
                printf("%d", temp1);
            }
        }
    }
    return 0;
}

(2)

#include<stdio.h>
#include<string.h>
char A[110], B[110], ans[110];
void reverse(char* s){//反转字符串
    int len = strlen(s);
    for (int i = 0; i < len / 2; i++){//交换s[i]和s[len - 1 - i]
        int temp = s[i];
        s[i] = s[len - 1 - i];
        s[len - 1 - i] = temp;
    }
}
int main(){
    scanf("%s %s", A, B);//整数A和B
    reverse(A);
    reverse(B);
    int lenA = strlen(A);//A长度
    int lenB = strlen(B);//B长度
    int len = lenA > lenB ? lenA : lenB;//A和B较大长度
    for(int i = 0; i < len; i++){//从低位开始
        int numA = i < lenA ? A[i] - '0' : 0;//numA对应A[i]
        int numB = i < lenB ? B[i] - '0' : 0;//numB对应B[i]
        if(i % 2 ==0){//当前位i是偶数
            int temp = (numB + numA) % 13;//和再模13
            if(temp == 10) ans[i] = 'J';//特判10、11、12
            else if (temp == 11) ans[i] = 'Q';
            else if (temp == 12) ans[i] = 'K';
            else ans[i] = temp + '0';//0-9
        }
        else{//当前位i是奇数
            int temp = numB - numA;//差
            if(temp < 0) temp += 10;//如果小于0,加上10
            ans[i] = temp + '0';//赋对应字符
        }
    }
    reverse(ans);//反转字符串
    puts(ans);//输出结果
    return 0;
}

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值