鱼C论坛

 找回密码
 立即注册
查看: 2818|回复: 13

关于vigenger加密问题 (C语言)

[复制链接]
发表于 2020-3-31 11:45:40 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能^_^

您需要 登录 才可以下载或查看,没有账号?立即注册

x
本帖最后由 北有樵先生 于 2020-4-8 15:10 编辑

问题是输出期望的结果后,有有一些不符合期望的字符跟在其后面。具体描述在代码最后。代码如下:
# include <stdio.h>
# include <stdlib.h>
# include <time.h>
# include <string.h>


# define OK         1 
# define ERROR  0
# define SIZE   16  

typedef char Elemtype ;
typedef struct node 
{
        Elemtype elem ;
        struct node *next ;
        struct node *previous ;
}node , *Linklist ;

static char* input_plaintext (void) ;
static void create_BidCirlinklist ( Linklist *L) ;
static int * create_CipherKey ( int len ) ;
static node* find_ch (Linklist L , Elemtype ch)  ;
static void create_one_cipher (node*S , int n , Elemtype *ch) ;
static Elemtype* create_Cipher (Linklist L, int len , int *key , char * passward)  ;

int main (void)
{
        FILE *fp ;
        int len , *key , i;
        Elemtype *password , *new_password ;
        Linklist l = NULL;
        if ( (fp = fopen("Encrypted.txt", "wb")) == NULL)
        {
                printf("打开文件失败\n") ;
                exit(EXIT_FAILURE) ;
        }
        password = input_plaintext() ;
        len = strlen(password) ;
        key = create_CipherKey(len) ;   
        fwrite(password,sizeof(char),len,fp) ;
        fwrite(key,sizeof(int),len,fp) ;
        fclose(fp) ; // 至此写入明文和密匙,以二进制的形式 
        create_BidCirlinklist(&l) ;
        new_password = create_Cipher(l,len,key,password) ;
        printf ("%s\n",password) ;    // 从这里开始便是验证输入和输出结果
        i = 0 ;
        while ( i < len )
        {
                printf("%2d ",key[i]) ;
                i++;
        }
        printf("\n") ;
        for( i = 0; i < len ; i++)
        {
                printf("%c ",new_password[i]) ;  // 单个字母输出并无问题
        }
        printf("\n") ;
        printf("%s\n",new_password) ;  // 问题出现在这个输出上
        free(new_password);
        free(key);
        return 0;
}
// 输入明文 
static char* input_plaintext (void) 
{
        int Len ;
        char *Str ,*str;
        str = (char*)malloc( SIZE * sizeof(char)) ;
        printf ("请输入明文(至多输入16位):") ;
        scanf ("%s",str) ;
        Len = strlen(str) ;
        Str = (char*)malloc( Len * sizeof(char)) ;
        strcpy(Str,str) ;
        return Str ;
}
// 建立解密环 
static void create_BidCirlinklist ( Linklist *L) // L是指针的指针 
{
        node *flag , *new_node ;
        int i = 0 ;
        while ( i< 26 )
        {
                new_node = (node *)malloc(sizeof(node )) ;
                new_node->elem = 'A'+i ;
                if ((*L) == NULL )
                {
                        flag = (*L) = new_node ;
                        flag->next = flag->previous = NULL ;
                }
                else 
                {
                        new_node->next = flag->next ;
                        flag->next = new_node ;
                        new_node->previous = flag ;
                        flag = new_node ;
                }
                i++ ; 
        }
        flag->next = (*L) ;
        (*L)->previous = flag ;
}
// 生成随机密匙 
static int * create_CipherKey ( int len )
{
        int i ;
        int *Key = (int *)malloc(sizeof(int) * len) ;
        time_t t;
        srand(time(&t)) ;
        for( i = 0 ; i < len ; i++)
        {
                Key[i] = rand()%100 ;
        }
        return Key ;
}

// 生成密文 
static Elemtype* create_Cipher (Linklist L, int len , int *key , char * passward)  
{
        int i ;
        Elemtype *new_cipher = (Elemtype*)malloc( sizeof(Elemtype)*len ) ;
        node *flag ;
        for ( i = 0 ; i < len ; i++)
        {
                flag = find_ch(L , passward[i]) ;
                create_one_cipher(flag,key[i],&new_cipher[i]) ;
        }
        return new_cipher ;
}

