วิธีแปลง int เป็น string บน Arduino


94

ฉันจะแปลง int 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++;
}

3
@Pubby "printf () ทำให้อ็อบเจ็กต์ปฏิบัติการของคุณมีขนาดใหญ่ขึ้น ~ 1,000 ไบต์ดังนั้นคุณอาจไม่ต้องการใช้มันหากขนาดมีปัญหา" playground.arduino.cc/Main/Printf
Marcello Romani

ที่เกี่ยวข้อง ( ไม่ซ้ำกัน): การแปลง int หรือ String เป็นอาร์เรย์ถ่านบน Arduino
Peter Mortensen

คำตอบ:


135

ใช้แบบนี้:

String myString = String(n);

คุณสามารถค้นหาตัวอย่างเพิ่มเติมที่นี่


5
คุณไม่จำเป็นต้องใช้อ็อบเจกต์ String, Serial.print หรือ println แล้วทำการแปลง!
Alexis Paques

ฉันกำลังมองหาวิธีการแปลง 97 เป็นอักขระ 'a' หรือ 65 เป็นอักขระ 'A' ฉันหมายถึงหมายเลข ASCII เป็นอักขระ เจอแบบนี้ไม่ได้ผล
Oki Erie Rinaldi

@OkiErieRinaldi: คุณสามารถใช้ - char bar = 97; มันจะทำงาน.
Cassio



13

คุณต้องพันรอบวัตถุ 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

9

นี่คือโซลูชันที่ปรับให้เหมาะสมกับความเร็วสำหรับการแปลง int (จำนวนเต็ม 16 บิตที่ลงชื่อ) เป็นสตริง

การใช้งานนี้หลีกเลี่ยงการใช้การหารเนื่องจาก AVR 8 บิตที่ใช้สำหรับ Arduino ไม่มีคำสั่ง DIV ของฮาร์ดแวร์คอมไพลเลอร์จะแปลการหารเป็นการลบซ้ำที่ใช้เวลานาน ดังนั้นวิธีแก้ปัญหาที่เร็วที่สุดคือการใช้สาขาเงื่อนไขเพื่อสร้างสตริง

บัฟเฟอร์ 7 ไบต์คงที่ที่เตรียมไว้ตั้งแต่ต้นใน RAM เพื่อหลีกเลี่ยงการจัดสรรแบบไดนามิก เนื่องจากมีเพียง 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() {}

ร่างนี้รวบรวมเป็นโค้ด 1,082 ไบต์โดยใช้ avr-gcc ซึ่งมาพร้อมกับ Arduino v1.0.5 (ขนาดของฟังก์ชัน int2str คือ 594 ไบต์) เมื่อเทียบกับโซลูชันโดยใช้อ็อบเจกต์ String ซึ่งคอมไพล์เป็น 2,398 ไบต์การใช้งานนี้สามารถลดขนาดโค้ดของคุณได้ 1.2 Kb (สมมติว่าคุณไม่ต้องการเมธอดอ็อบเจ็กต์ของ String อื่น ๆ และหมายเลขของคุณเข้มงวดสำหรับประเภท int ที่ลงนาม)

ฟังก์ชันนี้สามารถปรับให้เหมาะสมเพิ่มเติมได้โดยเขียนลงในโค้ดแอสเซมเบลอร์ที่เหมาะสม


1
อีกทางเลือกหนึ่งในการหลีกเลี่ยง DIV คือการคูณด้วย (2 ^ N / 10) แล้วเลื่อนไปทางขวาด้วย N บิต ดังนั้นสำหรับ N = 16, x / 10 ~ = (x * 6554) >> 16 ปิดให้เพียงพอสำหรับตัวเลขส่วนใหญ่อย่างไรก็ตาม
David R Tribble

1

การแก้ปัญหาใหญ่เกินไป ลองวิธีง่ายๆนี้ โปรดระบุบัฟเฟอร์อักขระ 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' และเพิ่มบัฟเฟอร์โดยตรง



0

ด้านล่างนี้คือ myitoa () ที่ประกอบด้วยตัวเองซึ่งมีขนาดเล็กกว่ามากและขอสงวนอาร์เรย์คงที่เป็น 7 (รวมถึงการยกเลิก 0) ใน char * mystring ซึ่งมักเป็นที่ต้องการ เห็นได้ชัดว่าเราสามารถสร้างโค้ดด้วย character-shift แทนได้หากต้องการสตริงเอาต์พุตที่มีความยาวตัวแปร

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;
}

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.