2016-01-24 30 views
0

我试图将一些文本(逐个字符)转换为其二进制表示形式。出于某种原因,打印语句printf("Hold is %d or %c: ", hold, hold);正在改变我的函数的输出,我不知道如何解释它。任何帮助将不胜感激。测试文件只是一个文本文件,其中包含Hello, World!打印语句正在更改字符数组输出

有了它:

Hold is 72 or H: 01001000 
Hold is 101 or e: 01100101 
Hold is 108 or l: 01101100 
Hold is 108 or l: 01101100 
Hold is 111 or o: 01101111 
Hold is 44 or ,: 00101100 
Hold is 32 or : 00100000 
Hold is 87 or W: 01010111 
Hold is 111 or o: 01101111 
Hold is 114 or r: 01110010 
Hold is 108 or l: 01101100 
Hold is 100 or d: 01100100 
Hold is 33 or !: 00100001 

没有它:

1000 � 
0101 � 
1100 � 
1100 � 
1111 � 
1100 � 
0000 � 
0111 � 
1111 � 
0010 � 
1100 � 
0100 � 
0001 � 

代码

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

void decimal_to_binary(unsigned long num, FILE *out) {  
    int i = 255, a = 0; 
    char binarr[255]; 
    for (i = 0; i < 255; i++) { binarr[i] = '0'; } 
    if (num != 0) { 
     while (num != 0) { 
      if (num % 2 == 0) { 
       binarr[i] = '0'; 
       i--; 
      } else { 
       binarr[i] = '1'; 
       i--; 
      } 
      num /= 2; 
     } 
    } else { 
     fprintf(out, "00000000"); 
    } 
    fprintf(out, "%s ", binarr + strlen(binarr) - 8); 
    printf("%s\n", binarr + strlen(binarr) - 8); 
    memset(binarr, 0, sizeof(binarr));  
} 

int main(int argc, char *argv[]) { 
    int hold; 
    FILE *in = fopen(argv[1], "r"); 
    FILE *out = fopen(argv[2], "w+"); 

    while (!feof(in)) { 
     hold = fgetc(in); 
     if (hold > 0 && hold != 10){ 
      printf("Hold is %d or %c: ", hold, hold); 
      decimal_to_binary(hold, out); 
     } 
    } 
    fclose(in); 
    fclose(out); 
    return 0; 
} 
+0

你需要了解什么*字符串*是[标签:C],则不能使用'strlen的()''你的阵列binarr'上,因为它不是'null'终止。 –

+0

字符串是字符数组。所以当你声明一个char数组时,不会自动产生一个空终止符。那是你在说什么? – Chirality

+0

是的,[tag:c]中的字符串需要这个空终止符。 –

回答

1

decimal_to_binary功能是不正确的:

  • 您的索引超出binarr阵列的末尾。
  • 你不能null终止这个数组传递给printf

下面是一个简单和纠正版:

void decimal_to_binary(unsigned long num, FILE *out) { 
    int i = 256, a = 0; 
    char binarr[257]; 
    memset(binarr, '0', sizeof(binarr) - 1); 
    binarr[i] = '\0'; 
    while (num != 0) { 
     --i; 
     if (num % 2) { 
      binarr[i] = '1'; 
     } 
     num /= 2; 
    } 
    if (i > 256 - 8) // print at least 8 bits 
     i = 256 - 8; 
    fprintf(out, "%s ", binarr + i); 
    printf("%s\n", binarr + i); 
} 

你的功能main有问题太:

  • 您测试与feof(in)文件结束。这是不正确的,你应该检查hold是否为EOF
  • 硬编码'\n'的值为10是不好的做法。

这是一个正确的版本:

int main(int argc, char *argv[]) { 
    int hold; 
    FILE *in = fopen(argv[1], "r"); 
    FILE *out = fopen(argv[2], "w+"); 

    while ((hold = fgetc(in)) != EOF) { 
     if (hold != '\n') { 
      printf("Hold is %d or %c: ", hold, hold); 
      decimal_to_binary(hold, out); 
     } 
    } 
    fclose(in); 
    fclose(out); 
    return 0; 
} 
+0