// 找到对应的字母,便于生成新字母 
static node* find_ch (Linklist l , Elemtype ch) 
{
        node *flag1 = l ;
        if ( ch > 'Z')
        {
                ch -= 32 ;
        }
        if ( ch <= 'M')
        {
                while (flag1->elem != ch)
                        flag1 = flag1->next ;
        }
        else
        {
                while (flag1->elem != ch)
                        flag1 = flag1->previous ;
        }
        return flag1 ;
}

// 生成新一位密文并用ch返回 
static void create_one_cipher (node*S , int n , Elemtype *ch)  // 当n的绝对值大于13时 向反方向移动 提高效率 
{
        node *flag2 = S ;
        if ( n > 0)
        {
                n %= 26 ;
                if ( n >13)
                {
                        while (n--)
                                flag2 = flag2->previous;
                }
                else
                {
                        while (n--)
                                flag2 = flag2->next ;
                }        
        }
        else
        {
                n %= -26 ;
                if ( n >13)
                {
                        while (n++)
                                flag2 = flag2->previous;
                }
                else
                {
                        while (n++) 
                                flag2 = flag2->next ;
                }        
        }
        *ch = flag2->elem ;
}

我已经调试了,结果都正确,问题在于结果后会跟不相符的字符;

这个临界点出现在输入7个字母和8个字母,8个字符往后都会出现这些,而且越多,我已经调试完了,可以正常运行,单个字母进行输出,也可以得到结果

因为是新人所以不能上传图片,但程序可运行,可以尝试输入,谢谢
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

发表于 2020-3-31 12:09:07 | 显示全部楼层
给出输入样例和输出结果,如果有必要,再指出哪里和你期望的结果不符
这样会对我调试程序很有帮助
还有代码写的也挺长了,该学一学调试程序的方法了
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2020-3-31 14:16:33 | 显示全部楼层
本帖最后由 北有樵先生 于 2020-3-31 15:56 编辑
人造人 发表于 2020-3-31 12:09
给出输入样例和输出结果,如果有必要,再指出哪里和你期望的结果不符
这样会对我调试程序很有帮助
还有代 ...


你的前半句很有道理,是我对问题的描述不够,我已经改了,谢谢。不过我想说,一上来就质疑人啥都没干,这种行为很愚蠢
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2020-3-31 16:57:08 | 显示全部楼层
北有樵先生 发表于 2020-3-31 14:16
你的前半句很有道理,是我对问题的描述不够,我已经改了,谢谢。不过我想说,一上来就质疑人啥都没干, ...

你修改后的结果也一样,对调试程序没有任何帮助
我期望的是像下面这样的
输入:abcd1234
输出:234abcd1+
我期望的输出是:1234abcd
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2020-3-31 18:40:53 | 显示全部楼层
发现了好多问题
# include <stdio.h>
# include <stdlib.h>
# include <time.h>
# include <string.h>


# define OK         1 
# define ERROR  0
# define SIZE   16  

typedef char Elemtype ;
typedef struct node 
{
        Elemtype elem ;
        struct node *next ;
        struct node *previous ;
}node , *Linklist ;

static char* input_plaintext (void) ;
static void create_BidCirlinklist ( Linklist *L) ;
static int * create_CipherKey ( int len ) ;
static node* find_ch (Linklist L , Elemtype ch)  ;
static void create_one_cipher (node*S , int n , Elemtype *ch) ;
static Elemtype* create_Cipher (Linklist L, int len , int *key , char * passward)  ;

