Go Down

Topic: Wie ermittle ich die die zweite Stelle einer Achtstelligen Zahl? (Read 906 times) previous topic - next topic

heikoch

Möchte mit dem MAX7219 eine achtstellige 7-Segmentanzeige betreiben.
Funktioniert auch schon.

Ziel soll es sein einen rückwärts zählenden Counter darzustellen der die fehlenden Stellen auf dem Display mit Nullen auffüllt.

Für meinen Scetch benötige ich folgende Funktionalitäten...
Wie ermittle ich wieviel Stellen eine Zahl hat?
Aus PHP kenne ich "strlen(int)" aber int ist ja kein String.
Wie kann ich eine Zahl in einen String umwandeln?

Wie ermittle ich die zweite Stelle einer Achtstelligen Zahl?
Wenn int zum Beispiel "93784501" ist, wie bekomme ich "3" raus wenn ich wissen will wie die zweite Stelle ist?

Vielen Dank für jede Anregung
Heiko


uwefed

mit %10
das ergibt den Rest einer Division durch 10.
Grüße Uwe

Code: [Select]
byte array[8];  Array mit einzelnen Stellen der Zahl
long Zahl = 12345678; //auszugebende Zahl.

void setup)
{
}

void loop()
{
for(byte i=0; i<8;i++)
{
array[i]=wert%10;
wert/=10;
}
}

sth77

Wird so nicht ganz klappen... :D Zahl und wert sind unterschiedliche Variablen. ;)
Mein Arduino-Blog: http://www.sth77.de/ - letzte Einträge: Teensy 3.0 - Teensyduino unter Window 7 - Teensyduino unter Windows 8

uwefed

ups.
Also nochmal richtig:

Code: [Select]
byte array[8];  Array mit einzelnen Stellen der Zahl
long Zahl = 12345678; //auszugebende Zahl.

...
void loop()
{
for(byte i=0; i<8;i++)
{
array[i]=Zahl%10;
Zahl/=10;
}
}

mwyraz

Die Zahl kannst Du direkt mit dem Konstruktor von String in einen String umwandeln, siehe Doku von String:
http://arduino.cc/en/Reference/StringConstructor

String thisString = String(12345678);

Anschließend einfach auf length() oder charAt() zugreifen.

heikoch


Die Zahl kannst Du direkt mit dem Konstruktor von String in einen String umwandeln, siehe Doku von String:
http://arduino.cc/en/Reference/StringConstructor

String thisString = String(12345678);

Anschließend einfach auf length() oder charAt() zugreifen.


Demzufolge müsste es ja hiermit funktionieren

Code: [Select]

void setup() {
  Serial.begin(9600);
}
void loop() {
  for(int i=0;i<10000000;i++) {
    Serial.println();
    int len = strlen(String(i));
    if (len==1) {
      Serial.print(0000000);
    }
    if (len==2) {
      Serial.print(000000);
    }
    if (len==3) {
      Serial.print(00000);
    }
    if (len==4) {
      Serial.print(0000);
    }
    if (len==5) {
      Serial.print(000);
    }
    if (len==6) {
      Serial.print(00);
    }
    if (len==7) {
      Serial.print(0);
    }
    Serial.print(i);
    delay(100);
  }
}


bekomme aber folgenden Fehler

Code: [Select]
int2string.ino: In function 'void loop()':
int2string:8: error: cannot convert 'String' to 'const char*' for argument '1' to 'size_t strlen(const char*)'


Was ist nicht richtig?

uwefed

Code: [Select]
for(int i=0;i<10000000;i++) {
Zuerst mal kannst Du 10 000 000 nicht in einen Int-Variable speichern da diese max ca 32000 darstellen kann. Dann verstehe ich auch nicht, wieso Du in den nächsten 10 Jahren in der For-Schleife bleiben willst und nullen ausgeben willst. Ein Zyklus braucht zwischen ca 10 (bei kleinen Werten von i)  und 1 Millisekunden.

Eine 100% Lösung kann ich Dir nicht anbieten da ich mich wenig mit String Konstruktor arbeite, aber Du mußt das über den Konstruktor machen:

Code: [Select]
String thisString = String(i);
int len = strlen(thisString);


Grüße Uwe


jurs


Was ist nicht richtig?


Richtig ist es, auf jegliche String-Objekte in Arduino-Programmen zu verzichten, da String-Objekte einerseits latent zur Fragmentierung des RAM-Speichers neigen bis das Programm irregulär arbeitet, und andererseits String-Objekte in Arduino fehlerhaft implementiert sind und Speicherlecks verursachen können.

Mein Codevorschlag beruht auf einem byte-Array (digits_array[8]), in das die Stellen gepackt werden, so dass man nacheinander darauf zugreifen kann mit digits_array[0] ... digits_array[7].

Anbei Funktion mit Zähler-Demo für den seriellen Monitor.
Ein achtstelliger Zähler muß natürlich "long" definiert sein, damit er auch große Zahlen aufnehmen kann.

Code: [Select]

byte digits_array[8];
void zahl2digits_array(long zahl)
{ // Zahl in byte array mit acht Stellen umwandeln
  for (int i=0;i<8;i++)
  {
    digits_array[7-i]=zahl%10;
    zahl=zahl/10;
  } 
}

void setup() {
  // put your setup code here, to run once:
  Serial.begin(9600);
  for (long counter=1234;counter>=0;counter--)
  {
     zahl2digits_array(counter);
     for (int i=0;i<8;i++)
     {
       Serial.print(digits_array[i]);
       if (i<7) Serial.print("-");
     }
     Serial.println(); 
  }
}


void loop() {
  // put your main code here, to run repeatedly:
}


Falls die Digitalstellen nicht als Byte sondern als ASCII-Zeichen benötigt wird, läßt sich das natürlich schnell abändern.

Und falls es sich um einen extrem schnelllaufenden Zähler handelt, in einem zeitkritischen Programm, bei dem eigentlich nicht der Zählerstand an sich interessiert, sondern ob der Zähler noch läuft und größer Null ist oder bereits Null erreicht hat, bietet es sich an, die Zählerlogik insgesamt in das Byte-Array zu verlegen, um den Zeitverbrauch durch die ganzen Divisions- und Modulo-Rechenoperationen zu vermeiden. D.h. dann würde man sich eine Funktion a la
void countBack_digits_array()
deklarieren und direkt in dem Array blitzschnell rückwärtszählen, statt eine andere Variable als Zähler zu verwenden und jedesmal die neuen 8 Dezimalstellen einzeln auszuklabüstern, wenn sich der Zählerstand um  -1 geändert hat. Ob sich der Aufwand lohnt, hängt aber davon ab, wie zeitkritisch das Zählen ist.

Go Up