Search code examples
cbinarycharxorparity

c How can i return a parity of char read from binary file


int parity (char msg[1400]) {

  int parity = 0;
  int i,j;
  char c;

  for(i=0;i<strlen(msg);i++) {
    for(j=0;j<8;j++) {
      c = msg[i];
      int bit = (c>>j)&1;
      parity ^= bit;
    }
  }

  return parity;
}

This function return a good result, for the next example:

char* msg = malloc(sizeof(char*)*1400);
strcpy(msg,"some string");
int parity = parity(msg);

For next example the result isn't good:

    char* msg = malloc(sizeof(char*)*1400);
    FILE *fp;
    fp = fopen(filename,"r");  //filename is a binary file
    while( !feof(fp) ){
      fread(msg,1399,sizeof(char),fp);
      int parity = parity(msg); //--> the result isn't well
      //.......
    }

I saw strlen(msg) is variable at each step (192,80,200...etc) when i read from file in while. I have to change the "parity" function for second example. Any suggestions?


Solution

  • There are other issues besides parity, but let us focus on that one.

    Find parity of all bytes, 1 byte at a time rather than 1 bit at a time. Next: the parity of the char. If char is 8 bits, the takes 3 iterations. (log2(CHAR_BIT))

    int parity(const char msg[], size_t len) {
      // XOR all bytes together
      unsigned par = 0;
      while (len > 0) {
        par ^= msg[--len];
      }
    
      // Find char parity 
      unsigned width = CHAR_BIT;
      do {
        par ^= par >> (width/2);  
        width -= width/2;
      } while (width > 1);
    
      // Only return Least Significant Bit
      return parity % 2;
    }
    
    #define Width 1400
    char msg[Width];
    fread(msg, Width, sizeof *msg, fp);
    int par = parity(msg, Width);
    

    If the length of the array is a multiple of sizeof(unsigned). This is a speed improvement by a factor of maybe 4 (sizeof unsigned/sizeof char).

    int parity_u(const unsigned msg[], size_t unsigned_len) {
      // XOR all unsigned together
      unsigned par = 0;
      while (len > 0) {
        par ^= msg[--len];
      }
    
      // Find unsigned parity 
      unsigned width = sizeof *msg * CHAR_BIT;
      do {
        par ^= par >> (width/2);  
        width -= width/2;
      } while (width > 1);
    
      // Only return Least Significant Bit
      return parity % 2;
    }
    
    #define Width (1400/sizeof(unsigned))
    unsigned msg[Width];
    fread(msg, Width, sizeof *msg, fp);
    int par = parity_u(msg, Width);