【问题标题】:Why are only the first 2 outputs correct in my binary to decimal converter programm?为什么我的二进制到十进制转换器程序中只有前 2 个输出正确?
【发布时间】:2021-08-29 20:00:01
【问题描述】:

我必须编写一个转换器,从numbers[] 获取字符串并将它们输出为小数。

我循环遍历大小和索引,然后将当前索引与其位置的幂相加,然后将其全部加起来。比如:101 = 1^2 + 0^1 + 1^0

所以我目前对此感到困惑:

#include <stdio.h>

#include <math.h> // Kompilieren mit -lm : gcc -Wall -std=c11 dateiname.c -lm

int main() {
    char* numbers[] = {
        "01001001",
        "00101010",
        "010100111001",
        "011111110100101010010111",
        "0001010110011010101111101111010101110110",
        "01011100110000001101"};
    
    // Add here..

int strlen(char *str){
int len=0;
for(;str[len]!='\0';len++){}
return len;
}

int sum = 0;
int length = sizeof(numbers) / sizeof(numbers[0]);

for( int i = 0; i < length; i++ ){
    
     int size = strlen(numbers[i]);
     
    for (int j = 0; j < size; j++) {
     
        if(numbers[i][j] == '1'){ 
            sum += 1 * pow(2,j-1);
        }else{
            sum += 0 * pow(2,j-1);
        }
    }
       printf("%s to the base of 2 \nequals %d  to the base of 10 \n\n",numbers[i], sum); 
       sum = 0;
       
    }
            
    return 0;
}

前两个循环的输出是正确的,即 01001001 = 73 和 00101010 = 42。但是,一旦长度变大,我的输出就完全错误了;例如010100111001 = 1253 而不是 1337 和 011111110100101010010111 = 7645567 而不是 8342167。

【问题讨论】:

  • j从左边开始数,但如果使用2**jj必须从右边开始计算。您的前两个数字恰好是正确的,因为它们几乎是对称的。 -1 的偏移量以“修复”来掩盖错误。
  • 不要使用 pow 获得 2 的整数幂:使用移位。另请注意,第五个字符串的位数太多,无法转换为 32 位 int。 “二进制到十进制转换”也是不正确的,它将数字字符串转换为二进制。二进制转十进制由printf完成。

标签: c binary decimal


【解决方案1】:

您的代码存在许多问题。首先,正如 cmets 中所指出的,您正在从左到右处理二进制数字,而您应该从右到左处理。

其次,在另一个函数中声明一个函数(就像您为 strlen 所做的那样)不是标准 C(尽管某些编译器可能允许这样做)。如果你真的不能使用标准的strlen 函数(在&lt;string.h&gt; 中提供),那么将你的定义移到main 的外部(和之前)。

第三,您不应该使用pow 函数(它接受并返回double 值)进行整数运算。只需使用一个正在运行的 int 变量,并在每次运行内部 for 循环时将其乘以 2。

第四,您的"0001010110011010101111101111010101110110" 值会溢出大多数机器上的int 类型(假设是32 位),因此请在必要时尝试使用long long int(很可能是64 位)。

最后,无论x 是什么,添加0 * x 是没有意义的,因此您可以取消else 块。

这是一个工作版本(使用标准 strlen):

#include <stdio.h>
#include <string.h> // For "strlen" - we don't need math.h if we don't use "pow".

int main(void) // For strict compliance, you should add the "void" argument list
{
    char* numbers[] = {
        "01001001",
        "00101010",
        "010100111001",
        "011111110100101010010111",
        "0001010110011010101111101111010101110110",
        "01011100110000001101" };

    long long int sum = 0; // So we can use more than 32 bits!
    size_t length = sizeof(numbers) / sizeof(numbers[0]);
    for (size_t i = 0; i < length; i++) {
        int size = (int)strlen(numbers[i]); // strlen gives a "size_t" type
        long long int p = 1;
        for (int j = size-1; j >= 0; j--) { // Start at the END of the string and work backwards!
            if (numbers[i][j] == '1') {
                sum += p;
            }
            // No point in adding zero times anything!
            p *= 2; // Times by two each time through the loop
        }
        printf("%s to the base of 2 \nequals %lld  to the base of 10 \n\n", numbers[i], sum);
        sum = 0;

    }
    return 0;
}