int main (void)
{
        FILE *fp ;
        int len , *key , i;
        Elemtype *password , *new_password ;
        Linklist l = NULL;
        srand(time(NULL)) ;     // 放在这里更好
        if ( (fp = fopen("Encrypted.txt", "wb")) == NULL)
        {
                printf("打开文件失败\n") ;
                exit(EXIT_FAILURE) ;
        }
        password = input_plaintext() ;
        len = strlen(password) ;
        key = create_CipherKey(len) ;   
        fwrite(password, 1, len, fp) ;
        fwrite(key,sizeof(int),len,fp) ;
        fclose(fp) ; // 至此写入明文和密匙,以二进制的形式 
        create_BidCirlinklist(&l) ;
        new_password = create_Cipher(l,len,key,password) ;
        printf ("%s\n",password) ;    // 从这里开始便是验证输入和输出结果
        i = 0 ;
        while ( i < len )
        {
                printf("%2d ",key[i]) ;
                i++;
        }
        printf("\n") ;
        for( i = 0; i < len ; i++)
        {
                printf("%c ",new_password[i]) ;  // 单个字母输出并无问题
        }
        printf("\n") ;
        printf("%s\n",new_password) ;  // 问题出现在这个输出上      // 你期望这个printf输出什么内容?
        free(password);         // 少了这个吧?
        free(new_password);
        free(key);
        return 0;
}
// 输入明文 
static char* input_plaintext (void) 
{
#if 0
        int Len ;
        char *Str ,*str;
        str = (char*)malloc(SIZE) ;     // 永远都不需要乘一个sizeof(char)
        printf ("请输入明文(至多输入16位):") ;
        scanf ("%s",str) ;
        Len = strlen(str) ;
        Str = (char*)malloc(Len + 1) ;  // 这里不需要加1吗?
        strcpy(Str,str) ;
        free(str);          // 这里不需要free吗?
        return Str ;
#endif
        char *str = malloc(5);
        strcpy(str, "abcd");
        return str;
}
// 建立解密环 
static void create_BidCirlinklist ( Linklist *L) // L是指针的指针 
{
        node *flag , *new_node ;
        int i = 0 ;
        while ( i< 26 )
        {
                new_node = (node *)malloc(sizeof(node )) ;
                new_node->elem = 'A'+i ;
                if ((*L) == NULL )
                {
                        flag = (*L) = new_node ;
                        flag->next = flag->previous = NULL ;
                }
                else 
                {
                        new_node->next = flag->next ;
                        flag->next = new_node ;
                        new_node->previous = flag ;
                        flag = new_node ;
                }
                i++ ; 
        }
        flag->next = (*L) ;
        (*L)->previous = flag ;
}
// 生成随机密匙 
static int * create_CipherKey ( int len )
{
        int i ;
        int *Key = (int *)malloc(sizeof(int) * len) ;
        for( i = 0 ; i < len ; i++)
        {
                Key[i] = rand()%100 ;
        }
        return Key ;
}

// 生成密文 
static Elemtype* create_Cipher (Linklist L, int len , int *key , char * passward)  
{
        int i ;
        Elemtype *new_cipher = (Elemtype*)malloc( sizeof(Elemtype)*len ) ;
        node *flag ;
        for ( i = 0 ; i < len ; i++)
        {
                flag = find_ch(L , passward[i]) ;
                create_one_cipher(flag,key[i],&new_cipher[i]) ;
        }
        return new_cipher ;
}

// 找到对应的字母,便于生成新字母 
static node* find_ch (Linklist l , Elemtype ch) 
{
        node *flag1 = l ;
        if ( ch > 'Z')
        {
                ch -= 32 ;
        }
        if ( ch <= 'M')
        {
                while (flag1->elem != ch)
                        flag1 = flag1->next ;
        }
        else
        {
                while (flag1->elem != ch)
                        flag1 = flag1->previous ;
        }
        return flag1 ;
}

// 生成新一位密文并用ch返回 
static void create_one_cipher (node*S , int n , Elemtype *ch)  // 当n的绝对值大于13时 向反方向移动 提高效率 
{
    node *flag2 = S ;
    n = n > 0 ? n : -n;
    n %= 26 ;
    while (n--)
        flag2 = flag2->next ;
    *ch = flag2->elem ;
#if 0
    node *flag2 = S ;
    n = n > 0 ? n : -n;
    n %= 26 ;
    if ( n >13)     // 这个if-else可以提高效率?
    {
        while (n--)
            flag2 = flag2->previous;
    }
    else
    {
        while (n--)
            flag2 = flag2->next ;
    }        
    *ch = flag2->elem ;
#endif
#if 0
        node *flag2 = S ;
        if ( n > 0)
        {
                n %= 26 ;
                if ( n >13)
                {
                        while (n--)
                                flag2 = flag2->previous;
                }
                else
                {
                        while (n--)
                                flag2 = flag2->next ;
                }        
        }
        else
        {
                n %= -26 ;
                if ( n >13)
                {
                        //while (n++)   // 确定这里是++ ?
                        while(n--)
                                flag2 = flag2->previous;
                }
                else
                {
                        //while (n++)   // 还有这里
                        while(n--)
                                flag2 = flag2->next ;
                }        
        }
        *ch = flag2->elem ;
#endif
}
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2020-4-1 16:59:02 | 显示全部楼层
本帖最后由 北有樵先生 于 2020-4-1 17:00 编辑


首先十分感谢你能看我的代码并指出问题,也让我注意到了很多问题,但输出还是有问题
比如:
输入:      wangbuliuxing
密匙:      0000000000001(假设是这个,方便讨论)
期望输出:wangbuliuxinh
实际输出:wangbuliuxinh794问日20394

