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

128

如何将整数 n 转换为字符串,以便在串行传输时作为字符串发送?

以下是我目前的代码:

int ledPin=13;
int testerPin=8;
int n=1;

char buf[10];

void setup()
{
    pinMode(ledPin, OUTPUT);
    pinMode(testerPin, OUTPUT);
    Serial.begin(115200);
}

void loop()
{
    digitalWrite(ledPin, HIGH);
    sprintf(buf, "Hello!%d", n);
    Serial.println(buf);
    delay(500);
    digitalWrite(ledPin, LOW);
    delay(500);

    n++;
}

4
“如果程序大小是个问题,你可能不想使用printf()函数,因为它会让可执行文件变大约1000字节。” 来源:http://playground.arduino.cc/Main/Printf - Marcello Romani
1
相关(不是重复):*在Arduino上将int或String转换为char数组*。 - Peter Mortensen
10个回答

193

使用方法如下:

String myString = String(n);
你可以在这里找到更多示例。

7
不需要使用String对象,Serial.print或println已经将它们转换了! - Alexis Paques
我正在寻找将97转换为'a'字符或65转换为'A'字符的方法,我的意思是将ASCII数字转换为字符。我发现这种方法不起作用。 - Oki Erie Rinaldi
@OkiErieRinaldi:你可以使用 - char bar = 97; 这将有效。 - Cassio

34

使用 stdlib.h 中包含的 itoa() 函数。

char buffer[7];         //the ASCII of the integer will be stored in this char array
itoa(-31596,buffer,10); //(integer, yourBuffer, base)

26

17

你只需要像这样将它包裹在一个String对象中:

String numberString = String(n);

你也可以这样做:

String stringOne = "Hello String";                     // using a constant String
String stringOne =  String('a');                       // converting a constant char into a String
String stringTwo =  String("This is a string");        // converting a constant string into a String object
String stringOne =  String(stringTwo + " with more");  // concatenating two strings
String stringOne =  String(13);                        // using a constant integer
String stringOne =  String(analogRead(0), DEC);        // using an int and a base
String stringOne =  String(45, HEX);                   // using an int and a base (hexadecimal)
String stringOne =  String(255, BIN);                  // using an int and a base (binary)
String stringOne =  String(millis(), DEC);             // using a long and a base

11

这是将int(有符号16位整数)转换为字符串的速度优化解决方案。

此实现避免使用除法,因为用于Arduino的8位AVR没有硬件DIV指令,编译器将除法翻译为耗时的重复减法。因此,最快的解决方案是使用条件分支来构建字符串。

从一开始就在RAM中准备好固定的7字节缓冲区以避免动态分配。由于它只有7个字节,固定RAM使用成本被认为是最低的。为了帮助编译器,我们在变量声明中添加寄存器修饰符以加快执行速度。

char _int2str[7];
char* int2str( register int i ) {
  register unsigned char L = 1;
  register char c;
  register boolean m = false;
  register char b;  // lower-byte of i
  // negative
  if ( i < 0 ) {
    _int2str[ 0 ] = '-';
    i = -i;
  }
  else L = 0;
  // ten-thousands
  if( i > 9999 ) {
    c = i < 20000 ? 1
      : i < 30000 ? 2
      : 3;
    _int2str[ L++ ] = c + 48;
    i -= c * 10000;
    m = true;
  }
  // thousands
  if( i > 999 ) {
    c = i < 5000
      ? ( i < 3000
          ? ( i < 2000 ? 1 : 2 )
          :   i < 4000 ? 3 : 4
        )
      : i < 8000
        ? ( i < 6000
            ? 5
            : i < 7000 ? 6 : 7
          )
        : i < 9000 ? 8 : 9;
    _int2str[ L++ ] = c + 48;
    i -= c * 1000;
    m = true;
  }
  else if( m ) _int2str[ L++ ] = '0';
  // hundreds
  if( i > 99 ) {
    c = i < 500
      ? ( i < 300
          ? ( i < 200 ? 1 : 2 )
          :   i < 400 ? 3 : 4
        )
      : i < 800
        ? ( i < 600
            ? 5
            : i < 700 ? 6 : 7
          )
        : i < 900 ? 8 : 9;
    _int2str[ L++ ] = c + 48;
    i -= c * 100;
    m = true;
  }
  else if( m ) _int2str[ L++ ] = '0';
  // decades (check on lower byte to optimize code)
  b = char( i );
  if( b > 9 ) {
    c = b < 50
      ? ( b < 30
          ? ( b < 20 ? 1 : 2 )
          :   b < 40 ? 3 : 4
        )
      : b < 80
        ? ( i < 60
            ? 5
            : i < 70 ? 6 : 7
          )
        : i < 90 ? 8 : 9;
    _int2str[ L++ ] = c + 48;
    b -= c * 10;
    m = true;
  }
  else if( m ) _int2str[ L++ ] = '0';
  // last digit
  _int2str[ L++ ] = b + 48;
  // null terminator
  _int2str[ L ] = 0;  
  return _int2str;
}

// Usage example:
int i = -12345;
char* s;
void setup() {
  s = int2str( i );
}
void loop() {}

使用与Arduino v1.0.5捆绑的avr-gcc编译,此草图编译为1,082字节的代码(int2str函数本身的大小为594字节)。与编译为2,398字节的String对象解决方案相比,此实现可以将您的代码大小减小1.2 Kb(假设您不需要其他String对象方法,并且您的数字严格限于有符号int类型)。

通过编写适当的汇编代码,可以进一步优化此函数。


2
避免使用除法的另一种方法是乘以(2^N/10),然后向右移动N位。因此,对于N=16,x/10 ~= (x*6554)>>16。对于大多数数字来说,这已经足够接近了。 - David R Tribble
1
这是...艺术。 - ljleb

2
解决方案太复杂了。试试这个简单的。请提供一个长度为7+的缓冲区,不进行任何检查。
char *i2str(int i, char *buf){
  byte l=0;
  if(i<0) buf[l++]='-';
  boolean leadingZ=true;
  for(int div=10000, mod=0; div>0; div/=10){
    mod=i%div;
    i/=div;
    if(!leadingZ || i!=0){
       leadingZ=false;
       buf[l++]=i+'0';
    }
    i=mod;
  }
  buf[l]=0;
  return buf;
}

如果您丢弃索引“l”并直接增加缓冲区,则可以轻松修改以返回缓冲区的末尾。


2
在Arduino中,使用String关键字创建String类的对象,该类有多个版本的构造函数。如果在实例化时传递一个整数作为参数,则它包含数字的ASCII表示。
int num = 12;
String intString = String(num);
// The value of intString should be "12"

请查看Arduino的String参考文档

1
这对我来说很简单:

这只是对我有效:

int bpm = 60;
char text[256];
sprintf(text, "Pulso: %d     ", bpm);
//now use text as string

0
下面是一个自编的myitoa()函数,它的代码更小,并且在char *mystring中保留了一个固定长度为7(包括终止符0)的数组,这通常是可取的。显然,如果需要可变长度的输出字符串,可以使用字符移位来构建代码。
void myitoa(int number, char *mystring) {
  boolean negative = number>0;

  mystring[0] = number<0? '-' : '+';
  number = number<0 ? -number : number;
  for (int n=5; n>0; n--) {
     mystring[n] = ' ';
     if(number > 0) mystring[n] = number%10 + 48;
     number /= 10;
  }  
  mystring[6]=0;
}

0

这不会将整数转换为字符串。 - Duloren

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