Jak przekonwertować int na string na Arduino?

90

Jak przekonwertować int nna ciąg, aby wysyłany przez numer seryjny był wysyłany jako ciąg?

Oto, co mam do tej pory:

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++;
}
user947659
źródło
3
@Pubby "printf () powiększa twój wykonywalny obiekt o ~ 1000 bajtów, więc możesz nie chcieć go używać, jeśli rozmiar jest problemem." plac
zabaw.arduino.cc/Main/Printf
Powiązane ( nie duplikat): Konwersja int lub ciągu znaków na tablicę znaków w Arduino
Peter Mortensen

Odpowiedzi:

131

Użyj w ten sposób:

String myString = String(n);

Więcej przykładów znajdziesz tutaj .

Cassio
źródło
4
Nie musisz już używać obiektu String, Serial.print lub println już je przekonwertuj!
Alexis Paques
Szukam sposobu, jak zamienić 97 na znak „a” lub 65 na znak „A”. Mam na myśli liczbę ASCII do znaku. Okazało się, że ten sposób nie działa.
Oki Erie Rinaldi
@OkiErieRinaldi: Możesz użyć - char bar = 97; to będzie działać.
Cassio,
25

użyj itoa()funkcji zawartej wstdlib.h

char buffer[7];         //the ASCII of the integer will be stored in this char array
itoa(-31596,buffer,10); //(integer, yourBuffer, base)
Cheesebaron
źródło
13

Wystarczy owinąć go wokół obiektu String w następujący sposób:

String numberString = String(n);

Możesz też:

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
PedroD
źródło
9

Jest to zoptymalizowane pod kątem szybkości rozwiązanie do konwersji int (16-bitowej liczby całkowitej ze znakiem) na łańcuch.

Ta implementacja unika używania dzielenia, ponieważ 8-bitowy AVR używany dla Arduino nie ma sprzętowej instrukcji DIV, kompilator tłumaczy podział na czasochłonne powtarzalne odejmowania. Dlatego najszybszym rozwiązaniem jest użycie gałęzi warunkowych do zbudowania łańcucha.

Stały bufor 7 bajtów przygotowany od początku w pamięci RAM, aby uniknąć dynamicznej alokacji. Ponieważ ma tylko 7 bajtów, koszt stałego użycia pamięci RAM jest uważany za minimalny. Aby pomóc kompilatorowi, dodajemy modyfikator rejestru do deklaracji zmiennej, aby przyspieszyć wykonywanie.

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() {}

Ten szkic jest kompilowany do 1082 bajtów kodu przy użyciu avr-gcc, który jest dołączony do Arduino w wersji 1.0.5 (rozmiar samej funkcji int2str wynosi 594 bajty). W porównaniu z rozwiązaniem wykorzystującym obiekt String, który został skompilowany do 2398 bajtów, ta implementacja może zmniejszyć rozmiar kodu o 1,2 Kb (zakładając, że nie potrzebujesz innej metody obiektowej String, a liczba jest ściśle związana z typem int ze znakiem).

Tę funkcję można dodatkowo zoptymalizować, pisząc ją w odpowiednim kodzie asemblera.

vcc2gnd
źródło
1
Alternatywnym podejściem do uniknięcia DIV jest pomnożenie przez (2 ^ N / 10), a następnie przesunięcie w prawo o N bitów. Więc dla N = 16, x / 10 ~ = (x * 6554) >> 16. W każdym razie wystarczająco blisko dla większości cyfr.
David R Tribble
1

Rozwiązanie jest o wiele za duże. Spróbuj tego prostego. Proszę podać bufor znaków 7+, bez sprawdzania.

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

Można go łatwo zmodyfikować, aby oddać koniec bufora, jeśli odrzucisz indeks „l” i bezpośrednio zwiększysz bufor.

Enkryptikon
źródło
0

Poniżej znajduje się własna skomponowana myitoa (), która ma znacznie mniejszy kod i rezerwuje STAŁĄ tablicę 7 (łącznie z zakończeniem 0) w char * mystring, co jest często pożądane. Jest oczywiste, że zamiast tego można zbudować kod za pomocą przesunięcia znaków, jeśli potrzebny jest łańcuch wyjściowy o zmiennej długości.

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;
}
David Svarrer
źródło
0

To po prostu działa dla mnie:

int bpm = 60;
char text[256];
sprintf(text, "Pulso: %d     ", bpm);
//now use text as string
Carlos Tornadijo
źródło