感谢您的回复,但我能够在您发布时解决它。为什么要硬编码以避免换行符错误的做法?我以前没有听说过。 – Chirality

+0

@Revolt:对字符文字的数值进行硬编码是一种不好的做法。它使你的代码难以阅读,而且便携性也较差,尽管大多数系统现在都使用ASCII。例如,EBCDIC中'a'不是'97',对于大多数人来说''a''确实比'97'更具可读性。 – chqrlie

+0

从最佳编程实践的角度来看,这是有道理的。我习惯于为他们都使用ASCII的特定系统编写代码。 – Chirality

1

我非常大阵下降,确信以空字符来终止字符串,零数组,然后使用fprintf打印它。这解决了这个问题。

void decimal_to_binary(unsigned long num, FILE *out){ 

    int i = 7, a = 0; 
    char binarr[9]; 
    binarr[8]='\0'; 
    for (a=7; a>=0; a--){ binarr[a] = '0'; } 
    if (num != 0) { 
     while (num!=0){ 
      if (num%2 == 0){ 
       binarr[i] = '0'; 
       i--; 
      } 
      else { binarr[i] = '1'; i--; } 
      num /= 2; 
     } 
    } else { fprintf(out, "00000000"); } 
    fprintf(out, "%s ", binarr); 
    memset(binarr, 0, sizeof(binarr)); 
} 
+0

这对于8位字节来说已经足够了,但是你应该定义'num'来避免在以后的生活中用更大的数字调用时的溢出。 – chqrlie

+0

还有一半的代码在这个函数中仍然没用';-)' – chqrlie

+0

它一次只能处理一个字符,所以8位很好。它不用于除此之外的其他任何事情。如果将它重命名为“character_to_binary”,请您我可以这样做<3 – Chirality

1

由于几个原因,你的程序有未定义的行为。

  1. 您没有以null结尾的字符串。在这样的字符串上调用strlen会导致未定义的行为。
  2. 您正在修改binarr使用越界索引。这也是未定义行为的原因。

我有我的注释到您的函数decimal_to_binary,指出这些错误在哪里。

void decimal_to_binary(unsigned long num, FILE *out){ 

    int i = 255, a = 0; 
    char binarr[255]; 
    for (i=0; i<255; i++){ binarr[i] = '0'; } 

    // All the elements of binarr are set to '0'. 
    // It's not a null terminated string. 

    if (num != 0) { 
     while (num!=0){ 

      // The value of i is 255 when this loop is 
      // entered the first time. 
      // Setting the value of binarr[255] is cause for 
      // undefined behavior. 

      if (num%2 == 0){ 

       binarr[i] = '0'; 
       i--; 
      } 
      else { binarr[i] = '1'; i--; } 
      num /= 2; 
     } 
    } else { fprintf(out, "00000000"); } 
    fprintf(out, "%s ", binarr + strlen(binarr) - 8); 
    printf("%s\n", binarr + strlen(binarr) - 8); 
    memset(binarr, 0, sizeof(binarr)); 
} 

修复很简单。

  1. 终止带有空字符的字符串。

    for (i=0; i<255; i++){ binarr[i] = '0'; } 
    i--; 
    binarr[i] = '\0'; 
    
  2. while循环修改binarr时,请使用正确的索引。

    while (num!=0){ 
    
        // Decrement the index before you assign to the next element. 
        // When the loop is entered the first time, i = 254, which 
        // is used to null terminate binarray. 
        // The next '1' or '0' needs to be placed at i = 253. 
        i--; 
    
        if (num%2 == 0){ 
    
         binarr[i] = '0'; 
        } 
        else { 
         binarr[i] = '1'; 
        } 
        num /= 2; 
    }