北有樵先生 发表于 2020-3-31 11:45:40

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

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

问题是输出期望的结果后,有有一些不符合期望的字符跟在其后面。具体描述在代码最后。代码如下:

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


# define OK         1
# define ERROR0
# 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++;
        }
        printf("\n") ;
        for( i = 0; i < len ; i++)
        {
                printf("%c ",new_password) ;// 单个字母输出并无问题
        }
        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 = 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) ;
                create_one_cipher(flag,key,&new_cipher) ;
        }
        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个字符往后都会出现这些,而且越多,我已经调试完了,可以正常运行,单个字母进行输出,也可以得到结果

因为是新人所以不能上传图片,但程序可运行,可以尝试输入,谢谢

人造人 发表于 2020-3-31 12:09:07

给出输入样例和输出结果,如果有必要,再指出哪里和你期望的结果不符
这样会对我调试程序很有帮助
还有代码写的也挺长了,该学一学调试程序的方法了

北有樵先生 发表于 2020-3-31 14:16:33

本帖最后由 北有樵先生 于 2020-3-31 15:56 编辑

人造人 发表于 2020-3-31 12:09
给出输入样例和输出结果,如果有必要,再指出哪里和你期望的结果不符
这样会对我调试程序很有帮助
还有代 ...

你的前半句很有道理,是我对问题的描述不够,我已经改了,谢谢。不过我想说,一上来就质疑人啥都没干,这种行为很愚蠢

人造人 发表于 2020-3-31 16:57:08

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

你修改后的结果也一样,对调试程序没有任何帮助
我期望的是像下面这样的
输入:abcd1234
输出:234abcd1+
我期望的输出是:1234abcd

人造人 发表于 2020-3-31 18:40:53

发现了好多问题

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


# define OK         1
# define ERROR0
# 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++;
      }
      printf("\n") ;
      for( i = 0; i < len ; i++)
      {
                printf("%c ",new_password) ;// 单个字母输出并无问题
      }
      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 = 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) ;
                create_one_cipher(flag,key,&new_cipher) ;
      }
      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
}

北有樵先生 发表于 2020-4-1 16:59:02

本帖最后由 北有樵先生 于 2020-4-1 17:00 编辑

人造人 发表于 2020-3-31 18:40
发现了好多问题

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

后面粗体意思是所出现的乱码,通过malloc函数分配的空间所存储的字符,再用printf(“%s”)输出时会出现乱码,也就是我第二个输出那里,你问我想做什么,那里是我想与上面通过输出单个字符的结果作比较。根据我自己试下来,当输入字符串长度大于等于8时,通过%s输出会出现乱码,这个也是我一开始的问题

人造人 发表于 2020-4-1 17:50:36

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

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

“假设是这个,方便讨论”
最好还是不要这样,这样不方便观察输入与输出的关系

人造人 发表于 2020-4-1 17:52:50

为了更好的观察输入输出,你就随便编一个密匙吧,类似于随机
考虑上正数、负数和 0

人造人 发表于 2020-4-1 18:00:45

就用这个密匙,在你看来输出什么才对?

./main
wangbuliuxing
39 93 42 16 54 77 50 38 610 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 ERROR0
#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++;
      }
      printf("\n") ;
      for( i = 0; i < len ; i++)
      {
                printf("%c ",new_password) ;// 单个字母输出并无问题
      }
      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 = 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) ;
                create_one_cipher(flag,key,&new_cipher) ;
      }
      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
}

北有樵先生 发表于 2020-4-1 18:50:19

本帖最后由 北有樵先生 于 2020-4-1 18:57 编辑

人造人 发表于 2020-4-1 18:00
就用这个密匙,在你看来输出什么才对?

我用的dev c++ 5.11,我复制你的代码然后运行,在正确结果后会出现乱码,会是编译器的问题嘛
因为我权限不够,没法给你发图片,要不先放着,然后我权限够了再说?{:10_266:}
https://user.qzone.qq.com/1924366928/infocenter

人造人 发表于 2020-4-1 19:29:48

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

图片显示不出来

北有樵先生 发表于 2020-4-2 10:36:06

人造人 发表于 2020-4-1 19:29
图片显示不出来

那我先等到我有权限了吧{:10_284:}

人造人 发表于 2020-4-2 13:12:27

北有樵先生 发表于 2020-4-2 10:36
那我先等到我有权限了吧

https://fishc.com.cn/forum.php?mod=viewthread&tid=155962&highlight=%B7%A2%CD%BC%C6%AC

北有樵先生 发表于 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

审核把回复删了,现在重发,第二个图就出现了乱码
页: [1]
查看完整版本: 关于vigenger加密问题 (C语言)