C中的奇偶校验位

问题描述 投票:1回答:1

所以我想用C语言制作一个脚本来显示奇偶校验位。基本上,我需要输入一个转换后的字符的二进制值,然后作为输出,我应该有输入+1或0(10是奇偶校验位,0是偶数,1是不偶数)。我就是不能让它工作。我要么得到相同的输入,要么得到一些疯狂的错误。谁能帮我一下?谢谢

这是我的剧本

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

int main (){    
   char msg_bit_input[128];    
   char msg_bit_output[128];    
   char caruno='1';    
   int i;    
   int one; 
   printf("Insert the byte: "); 
   scanf("%s", msg_bit_input);
   strcpy (msg_bit_output, msg_bit_input); 
   for(i=0;i<8;i++){        
       if(msg_bit_input[i]==caruno){            
           one--;
       }
   }

   if(one%2==0){        
       //byte is even        
       strcat (msg_bit_output, msg_bit_input);    
   } else if(one%2==1){
       //byte is uneven      
       strcat (msg_bit_output, msg_bit_input);
   }
   printf("The result is: %s", msg_bit_output);    
   return (EXIT_SUCCESS); 
}
c
1个回答
0
投票

让我们来解决这个问题

让它工作所需的最小改动是。

  1. 你忘了初始化 one 计数器。
  2. 你应该向上数,而不是向下数(即 one++ 不应该是 one--).
  3. 你并没有在输出中加入奇偶校验位,只是重复了输入。
  4. 你需要添加一个终止的换行符 (\n)中。printf 的输出。

经过修复,它是。

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

int main (){    
   char msg_bit_input[128];    
   char msg_bit_output[128];    
   char caruno='1';    
   int i;    
   int one = 0;
   printf("Insert the byte: "); 
   scanf("%s", msg_bit_input);
   strcpy (msg_bit_output, msg_bit_input); 
   for(i=0;i<8;i++){        
       if(msg_bit_input[i]==caruno){            
           one++;
       }
   }
   if(one%2==0){        
       //byte is even        
       strcat (msg_bit_output, "0");    
   } else if(one%2==1){
       //byte is uneven      
       strcat (msg_bit_output, "1");
   }
   printf("The result is: %s", msg_bit_output);    
   return (EXIT_SUCCESS); 
}

在网上试一试。https:/onlinegdb.comBk30ef1s8。.

让我们简化和改进

但这个程序是不必要的复杂。首先,不需要使用单独的输出和输入:你是按原样取输入,然后加一个奇偶位。我们简化为。

//...
int main (){    
   char bits[128];    
   char caruno='1';    
   int i;    
   int one = 0;
   printf("Insert the byte: "); 
   scanf("%s", bits);
   for(i=0;i<8;i++){        
       if(bits[i]==caruno){            
           one++;
       }
   }
   if(one%2==0){        
       //byte is even        
       strcat (bits, "0");    
   } else if(one%2==1){
       //byte is uneven      
       strcat (bits, "1");
   }
   printf("The result is: %s", bits);    
   return (EXIT_SUCCESS); 
}

试试吧: https: /onlinegdb.comS1UwWMksU

然后,我们注意到,偶数均等性的检验只能有两种结果--它们是替代物,所以如果结果不是偶数,我们就知道它一定是奇数,所以不需要检查。

//...
   if (one%2==0) 
       //byte is even        
       strcat (bits, "0");    
   else
       //byte is odd      
       strcat (bits, "1");
//...

试试吧: https:/onlinegdb.comSkrc-Gki8

的使用。caruno 变量是不必要的:它几乎不是一个 "神奇的常数",我们很清楚它的含义。

