C和指针_编程练习_第9章_第12题

/*
        有一种技巧可以对数据进行加密, 并使用一个单词作为它的密钥. 下面是它的工作原理:
        首先, 选择一个单词作为密钥. 如:TRAILBLAZERS. 如果单词中包含重复的字母, 只保留第一个, 其余几个丢弃.
        现在, 修改过的那个单词列于字母表的下面, 如下所示:
        A 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
        T R A I L B Z E S
        
        最后, 底下的那行字母用剩余的字母填充完整:
        A 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
        T R A I L B Z E S C D F G H J K M N O P Q U V W X Y

        在对信息进行加密时, 信息中的每个字母被固定于顶上那行, 并用下面那行的对应字母一一取代原文的字母.
        因此, 使用这个密钥, ATTACK AT DAWN(黎明时进攻)就会被翻译成TPPTAD TP ITVH.

        这个题材共有三个程序(包含下面两个题目). 在第一个程序中, 你需要编写函数:
        int prepare_key( char *key );
        
        它接受一个字符串参数, 它的内容就是需要使用的密钥单词. 函数根据上面描述的方法把它转化成一个包含编好码的字符串数组. 假定key参数是个字符数组, 其长度至少可以容纳27个字符.
        函数必须把密钥中所有的字符要么转化成大写字母, 要么转化成小写字母(随你选择), 并且从单词中去除重复出现的字母, 然后再用字母表中剩余的字母按照你原先所选择的大小写形式填充到key数组中.
        如果处理成功, 函数返回一个真值. 如果key参数为空或者包含任何非字母字符, 函数返回一个假值.
*/

typedef char bool;
#define true 1
#define false 0
#define MIN_KEY 27

bool prepare_key( char *key )
{
        /*
         * keyMark: 字符数组的起点
         * modify: 永远指向待修改的字符
         * compare: 遍历字符数组并比较字符的指针
         * Is_Appeared: 布尔值, 标定比较结果
         */
        char *keyMark = key;
        char *modify;
        char *compare;
        bool Is_Appeared;

        /* 遍历字符数组中的密钥(实质上是字符串), 逐字符判断密钥中是否包含重复字母, 删除重复字母 */
        for( modify = keyMark; *key != '\0'; ++key )
        {
                /* 如果key 指向的字符不是字母, 函数返回false */
                if( !( ( *key >= 'A' && *key <= 'Z' ) || ( *key >= 'a' && *key <= 'z' ) ) ) 
                {
                        return false;
                }

                /* 执行到这里说明key 指向的值是字母, 如果是大写, 就转化成小写 */
                if( *key <= 'Z'  )
                {
                        *key += 32; 
                }
    
                /* 
                 * 检查key 对应的字母是否是重复字母
                 * 如果是重复字母, 用Is_Appeared 标记, 并跳出循环
                 */
                Is_Appeared = false;
                for( compare = keyMark; compare != modify; ++compare )
                {
                        if( *compare == *key )
                        {
                                Is_Appeared = true;
                                break;
                        }
                }

                /* 如果Is_Appeared 为false, 说明不重复, 记录下key 对应的字母, 然后modify 后移一位, modify 永远都不会超前于key, 所以不用担心数组越界 */
                if( !Is_Appeared )
                {
                        *modify++ = *key;
                }
        }
        
        /* 
         * 执行到这里说明密钥部分已经全部处理完毕(去重复化), 接下来的工作是填充剩余字母
         * letter: 表示字母a ~ z
         * modifyMark: 比较的终点
         */
        char letter;
        char *const modifyMark = modify;

        /* 判断从a 开始到z 结束的字母是否在新密钥部分出现过, 如果出现过就不填充 */
        for( letter = 'a'; letter <= 'z'; ++letter )
        {
                Is_Appeared = false;
                for( compare = keyMark; compare != modifyMark; ++compare )
                {
                        if( letter == *compare )
                        {
                                Is_Appeared = true;
                                break;
                        }
                }

                /* 如果letter对应的字母没有出现过, 要填充 */
                if( !Is_Appeared )
                {
                        *modify++ = letter;
                }
        }

        /* 执行到这里说明填充完毕, 还需要在有效字符后面加上一个NUL字符, 使之满足字符串格式 */
        *modify = '\0';

        return true;
}

#include <stdio.h>

int main( void )
{
        char ret = false;

        char key[MIN_KEY] = "TRAILBLAZERS";
        printf( "密钥:%s\n", key );
        ret = prepare_key( key );
        if( ret == true )
        {
                printf( "编码:%s\n", key );
        }
        else
        {
                printf( "函数返回值为false\n" );
        }

        char falseKey[MIN_KEY] = "P51";
        printf( "密钥:%s\n", falseKey );
        ret = prepare_key( falseKey );
        if( ret == true )
        {
                printf( "编码:%s\n", falseKey );
        }
        else
        {
                printf( "函数返回值为false\n" );
        }

        return 0;
}

程序运行结果:
gcc version 8.3.1 20191121 (Red Hat 8.3.1-5) (GCC)

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值