I am a teacher!

导航

C语言程序设计100例之(80):ISBN 号码

例80   ISBN 号码

问题描述

每一本正式出版的图书都有一个ISBN号码与之对应,ISBN码包括9位数字、1位识别码和3位分隔符,其规定格式如x-xxx-xxxxx-x,其中符号-就是分隔符(键盘上的减号),最后一位是识别码,例如0-670-82162-4就是一个标准的ISBN码。ISBN码的首位数字表示书籍的出版语言,例如0代表英语;第一个分隔符-之后的三位数字代表出版社,例如670代表维京出版社;第二个分隔符后的五位数字代表该书在该出版社的编号;最后一位为识别码。

识别码的计算方法如下:

首位数字乘以1加上次位数字乘以2……以此类推,用所得的结果mod11,所得的余数即为识别码,如果余数为10,则识别码为大写字母X。例如ISBN号码0-670-82162-4中的识别码4是这样得到的:对067082162这9个数字,从左至右,分别乘以1,2,...,9再求和, 0×1+6×2+……+2×9=158,然后取158 mod 11的结果4作为识别码。

你的任务是编写程序判断输入的ISBN号码中识别码是否正确,如果正确,则仅输出Right;如果错误,则输出你认为是正确的ISBN号码。

输入

一个字符序列,表示一本书的ISBN号码(保证输入符合ISBN号码的格式要求)。

输出

一行,假如输入的ISBN号码的识别码正确,那么输出Right,否则,按照规定的格式,输出正确的ISBN号码(包括分隔符-)。

输入样例

0-670-82162-0

输出样例

0-670-82162-4

        (1)编程思路。

        简单的字符串模拟题。用循环对字符串中的前11个字符进行处理,计算出识别码与最后一个字符比较,根据比较结果输出相应信息。

        (2)源程序。
