Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/sqlite/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C sprintf预先添加了额外的字符_C - Fatal编程技术网

C sprintf预先添加了额外的字符

C sprintf预先添加了额外的字符,c,C,我决定写一个二进制转换器,代码小而简单,它需要一个整数,并且应该输出一个带有结果二进制字符串的char* 这里的问题似乎是,最后一个sprintf似乎总是将最后一个前置字符加倍 例如,如果答案是1001001,它将打印11001001,或者如果它应该是-10,它将打印-10,后者特别奇怪,因为它甚至不在循环中 #include <stdlib.h> #include <stdio.h> #include <stdbool.h> void bin_string

我决定写一个二进制转换器,代码小而简单,它需要一个整数,并且应该输出一个带有结果二进制字符串的char*

这里的问题似乎是,最后一个sprintf似乎总是将最后一个前置字符加倍

例如,如果答案是1001001,它将打印11001001,或者如果它应该是-10,它将打印-10,后者特别奇怪,因为它甚至不在循环中

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

void bin_string( char** buffer ,int num ){

    bool neg = false;

    if ( num < 0 ){
        neg = true;
        num = ~num+1;
    }

    if( num == 0 )
        sprintf( *buffer, "%d", 0 );

    while( num > 0 ){

        int rem = num%2;

        sprintf( *buffer, "%d%s", rem, *buffer );

        printf("iteration: %s rem: %d\n", *buffer, rem );
        num = num/2;
    }

    if( neg )
        sprintf( *buffer, "-%s", *buffer );
}

int main( int argc, char** argv ){

    char* a = malloc( sizeof(char)*64 );
    bin_string( &a, 73 );

    printf("Result %s\n",a ); /* output is 11001001 but should be 1001001*/

    return 0;
}

我认为sprintf不够聪明,无法将缓冲区插入自身。您可能需要有两个缓冲区并交换它们。

我认为sprintf不够聪明,无法将缓冲区插入自身。您可能需要有两个缓冲区并交换它们。

C99及更高版本中的声明是:

    int sprintf(char *restrict s, const char *restrict format, ...);
您违反了该声明的限制部分。您正在使用,例如:

sprintf(*buffer, "-%s", *buffer);
这是试图在原地修改缓冲区,是未定义的行为。你很幸运,你得到了如此接近正常的结果——或者可能是不幸的。不能在sprintf调用的尾部参数中使用目标缓冲区。

在C99及更高版本中的声明是:

    int sprintf(char *restrict s, const char *restrict format, ...);
您违反了该声明的限制部分。您正在使用,例如:

sprintf(*buffer, "-%s", *buffer);

这是试图在原地修改缓冲区,是未定义的行为。你很幸运,你得到了如此接近正常的结果——或者可能是不幸的。您不能在sprintf调用的尾部参数中使用目标缓冲区。

答案是,当您将*缓冲区转换为自身时,您正在调用未定义的行为。你应该做的是:

void bit_string(char *buf, int n)
{
    int nbits = sizeof(n) * CHAR_BIT;
    int i;
    for (i = 0; i < nbits; i++) {
        buf[i] = '0' + ((n >> (nbits - i - 1)) & 1);
    }
    buf[nbits] = 0;
}

是的,我还为您考虑了效率、可读性和可移植性-不客气。

答案是,当您将*缓冲区冲刺到自身时,您正在调用未定义的行为。你应该做的是:

void bit_string(char *buf, int n)
{
    int nbits = sizeof(n) * CHAR_BIT;
    int i;
    for (i = 0; i < nbits; i++) {
        buf[i] = '0' + ((n >> (nbits - i - 1)) & 1);
    }
    buf[nbits] = 0;
}

是的,我还为您考虑了效率、可读性和可移植性-不客气。

如果char**buffer没有分配或更改指针,为什么要将其传递给bin_字符串。传递char*buffer并使用buffer而不是*buffer会更简单。然而,这与您提到的问题无关;比num=~num+1更容易理解;对大多数人来说,我不喜欢你把缓冲区打印到它自己。这实际上可能就是原因。尝试将缓冲区复制到其他位置,然后使用sprintf;num=neg-num:num;当num>0{…}/*时,如果neg*/。。。。字符数组可以从缓冲区末尾的终止null之前开始逐个字符地写入,然后返回到缓冲区的开头,而不需要任何sprintf。然后,bin_string可以返回指向缓冲区内结果字符串开头的char*。另一方面,这些都不是问题的一部分。如果没有分配或改变指针,为什么要将char**buffer传递给bin_string呢。传递char*buffer并使用buffer而不是*buffer会更简单。然而,这与您提到的问题无关;比num=~num+1更容易理解;对大多数人来说,我不喜欢你把缓冲区打印到它自己。这实际上可能就是原因。尝试将缓冲区复制到其他位置,然后使用sprintf;num=neg-num:num;当num>0{…}/*时,如果neg*/。。。。字符数组可以从缓冲区末尾的终止null之前开始逐个字符地写入,然后返回到缓冲区的开头,而不需要任何sprintf。然后,bin_string可以返回指向缓冲区内结果字符串开头的char*。另一方面,这些都不是问题的一部分。谢谢你的回答,结果证明你完全正确,将buf复制到临时变量解决了我的问题。谢谢你的回答,结果证明你完全正确,将buf复制到临时变量解决了我的问题。这个答案在算法上非常简单,它可能也更适合现实世界,因为我们应该期待一个固定的尺寸。我的问题更关注于为什么我的解决方案不起作用,而不是获得更好的算法,但这很好。其他地方给了我一个有点变化的答案,大概是1行6行,有点夸张。很高兴看到有些人仍在为简单而奋斗。@CoDragon谢谢:经验和懒散,仅此而已-这个答案在算法上很简单,它可能更符合现实世界,正如我们所期望的那样
固定大小。我的问题更关注于为什么我的解决方案不起作用,而不是获得更好的算法,但这很好。其他地方给了我一个有点变化的答案,大概是1行6行,有点夸张。很高兴看到有些人仍在为简单而奋斗。@CoDragon谢谢:经验和懒散,仅此而已-