后面粗体意思是所出现的乱码,通过malloc函数分配的空间所存储的字符,再用printf(“%s”)输出时会出现乱码,也就是我第二个输出那里,你问我想做什么,那里是我想与上面通过输出单个字符的结果作比较。根据我自己试下来,当输入字符串长度大于等于8时,通过%s输出会出现乱码,这个也是我一开始的问题
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2020-4-1 17:50:36 | 显示全部楼层
北有樵先生 发表于 2020-4-1 16:59
首先十分感谢你能看我的代码并指出问题,也让我注意到了很多问题,但输出还是有问题
比如:
输入:   ...

一组输入输出不具有代表性,我看不出规律
输入g,在密匙为1时输出h,密匙是2时输出什么?是3呢?-1呢?-2?等等
你说长度大于8会出问题,那小于等于8没问题?再举3个例子
小于8不会出问题的
等于8不会出问题的
还有大于8会出问题的

“假设是这个,方便讨论”
最好还是不要这样,这样不方便观察输入与输出的关系
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2020-4-1 17:52:50 | 显示全部楼层
为了更好的观察输入输出,你就随便编一个密匙吧,类似于随机
考虑上正数、负数和 0
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2020-4-1 18:00:45 | 显示全部楼层
就用这个密匙,在你看来输出什么才对?
 ./main
wangbuliuxing
39 93 42 16 54 77 50 38 61  0 42 15 13
J P D W D T J U D X Y C T
JPDWDTJUDXYCT

#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <string.h>


#define OK     1
#define ERROR  0
#define SIZE   16

typedef char Elemtype ;
typedef struct node 
{
        Elemtype elem ;
        struct node *next ;
        struct node *previous ;
}node , *Linklist ;

static char* input_plaintext (void) ;
static void create_BidCirlinklist ( Linklist *L) ;
static int * create_CipherKey ( int len ) ;
static node* find_ch (Linklist L , Elemtype ch)  ;
static void create_one_cipher (node*S , int n , Elemtype *ch) ;
static Elemtype* create_Cipher (Linklist L, int len , int *key , char * passward)  ;

int main (void)
{
        FILE *fp ;
        int len , *key , i;
        Elemtype *password , *new_password ;
        Linklist l = NULL;
        srand(time(NULL)) ;     // 放在这里更好
        if ( (fp = fopen("Encrypted.txt", "wb")) == NULL)
        {
                printf("打开文件失败\n") ;
                exit(EXIT_FAILURE) ;
        }
        password = input_plaintext() ;
        len = strlen(password) ;
        key = create_CipherKey(len) ;   
        fwrite(password, 1, len, fp) ;
        fwrite(key,sizeof(int),len,fp) ;
        fclose(fp) ; // 至此写入明文和密匙,以二进制的形式 
        create_BidCirlinklist(&l) ;
        new_password = create_Cipher(l,len,key,password) ;
        printf ("%s\n",password) ;    // 从这里开始便是验证输入和输出结果
        i = 0 ;
        while ( i < len )
        {
                printf("%2d ",key[i]) ;
                i++;
        }
        printf("\n") ;
        for( i = 0; i < len ; i++)
        {
                printf("%c ",new_password[i]) ;  // 单个字母输出并无问题
        }
        printf("\n") ;
        printf("%s\n",new_password) ;  // 问题出现在这个输出上      // 你期望这个printf输出什么内容?
        free(password);         // 少了这个吧?
        free(new_password);
        free(key);
        return 0;
}
// 输入明文 
static char* input_plaintext (void) 
{
#if 0
        int Len ;
        char *Str ,*str;
        str = (char*)malloc(SIZE) ;     // 永远都不需要乘一个sizeof(char)
        printf ("请输入明文(至多输入16位):") ;
        scanf ("%s",str) ;
        Len = strlen(str) ;
        Str = (char*)malloc(Len + 1) ;  // 这里不需要加1吗?
        strcpy(Str,str) ;
        free(str);          // 这里不需要free吗?
        return Str ;
#endif
        char *str = malloc(14);
        strcpy(str, "wangbuliuxing");
        return str;
}
// 建立解密环 
static void create_BidCirlinklist ( Linklist *L) // L是指针的指针 
{
        node *flag , *new_node ;
        int i = 0 ;
        while ( i< 26 )
        {
                new_node = (node *)malloc(sizeof(node )) ;
                new_node->elem = 'A'+i ;
                if ((*L) == NULL )
                {
                        flag = (*L) = new_node ;
                        flag->next = flag->previous = NULL ;
                }
                else 
                {
                        new_node->next = flag->next ;
                        flag->next = new_node ;
                        new_node->previous = flag ;
                        flag = new_node ;
                }
                i++ ; 
        }
        flag->next = (*L) ;
        (*L)->previous = flag ;
}
// 生成随机密匙 
static int * create_CipherKey ( int len )
{
        int i ;
        int *Key = (int *)malloc(sizeof(int) * len) ;
        for( i = 0 ; i < len ; i++)
        {
                Key[i] = rand()%100 ;
        }
        return Key ;
}