#include <stdio.h>
int main()
{
    char isbn[14],ch;
    int i,k,s;
    scanf("%s",isbn);
    for (i=0,k=0,s=0;i<=10;i++)
        if (isbn[i]!='-')
        {
           k++;
           s+=k*(isbn[i]-'0');
        }
    if (s%11==10)  ch='X';
    else  ch=(s%11)+'0';
    if (isbn[12]==ch) printf("Right\n");
    else { isbn[12]=ch; printf("%s\n",isbn); }
    return 0;
}

        将此源程序提交给洛谷OJ题库 P1055 ISBN 号码(https://www.luogu.com.cn/problem/P1055)可以Accepted。

习题80

80-1  信用卡号的验证

问题描述

当你输入信用卡号码的时候,有没有担心输错了而造成损失呢?其实可以不必这么担心,因为并不是一个随便的信用卡号码都是合法的,它必须通过Luhn算法来验证通过。

该校验的过程:

1、从卡号最后一位数字开始,逆向将奇数位(1、3、5等等)相加。

2、从卡号最后一位数字开始,逆向将偶数位数字,先乘以2(如果乘积为两位数,则将其减去9),再求和。

3、将奇数位总和加上偶数位总和,结果应该可以被10整除。

例如,卡号是:5432123456788881

则奇数位和=35

偶数位乘以2(有些要减去9)的结果:1 6 2 6 1 5 7 7,求和=35。

最后35+35=70 可以被10整除,认定校验通过。

请编写一个程序,从键盘输入卡号,然后判断是否校验通过。通过显示:“Right”,否则显示“Wrong”。

输入

一串信用卡号。

输出

判断结果。

输入样例

356827027232780

输出样例

成功

       (1)编程思路。

        简单的字符串模拟题,用循环对字符串按题目要求进行处理。

       (2)源程序。

#include <stdio.h>
#include <string.h>
int main()
{
    char s[26];
    scanf("%s",s);
    int sum=0,t;
    int i,f;
    for (i=strlen(s)-1,f=1;i>=0;i--,f=1-f)
    {
        if (f==1)
            sum+=s[i]-'0';
        else
        {
            t=2*(s[i]-'0');
            if (t>9) t-=9;
            sum+=t;
        }
    }
    if (sum%10==0) printf("Right\n");
    else  printf("Wrong\n");
    return 0;
}
80-2  宝石串

问题描述

有一种宝石串,由绿宝石和红宝石串成,仅当绿宝石和红宝石数目相同的时候,宝石串才最为稳定,不易断裂。安安想知道从给定的宝石串中,可以截取一段最长的稳定的宝石串,有多少颗宝石组成。请你帮助他。

绿宝石用‘G’表示,红宝石用‘R'表示。

输入

一行由G和R组成的字符串

输出

最长的稳定的宝石串有多少颗宝石组成

输入样例

GRGGRG

输出样例

4

        (1)编程思路。

        定义两个数组int a[1000001],b[1000001];,其中a[i]和b[i]分别表示前一个宝石中绿宝石和红宝石的个数,初始值全部为0。

        用循环对宝石串进行扫描处理,计算出数组a和b各元素的值。

        之后对区间[i,j](区间左端点从1~n,n为宝石串中宝石的个数;右端点从n~i)进行处理,若在某段区间中,绿宝石的个数a[j]-a[i-1]和红宝石的个数b[j]-b[i-1]相等,则这段区间中的宝石可以构成稳定的宝石串,穷举找到最长的区间即可。

        (2)源程序。

#include <stdio.h>
int a[1000001],b[1000001];
int main()
{
    char str[1000001];
    scanf("%s",str);
    a[0]=b[0]=0;
    int i,j;
    for (i=1;str[i-1]!='\0';i++)
    {
       if (str[i-1]=='G')
       {
           a[i]=a[i-1]+1;
           b[i]=b[i-1];
       }
       else
       {
           b[i]=b[i-1]+1;
           a[i]=a[i-1];
       }
    }
    int n=i-1;
    if (a[n]==0 || b[n]==0)
    {
        printf("0\n");
        return 0;
    }
    int ans=0;
    for (i=1;i<=n;i++)   // 区间左端点
    {
        if (n-i+1<ans) break;
        for (j=n;j>=i;j--)
        {
            if (j-i+1<=ans) break;
            if (a[j]-a[i-1]==b[j]-b[i-1])
              if (ans<j-i+1) ans=j-i+1;
        }
    }
    printf("%d\n",ans);
    return 0;
}

        将此源程序提交给洛谷OJ题库 P2697 宝石串(https://www.luogu.com.cn/problem/P2697)可以Accepted。

80-3  方便记忆的电话号码

问题描述

英文字母(除Q和Z外)和电话号码存在着对应关系,如下所示:

A,B,C -> 2

D,E,F -> 3

G,H,I -> 4

J,K,L -> 5

M,N,O -> 6

P,R,S -> 7

T,U,V -> 8

W,X,Y -> 9

标准的电话号码格式是xxx-xxxx,其中x表示0-9中的一个数字。有时为了方便记忆电话号码,我们会将电话号码的数字转变为英文字母,如把263-7422记成America。有时,我们还加上“-”作为分隔符,如把449-6753记成Hi-World。当然,我们未必要将所有的数字都转变为字母,比如474-6635可以记成iPhone-5。

总之,一个方便记忆的电话号码由数字和除Q、Z外的英文字母组成,并且可以在任意位置插入任意多的“-”符号。

现在 ,我们有一个列表,记录着许多方便记忆的电话号码。不同的方便记忆的电话号码可能对应相同的标准号码,你的任务就是找出它们。

输入

第一行是一个正整数n(n <= 100000),表示列表中的电话号码数。

其后n行,每行是一个方便记忆的电话号码,它由数字和除Q、Z外的英文字母、“-”符号组成,其中数字和字母的总数一定为7,字符串总长度不超过200。

输出

输出包括若干行,每行包括一个标准电话号码(xxx-xxxx)以及它重复出现的次数k(k >= 2),中间用空格分隔。输出的标准电话号码需按照升序排序。

如果没有重复出现的标准电话号码,则输出一行“No duplicates.”。

输入样例

12

4873279

ITS-EASY

888-4567

3-10-10-10

888-GLOP

TUT-GLOP

967-11-11

310-GINO

F101010

888-1200

-4-8-7-3-2-7-9-

487-3279

输出样例

310-1010 2

487-3279 4

888-4567 3

         (1)编程思路。

        编写函数int ctoi(char ch),按英文字母(除Q和Z外)和电话号码存在的对应关系,把字符ch转换为对应的数字。

        输入时将所有的电话号码全部转换为全部由7位数字表示的电话号码后进行保存,去掉输入中的连接符“-”,将字母全部转换为对应的数字。

        将保存好的电话号码按整数从小到大排列,这样相同的号码一定会排列在一起,用循环对排序好的数组进行扫描处理,重复次数超过2的电话号码按要求格式输出。

        (2)源程序。

#include <stdio.h>
#include <algorithm>
using namespace std;
int ctoi(char ch)      // 把字符ch转换为对应的数字
{
    if(ch=='A' || ch=='B' || ch=='C')
        return 2;
    if(ch=='D' || ch=='E' || ch=='F')
        return 3;
    if(ch=='G' || ch=='H' || ch=='I')
        return 4;
    if(ch=='J' || ch=='K' || ch=='L')
        return 5;
    if(ch=='M' || ch=='N' || ch=='O')
        return 6;
    if(ch=='P' || ch=='R' || ch=='S')
        return 7;
    if(ch=='T' || ch=='U' || ch=='V')
        return 8;
    if(ch=='W' || ch=='X' || ch=='Y')
        return 9;
    if (ch>='0' && ch<='9')
        return ch-'0';
}
int main()
{
    int n;             //号码数
    scanf("%d",&n);
    int out[100001];   // 存放待输出的电话号码
    int num,i,j;
    for(i=0;i<n;i++)
    {
        num=0;
        char s[201];
        scanf("%s",s);
        for (j=0;s[j]!='\0';j++)
        {
            if(s[j]=='-' || s[j]=='Q' || s[j]=='Z')
                continue;
            num=num*10+ctoi(s[j]);
        }
        out[i]=num;
    }
    sort(out,out+n);
    int flag=1;        // 标记是否所有号码都是唯一的
    i=0;
    while (i<n)
    {
        int times=0;       //  out[i]出现的次数
        int k=out[i];
        int  sign=0;       // 标记k出现次数是否大于2
         while (i<n && k==out[i])
        {
            times++;
            i++;
            if(times==2)
            {
                flag=0;
                sign=1;
            }
        }
        if (sign)
        {
            printf("%03d-%04d %d\n",k/10000,k%10000,times);
        }
    }
    if (flag)
        printf("No duplicates.\n");
    return 0;
}

        将此源程序提交给北大OJ题库 POJ 1002 487-3279(http://poj.org/problem?id=1002)可以Accepted。

posted on 2022-03-29 11:13  aTeacher  阅读(955)  评论(0编辑  收藏  举报