【讨论】:

  • 真的,非常感谢!我对 c 真的很陌生,这是我的第四个任务。它真的有助于你如何打破“错误”。
  • @0___________:但您已经发布了一个答案,您使用strchr 的结果而不测试NULL。我怀疑这会使它“对任何数据都正确”。
  • @MOehm 对!更正。我不争论是否有人有建设性的意见。在另一句话之前 - 由调用者传递有效指针(与标准库函数相同)
  • @AdrianMole cast 不能防止溢出。
  • @AdrianMole 计算编译时间还是运行时间都没有关系。分配大于 INT_MAX 的值是实现定义的
【解决方案2】:
sizeof(); // it will give you the size of datatype (in bytes), not the length of a string.

你必须改用字符串函数。

length = strlen(numbers[0]);

【讨论】:

  • 但是sizeof这里只用来获取测试数组(6)的大小。处理字符串时,程序使用strlen
  • 目的是什么:int length = sizeof(numbers) / sizeof(numbers[0]);
  • @OwaisYosuf 获取数组长度是一个常用的习惯用法。
  • int length = sizeof(numbers); // 数组的长度。
  • 最后的评论不是真的。 sizeof会告诉你一个变量在内存中占用了多少字节,这和数组的长度是不一样的。
【解决方案3】:

你的函数很糟糕,很复杂并且使用pow。您不需要知道字符串的长度。

这可以更容易地完成:

unsigned long long bstrtoint(const char *str)
{
    unsigned long long result = 0;

    while(*str)
    {
        result *= 2;
        result += *str++ == '1';
    }
    return result;
}

或任何基数(小于位数)

//bad digits considered as zeroes
static const char digits[] = "0123456789ABCDEFGHIJKLMNOPQRSTUWXYZ";
unsigned long long strtoint(const char *str, unsigned base)
{
    unsigned long long result = 0;
    char *ppos;

    while(*str)
    {
        result *= base;
        result += (ppos = strchr(digits, toupper(*str++))) ? (ppos - digits < base) ? ppos - digits : 0 : 0;
    }
    return result;
}

例子:

    printf("%llu\n", bstrtoint("1111000011110000"));
    printf("%llu\n", strtoint("0001010110011010101111101111010101110110", 2));
    printf("%llu\n", strtoint("1dr45Xvy4", 36)); // base 36 number

https://godbolt.org/z/bsG5rfTsb

如果你想正确使用你的程序布局:

int main(void) // For strict compliance, you should add the "void" argument list
{
    char* numbers[] = {
        "01001001",
        "00101010",
        "010100111001",
        "011111110100101010010111",
        "0001010110011010101111101111010101110110",
        "01011100110000001101" };

    unsigned long long sum = 0;
    size_t length = sizeof(numbers) / sizeof(numbers[0]);

    for (size_t i = 0; i < length; i++) 
    {
        size_t size = strlen(numbers[i]); // strlen gives a "size_t" type
        sum = 0;
        for (size_t j = 0; j < size; j++) 
        { 
            sum *= 2;
            if (numbers[i][j] == '1') 
            {
                sum += 1;
            }
        }
        printf("%s to the base of 2 \nequals %llu  to the base of 10 \n\n", numbers[i], sum);
    }
    return 0;
}

但您不必将字符串集成两次 - 根本不需要 strlen

int main(void) // For strict compliance, you should add the "void" argument list
{
    char* numbers[] = {
        "01001001",
        "00101010",
        "010100111001",
        "011111110100101010010111",
        "0001010110011010101111101111010101110110",
        "01011100110000001101" };

    unsigned long long sum = 0;
    size_t length = sizeof(numbers) / sizeof(numbers[0]);

    for (size_t i = 0; i < length; i++) 
    {
        sum = 0;
        for (size_t j = 0; numbers[i][j] != 0; j++) 
        { 
            sum *= 2;
            if (numbers[i][j] == '1') 
            {
                sum += 1;
            }
        }
        printf("%s to the base of 2 \nequals %llu  to the base of 10 \n\n", numbers[i], sum);
    }
    return 0;
}

【讨论】:

    猜你喜欢
    • 2019-08-31
    • 2019-12-16
    • 2019-05-05
    • 1970-01-01
    • 1970-01-01
    • 2023-04-02
    • 2012-03-23
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多