如何将整数转换为字符串?

4

我有一个标准的C函数,其原型如下:

extern void lcd_puts(const char *s);

在我的另一个函数中,我有如下内容:
send_to_lcd() {
  uint8_t count = 10
  lcd_puts(count);
}

我的问题是如何将计数转换为字符串指针,以便能够发送到lcd_puts函数,在液晶屏上打印出计数值。谢谢。

2
你知道有哪些库可用吗?你有itoasprintf吗? - Owen
6个回答

6

在微控制器上,你必须至少有一点担心性能(这排除了sprintf),即使是除法在这种芯片上也是非常昂贵的操作。因此,您需要为微控制器优化代码。

我写了一些代码:http://ideone.com/SsEUW(需要进行一些更改以使用C风格字符串而不是C ++,但方法应该很清楚)


5
你不一定需要担心,这取决于是否具有时间紧迫性。在你确定需要使用之前,请优先选择标准库程序而不是自己编写代码。 - Oliver Charlesworth
3
@Oli:根据Owen的建议,使用itoa可能是可行的,但在微控制器上选择sprintf是一个可怕的选择。 - Ben Voigt
1
除非楼主在问题中加入“我需要它快速”的字眼,否则我仍然坚持我的答案,即sprintf是最佳选择;它是一个广泛支持的标准库函数(对于itoa不能这样说)。 - Oliver Charlesworth
这个链接已经失效了,你能否编辑答案并提供一个有效的链接或者直接在答案中引用解决方案? - ChrisW
@ChrisW:抱歉,我没有保留单独的副本。当时(10年前),我愚蠢地期望ideone会遵守他们自己的条款,即帖子将永久保存(我们谈论的是几千字节的数据,100年的存储成本只有一分钱的零头,因此这个承诺是完全可信的)。 - Ben Voigt
显示剩余6条评论

5

这取决于lcd_puts对其参数的处理方式。其中一种可能是:

void send_to_lcd(uint8_t count)
{
    char str[SOME_CONSERVATIVE_MAX_LENGTH];
    sprintf(str, "%d", count);  // You might also snprintf() if it's available
    lcd_puts(str);
}

但请记住,str 变量在 send_to_lcd() 函数返回时就会超出作用域。因此,如果 lcd_puts "记住" 其输入参数,这将导致未定义的行为。

如果是这种情况,您需要使用 malloc 函数来分配一个字符串缓冲区。但那样的话,您需要记得在某个时候使用 free() 函数释放内存,所有这些都会变得非常混乱。


或者,如果您没有malloc(),您可以使用一个static缓冲区(但我不认为lcd_puts会保存它的参数--它可能只是设置数字引脚)。 - Owen
@Owen:是的,可能不需要。我只是为最坏情况做准备,比如LCD实际上要到稍后才更新之类的。 - Oliver Charlesworth
由于计数本质上是一个小的无符号整数,因此在sprintf中使用%s格式很可能会访问违规。 - EvilTeach
如果您正在使用AVR,您可能需要改用sprintf_P(http://www.nongnu.org/avr-libc/user-manual/group__avr__stdio.html#ga6017094d9fd800fa02600d35399f2a2a)函数。 - Owen
1
对于微控制器项目,我避免使用malloc。 - Jeff

2

这似乎是一个合理的方法。

#include <stdint.h>
#include <stdio.h>

const char *u82s(uint8_t count)
{
    static char aString[4];

    aString[3] = '\0';
    aString[2] = (count % 10) + '0';  count /= 10;
    aString[1] = (count % 10) + '0';  count /= 10;
    aString[0] = (count % 10) + '0';

    return aString;
}

int main(void)
{
    uint8_t z = UINT8_MAX;

    do
    {
        z++;
        printf("%s\n", u8ts(z));
    }
    while (z != UINT8_MAX);

    return 0;
}

你写了一个不错的简短版本(虽然非常慢),然后还是调用了 printf - Ben Voigt
重命名函数以表明其意图。 - EvilTeach
1
@EvilTeach:抱歉我对 C 不是很熟,但我想知道 u82s() 函数到底在什么时候被调用? - w_hoami
我会把它放在答案中,这样其他人也可以评论。 - EvilTeach
重命名了一个名称,但是没有在两个地方都修改。呃。 - EvilTeach
显示剩余3条评论

1

sprintf函数可以格式化字符串

快速示例:

char buf[50];
uint8_t count = 10;
sprintf(buf,'%d',count);

lcd_puts(buf);

我刚开始接触这个uC的东西,所以目前性能对我来说不是问题。我尝试了这个,它可以直接使用。感谢其他人的评论和让我意识到性能问题。 - w_hoami

0

以您的API为基础。

/* One assumes this is a function that somehow displays a c string on the lcd. */
extern void lcd_puts(const char *s);


send_to_lcd() 
{
  uint8_t count = 10;     /* This is the variable to send to the screen         */ 

  lcd_puts(u82s(count));  /* This creates a string representation of count,     */
}                         /* which is then passed to the lcd_puts function      */
                          /* giving you the result you are after.  You question */
                          /* was how to make a c string out of a uint8.         */
                          /* this is a way to do it.                            */

它基本上与您选择的答案相同。将值计数转换为C字符串,以便lcd_puts可以使用它。


0

移除了静态内容并整理了代码:

void UART_SendInt( uint16_t num )
{
    #define MAX_LEN         6   // 32767 is 6 characters with NULL terminator
    #define BASE_10         10  // Print decimal format

    uint8_t index = MAX_LEN - 1;
    char str[ MAX_LEN ];

    str[ index ] = '\0';
    while( index-- )
    {
        str[ index ] = ( num % BASE_10 ) + '0'; 
        num /= BASE_10;

        if( 0 == num )
        {
            UART_SendStr( &str[ index ] );
            break;
        }
    }

    UART_SendStr( "\r\n" );

    return;
}

我无法打印超过32767的内容,但我认为这与我的编译器选项有关。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接