int main (){    
   char bits[128];  
   int i;    
   int one = 0;
   printf("Insert the byte: "); 
   scanf("%s", bits);
   for(i=0;i<8;i++){        
       if(bits[i]=='1'){            
           one++;
       }
   }
//...

试试吧。https: /onlinegdb.comByAA-MkjU

然后我们注意到 scanf 无法知道它接收输入的缓冲区有多长。如果用户提供较长的输入。scanf 会很高兴地溢出那个缓冲区,并在堆栈中乱写乱画。我们希望程序在面对不好的输入时能够健壮地运行--这只是对 scanf 格式参数,提供宽度。有一个 注意事项: scanf 将始终在输入中附加零结束符,所以我们需要提供缓冲区大小减1,为零留出空间。

   scanf("%127s", bits);

试试吧 https:/onlinegdb.comSJJrqMyj8

而现在我们也注意到,我们并没有真正测试输入字符串中是否有空间来追加输出。我们可以不追加输出,而是单独打印。

int main (){    
    char bits[128];  
    int i;    
    int one = 0;
    char result;
    printf("Insert the byte: "); 
    scanf("%127s", bits);
    for(i=0;i<8;i++){        
        if(bits[i]=='1'){            
            one++;
        }
    }
    if (one%2==0) 
        result = '0'; //byte is even       
    else
        result = '1'; //byte is odd

   printf("The result is: %s%c", bits, result);    
   return (EXIT_SUCCESS); 
}

试试吧 https: /onlinegdb.comBk0w9M1iU

可以说,将输入限制在8位似乎没有必要--你从来没有检查过它。如果有必要,我们可以明确地检查它。

假设我们不关心输入是否正好是8位:我们将返回输入的任何位,并附加一个奇偶校验位。我们通过循环不超过 i,但使用指向字符串缓冲区的指针,并将该字符与 '\0' - 这就是我们应该中断循环的空结束符。注意,我们应该在这里断开循环。 迭代器(即 bufp 指针)可以指向 const char,因为我们不打算让循环修改字符。

这时我们也可以检测到包含除 01. 我们增加 error 函数来打印错误输出。我们也可以摆脱 string.h 头包含,因为我们没有使用该头的任何字符串操作。

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

int error(const char *message)
{
    fprintf(stderr, "\nError: %s.\n", message);
    return EXIT_FAILURE;
}

int main (){    
    const char bits[128];  
    char *bitp;  
    int one = 0;
    char result;

    printf("Enter one or more binary bits: "); 
    scanf("%127s", bits);

    for (bitp = bits; *bitp != '\0'; ++bitp)
    {
        if (*bitp == '1')
            ++one;
        else if (*bitp != '0')
            return error("invalid input");
    }

    if (one%2==0) 
        result = '0'; //byte is even       
    else
        result = '1'; //byte is odd

   printf("The result is: %s%c", bits, result);    
   return (EXIT_SUCCESS); 
}

试试吧 https:/onlinegdb.comB1Ux-XyiI

现在我们应该测试是否处理了另一个输入错误条件--输入流是否过早结束。这可以在windows上通过按Ctrl-Z然后按Enter键触发(这将输入流关闭到控制台进程),或者在Unix上按Ctrl-D触发。

在onlinegdb中,你可以通过在控制台窗口中按^D触发这个错误条件,在你按完 Run 节目。

A screenshot showing the failure due to premature end of input

最后...

最后,利用更多的现代C语言特性将是一个好主意:你应该在接近使用点的地方声明和初始化变量,这样它们更容易被跟踪。在 result 变量可以使用三元运算符表达式进行初始化,表达式的形式为:: condition ? value_if_true : value_if_false. 整个表达式变成了 value_if_true 如果条件评价为真,或 value_if_false 如果条件评估为false。这有助于在声明时进行初始化。

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

int error(const char *message)
{
    fprintf(stderr, "\nError: %s.\n", message);
    return EXIT_FAILURE;
}

int main()
{
    char bits[128];  
    printf("Enter one or more binary bits: "); 
    scanf("%127s", bits);

    int ones = 0;
    for (const char *bitp = bits; *bitp != '\0'; ++bitp)
    {
        if (*bitp == '1')
            ++ones;
        else if (*bitp != '0')
            return error("invalid input");
    }

    char result = (ones%2==0) ? '0' /*even*/ : '1' /*odd*/;

    printf("The result is: %s%c", bits, result);    
    return EXIT_SUCCESS; 
}

试试吧 https:/onlinegdb.comSJ1DbmJi8

最后,最后:)

有一点我不是特别喜欢,那就是容易出现bug的重复的 buf 在变量声明和 scanf的格式字符串。

让我们试试来自 本回答并将输入的字符串因子化成一个单独的函数。

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

int error(const char *message)
{
    fprintf(stderr, "\nError: %s.\n", message);
    return EXIT_FAILURE;
}

void scan_string(char *buffer, unsigned length) {
    char format[12]; // Support max int value for the format %<num>s
    snprintf(format, sizeof(format), "%%%ds", length - 1); // Generate format
    scanf(format, buffer);
}

int main()
{
    char bits[128];  
    printf("Enter one or more binary bits: "); 
    scan_string(bits, sizeof(bits));

    int ones = 0;
    for (const char *bitp = bits; *bitp != '\0'; ++bitp)
    {
        if (*bitp == '1')
            ++ones;
        else if (*bitp != '0')
            return error("invalid input");
    }

    char result = (ones%2==0) ? '0' /*even*/ : '1' /*odd*/;

    printf("The result is: %s%c", bits, result);    
    return EXIT_SUCCESS; 
}

试试吧: https:/onlinegdb.comHyEsbQJoI。

© www.soinside.com 2019 - 2024. All rights reserved.