// 生成密文 
static Elemtype* create_Cipher (Linklist L, int len , int *key , char * passward)  
{
        int i ;
        Elemtype *new_cipher = (Elemtype*)malloc( sizeof(Elemtype)*len ) ;
        node *flag ;
        for ( i = 0 ; i < len ; i++)
        {
                flag = find_ch(L , passward[i]) ;
                create_one_cipher(flag,key[i],&new_cipher[i]) ;
        }
        return new_cipher ;
}

// 找到对应的字母,便于生成新字母 
static node* find_ch (Linklist l , Elemtype ch) 
{
        node *flag1 = l ;
        if ( ch > 'Z')
        {
                ch -= 32 ;
        }
        if ( ch <= 'M')
        {
                while (flag1->elem != ch)
                        flag1 = flag1->next ;
        }
        else
        {
                while (flag1->elem != ch)
                        flag1 = flag1->previous ;
        }
        return flag1 ;
}

// 生成新一位密文并用ch返回 
static void create_one_cipher (node*S , int n , Elemtype *ch)  // 当n的绝对值大于13时 向反方向移动 提高效率 
{
    node *flag2 = S ;
    n = n > 0 ? n : -n;
    n %= 26 ;
    while (n--)
        flag2 = flag2->next ;
    *ch = flag2->elem ;
#if 0
    node *flag2 = S ;
    n = n > 0 ? n : -n;
    n %= 26 ;
    if ( n >13)     // 这个if-else可以提高效率?
    {
        while (n--)
            flag2 = flag2->previous;
    }
    else
    {
        while (n--)
            flag2 = flag2->next ;
    }        
    *ch = flag2->elem ;
#endif
#if 0
        node *flag2 = S ;
        if ( n > 0)
        {
                n %= 26 ;
                if ( n >13)
                {
                        while (n--)
                                flag2 = flag2->previous;
                }
                else
                {
                        while (n--)
                                flag2 = flag2->next ;
                }        
        }
        else
        {
                n %= -26 ;
                if ( n >13)
                {
                        //while (n++)   // 确定这里是++ ?
                        while(n--)
                                flag2 = flag2->previous;
                }
                else
                {
                        //while (n++)   // 还有这里
                        while(n--)
                                flag2 = flag2->next ;
                }        
        }
        *ch = flag2->elem ;
#endif
}
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 1 反对 0

使用道具 举报

 楼主| 发表于 2020-4-1 18:50:19 | 显示全部楼层
本帖最后由 北有樵先生 于 2020-4-1 18:57 编辑
人造人 发表于 2020-4-1 18:00
就用这个密匙,在你看来输出什么才对?


我用的dev c++ 5.11,我复制你的代码然后运行,在正确结果后会出现乱码,会是编译器的问题嘛
因为我权限不够,没法给你发图片,要不先放着,然后我权限够了再说?

                               
登录/注册后可看大图

想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2020-4-1 19:29:48 | 显示全部楼层
北有樵先生 发表于 2020-4-1 18:50
我用的dev c++ 5.11,我复制你的代码然后运行,在正确结果后会出现乱码,会是编译器的问题嘛
因为我权 ...

图片显示不出来
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2020-4-2 10:36:06 | 显示全部楼层

那我先等到我有权限了吧
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2020-4-2 13:12:27 | 显示全部楼层
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2020-4-3 21:13:32 | 显示全部楼层
人造人 发表于 2020-4-2 13:12
https://fishc.com.cn/forum.php?mod=viewthread&tid=155962&highlight=%B7%A2%CD%BC%C6%AC

https://imgchr.com/i/GJvEaq
https://imgchr.com/i/GJvVI0

审核把回复删了,现在重发,第二个图就出现了乱码
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|手机版|Archiver|鱼C工作室 ( 粤ICP备18085999号-1 | 粤公网安备 44051102000585号)

GMT+8, 2024-11-23 01:57

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

快速回复 返回顶部 返回列表