Forum: Mikrocontroller und Digitale Elektronik ASCII Verarbeitung optimieren


von µC-noob (Gast)


Lesenswert?

Hallo, ich habe folgendes Programm geschrieben, womit ich Kommandos 
durch def. Zeichenabfolgen z.B. über das Hyperterminal an meinen µC 
sende, und dieser dann irgend etwas ausführt.
Ascii ist Vorgabe sonst hätt ich das mit einfachen dezimalzahlen 
gemacht.

Ich verwende einen ATmega 128 mit 16MHz

Der Code unten wird jede ms aufgerufen.

Ich finde aber der Code ist sehr unübersichtlich und aufwendig, vor 
allem, wenn ich noch weitere bedingungen hinzufüge (unten wird nur eine 
Bedingung bearbeitet).

Hat jemand einen Vorschlag wie ich das verbessern/ Optimieren kann.
1
void triggerCommand (void)
2
{
3
  unsigned char getChar = 0;
4
5
  static unsigned char savedChar[10];
6
  static unsigned char chosenPin;
7
8
  static unsigned char ENTER_Push[5];
9
10
  getChar = uart0_getc();
11
12
  LCDLine1[0] = savedChar[0];
13
  LCDLine1[1] = savedChar[1];
14
  LCDLine1[2] = savedChar[2];
15
  
16
  if( getChar == 'T' )  //Set Trigger
17
    savedChar[0] = 'T';
18
  
19
20
  if( savedChar[0] == 'T' )    //If T (Trigger) recieved
21
  {
22
    if( getChar == 'R' )  //If T + R (Trigger) recieved
23
      savedChar[1] = 'R';
24
25
    if( savedChar[1] == 'R' )  //If Trigger Mode
26
    {
27
      if( getChar == 'P' )  //If P (Pin) recieved
28
        savedChar[2] = 'P';
29
      else if( getChar == 'S' )
30
        savedChar[2] = 'S';
31
    
32
      if ( savedChar[2] == 'P' )
33
      {
34
        if ( getChar == 'I' )
35
          savedChar[3] = 'I';
36
        else if( getChar == 'E' )
37
          savedChar[3] = 'E';
38
39
        if( savedChar[3] == 'I' )
40
        {
41
          //chosenPin = atoi(getChar);
42
43
          if ( getChar == '\r' || getChar == '\n');
44
          {
45
            ENTER_Push[0] = 1;
46
          }
47
        }
48
      }
49
    }
50
  }
51
  
52
  add_menutext(&LCDLine1[0], "%d", chosenPin);
53
54
  if (ENTER_Push[0] == 1)
55
  {
56
    togglePeriod_slow(100, 4); //Beispielaufruf
57
    ENTER_Push[0] = 0;
58
  }
59
60
}

was sagt ihr dazu??


Gruß und danke
joe

von Falk B. (falk)


Lesenswert?

@ µC-noob (Gast)

>Der Code unten wird jede ms aufgerufen.

Warum so oft?

>Hat jemand einen Vorschlag wie ich das verbessern/ Optimieren kann.

Hmm, warum liest du nicht erst ein komplettes Kommando ein, welchen mit 
RETRUN ('\r') abgeschlossen wird. Den empfangenen String kann man dann 
viel einfacher analysieren. Etwa so.

1
  char rx_buffer[16];
2
3
  while(1) {                                // endless main loop
4
    i=getc();
5
    putc(i);
6
    if (pos<16) {
7
      rx_buffer[pos]=i;
8
      pos++;
9
    }
10
    if (i=='\r') {
11
      switch (rx_buffer[0]) {
12
        case 'C': cmd_C(rx_buffer, pos); break;
13
        case 'I': cmd_I(rx_buffer, pos); break;  
14
        case 'O': cmd_O(rx_buffer, pos); break;        
15
        case 'P': cmd_P(rx_buffer, pos); break;
16
        default: put_error(); break; // command illegal
17
      }
18
      pos=0;
19
    }
20
  }

MFG
Falk

von Kai G. (runtimeterror)


Lesenswert?

Ich glaube, du musst mir erklären, was der Code tun soll... das ist mir 
zu aufwendig zu lesen.

von UBoot-Stocki (Gast)


Lesenswert?

Abo

von µC-noob (Gast)


Lesenswert?

???? Abo ?????
Hä??


Danke erstmal,

hab das Programm erstmal zu testzwecken folgendermaßen angepasst:
1
void triggerCommand (void)
2
{
3
4
  static unsigned char rx_buffer[16];
5
  static unsigned char pos = 0; 
6
  unsigned char actChar = 0;
7
  
8
  static unsigned char testLCD = 0;  
9
                         
10
    actChar = uart0_getc();
11
12
  LCDLine3[7] = actChar;
13
14
    if ( pos < 16 )//Hier vermute ich den Fehler
15
  {
16
      rx_buffer[pos] = actChar;
17
      pos++;
18
    uart0_putc(actChar);
19
    }
20
21
    if (actChar =='\r') 
22
    {
23
      switch (rx_buffer[0]) 
24
      {
25
        case 'T': 
26
    testLCD = 1;
27
    break;
28
      }
29
      pos=0;
30
    }
31
}
32
  if (testLCD == 1)
33
     LCD_puts("eee");


Ich denke das liegt daran, dass die Bufferpos immer hochgezählt wird, 
auch wenn kein zeichen gesendet wird, korrigiert mich wenn ich Stuss 
erzähl??
Da ich den Code ja periodisch aufrufe, aber nicht jede Periode ein Char 
gesendet wird klappt das nann so nicht.

Aber wie stell ich es an, dass nur wenn ein zeichen empfangen wird, also 
nach einer eingabe im Hiperterminal, der Buffer gefüllt wird??

Danke
Joe

von Falk B. (falk)


Lesenswert?

@ µC-noob (Gast)

>Ich denke das liegt daran, dass die Bufferpos immer hochgezählt wird,
>auch wenn kein zeichen gesendet wird, korrigiert mich wenn ich Stuss
>erzähl??

Stuss. pos wird nur höht, wenn ein zeichen empfangen wurde UND pos <15 
ist, um einen Bufferüberlauf zu vermeiden.

>Aber wie stell ich es an, dass nur wenn ein zeichen empfangen wird, also
>nach einer eingabe im Hiperterminal, der Buffer gefüllt wird??

Ganz einfach. Deine Funktion uart0_getc() muss so aufgebaut sein, dass 
sie nur dann ein Zeichen liefert, wenn eins im UART RX buffer steht. 
Wenn NICHT, wird NICHT gewartet. ODer halt einfach vorher das Flag 
abfragen und entsprechend verzweigen. Denk aber auch dran, dass dann 
deine Datenrate auf 1000 Zeichen/s begrenzt ist, also knapp 9k6 Baud.

MFG
Falk

von Karl H. (kbuchegg)


Lesenswert?

µC-noob wrote:

> Aber wie stell ich es an, dass nur wenn ein zeichen empfangen wird, also
> nach einer eingabe im Hiperterminal, der Buffer gefüllt wird??

In dem Fall wird dir wohl uart0_getc() einen Returncode liefern
müssen, der genau das aussagt: Ich habe kein Zeichen empfangen.


Und darauf reagierst du dann. Zb. indem die Funktion triggerCommand
dann gar nicht weitermacht, sondern gleich retourniert.

Im übrigen kann ich nur Falk's Aussage noch mal unterstreichen:
Trenne das Empfangen eines Kommandos von der Auswertung. Trennen
heist in diesem Fall: Das sollen auch verschiedene Funktionen
sein.
Die eine Funktion empfängt einen String (Eine Sequenz von Zeichen
die zb. durch Empfang eines '\r' abgeschlossen wird).
Die andere Funktion bekommt einen String übergeben und wertet
ihn aus.

Gerade bei einfachen Systemen ist der Gedanke natürlich
verführerisch, dass alles in eine Funktion zu packen. Du
hast in deinem ersten Programm schon gesehen wohin das führt:
In endlose if-then-else Orgien. Und dabei hast du noch nicht
mal Fehlerbehandlung mit dabei.
Bei kleinen Programmen und wenigen Kommandos an der Schnittstelle
mag das sogar noch leidlich funktionieren. Sobald du aber mehr als,
sagen wir mal 8 bis 10 Kommandos hast, die ev. nicht mehr nur aus
einem Buchstaben bestehen, ist so ein Ansatz nicht mehr vernünftig
handhabbar.

von µC-noob (Gast)


Lesenswert?

Erstmal herzlichen Dank für die Hilfe.


So sieht der Code derzeit aus:
1
void cmd_T(char *rx_buffer, unsigned char pos)
2
{
3
  if ( rx_buffer[1] == 'R' )
4
  {
5
    if( rx_buffer[2] == 'P' )
6
    {
7
      if( rx_buffer[3] == 'I' ) //if command TRPI (Triggerpin)
8
      {
9
        togglePeriod_slow(100, 4);  //To Test
10
      }
11
      else if ( rx_buffer[3] == 'E' ) //if command TRPE (Triggerperiod)
12
      {
13
        togglePeriod_slow(100, 2); //To Test
14
      }
15
    }
16
  }
17
}
18
19
void cmd_P(char *rx_buffer, unsigned char pos)
20
{
21
  
22
      add_menutext(&LCDLine3[0], "aaa",0);  
23
24
}
25
26
void put_error(void)
27
{
28
29
}
30
31
32
void triggerCommand (void)
33
{
34
  static char rx_buffer[16];
35
  static unsigned char pos = 0; 
36
  unsigned char actChar = 0;
37
          
38
    actChar = uart0_getc();
39
40
  if (pos < 16 ) 
41
  {
42
    rx_buffer[pos] = actChar;
43
    pos++;
44
  }
45
46
  if ( actChar == '\r' ) 
47
  {
48
    switch (rx_buffer[0]) 
49
    {
50
      case 'T':   
51
        cmd_T(rx_buffer, pos); 
52
        rx_buffer[0] = ' ';
53
      break;
54
      case 'P': 
55
        cmd_P(rx_buffer, pos); 
56
      break;  
57
58
      default: put_error(); break; // command illegal
59
    }
60
    pos = 0;
61
  }
62
}

Es läuft noch nicht 100%,
so wird nicht nach einem Commando ein Enter abgewartet.

Und wenn ein Zeichen im Hypertrm eingegeben wird, bevor mind. einmal 
Enter gedrückt wurde, sendet er ununterbrochen das zeichen bis einmal 
Enter gedrückt wurde.
Ich werde versuchen den Fehler herauszufinden, falls euch etwas 
auffällt, oder ihr noch Verbesserungsvorschläge habt, immer gerne...

bis dann
Gruß

von Falk B. (falk)


Lesenswert?

@ µC-noob (Gast)

>Es läuft noch nicht 100%,
>so wird nicht nach einem Commando ein Enter abgewartet.

>Und wenn ein Zeichen im Hypertrm eingegeben wird, bevor mind. einmal
>Enter gedrückt wurde, sendet er ununterbrochen das zeichen bis einmal
>Enter gedrückt wurde.
>Ich werde versuchen den Fehler herauszufinden, falls euch etwas
>auffällt, oder ihr noch Verbesserungsvorschläge habt, immer gerne...

Liest du auch mal die Posts? Deine Funktion uart0_getc() muss angepasst 
werden. Wie sieht die aus?
Der Effekt hängt wahrscheinlich mit dem Rest des Programms zusammen.

MfG
Falk

von Karl H. (kbuchegg)


Lesenswert?

µC-noob wrote:
>
>
1
> void cmd_T(char *rx_buffer, unsigned char pos)
2
> {
3
>   if ( rx_buffer[1] == 'R' )
4
>   {
5
>     if( rx_buffer[2] == 'P' )
6
>     {
7
>       if( rx_buffer[3] == 'I' ) //if command TRPI (Triggerpin)
8
>       {
9
>         togglePeriod_slow(100, 4);  //To Test
10
>       }
11
>       else if ( rx_buffer[3] == 'E' ) //if command TRPE (Triggerperiod)
12
>       {
13
>         togglePeriod_slow(100, 2); //To Test
14
>       }
15
>     }
16
>   }
17
> }
18
>

So könnte das aussehen
1
void cmd_T( char *rx_buffer )
2
{
3
  if( strcmp( rx_buffer, "RPI" ) == 0 )
4
    togglePeriod_slow(100, 4);
5
6
  else if( strcmp( rx_buffer, "RPE" ) == 0 )
7
    togglePeriod_slow(100, 2);
8
9
  ....  // nächstes Kommando
10
}

Dazu musst du aber C-Strings beim Empfang bilden, also
welche die mit einem '\0' Character abgeschlossen sind.

http://www.mikrocontroller.net//articles/FAQ#Wie_funktioniert_String-Verarbeitung_in_C.3F

> Es läuft noch nicht 100%,

Wundert mich nicht. Um den Fall, dass uart0_getc kein Zeichen
empfangen hat, hast du dich immer noch nicht gekümmert.

Was ist denn da dran so schwer (Ich rate jetzt einfach mal
wie deine uart0_getc aussehen könnte)
1
uint8_t uart0_getc(void)
2
{
3
    if (!(UCSRA & (1<<RXC)))   // wenn kein Zeichen verfügbar
4
       return 0;               // ... dann eine 0 zurück
5
    return UDR;                // ... ansonsten das empfangene Zeichen
6
}

Anstatt dem üblichen while ein if und wenn dessen Bedingung wahr ist
und daher kein Zeichen vorliegt, gehts gleich mit 0 zum Aufrufer
zurück. 0 deshalb, da du anscheinend Textbasierte Kommunikation
machst, und kein druckbares ASCII Zeichen den ASCII Code 0 hat.

Beim Aufrufer
1
uint8_t receiveString( char *rx_buffer, uint8_t bufferSize, uint8_t *pos )
2
{
3
  char actChar = uart0_getc();
4
  if( actChar == 0 )
5
    return 0;
6
7
  if( actChar == '\r' || *pos == bufferSize - 1 ) {
8
    rx_buffer[ *pos ] = '\0';   // String abschliessen
9
    *pos = 0;
10
    return 1;
11
  }
12
13
  rx_buffer[*pos] = actChar;
14
  *pos++;
15
  return 0;
16
}


und das ganze dann in einem Programm eingebaut
1
char Buffer[40];
2
uint8_t BufferCnt;
3
4
....
5
6
int main()
7
{
8
   .....
9
10
11
   while( 1 ) {
12
13
     if( receiveString( Buffer, sizeof( Buffer ), &BufferCnt ) )
14
       cmd_T( Buffer, sizeof( Buffer ) );
15
   }
16
}

Siehst du wie sich jede Funktion nur um den Mist kümmert, für den
sie gemacht wurde? Die receive_string kümmert sich nur darum
eine Zeile von der UART zu lesen. Dafür kümmert sich cmd_T nur
darum diesen String auszuwerten.

Warnung: ungetesteter Code! Das Prinzip stimmt aber da mag noch der
eine oder andere Syntax Error drinn sein.

von µC-noob (Gast)


Lesenswert?

Danke

Hat auf Anhieb funktioniert.

Erstmal, natürlich lese ich die Posts, ich wär ja blöd wenn ichs nicht 
täte bei der tollen Hilfe!

Folgendermaßen sieht der Code jetzt aus.
Ein paar wenige Punkte, die so nicht funktionierten, habe ich 
auskommentiert.
1
#include "string.h"
2
3
4
char Buffer[40];
5
unsigned char BufferCnt;
6
7
8
void cmd_T( char *rx_buffer )
9
{
10
  if( strcmp( rx_buffer, "TRPIN" ) == 0 )
11
    togglePeriod_slow(100, 4);
12
13
  else if( strcmp( rx_buffer, "TRPER" ) == 0 )
14
    togglePeriod_slow(100, 2);
15
16
  else if( strcmp( rx_buffer, "TRPER" ) == 0 )
17
    togglePeriod_slow(100, 2);   
18
19
  // nächstes Kommando
20
}
21
22
23
unsigned char receiveString( char *rx_buffer, unsigned char bufferSize ) //, unsigned char *pos )
24
{
25
  static unsigned char pos = 0;
26
  char actChar = uart0_getc();
27
28
  uart0_putc(actChar);
29
30
  if( actChar == 0 )
31
    return 0;
32
33
  if( actChar == '\r' || pos == bufferSize - 1 ) 
34
  {
35
    rx_buffer[ pos ] = '\0';   // String abschliessen
36
    pos = 0;
37
    return 1;
38
  }
39
40
  rx_buffer[pos] = actChar;
41
  pos++;
42
  return 0;
43
}
44
45
46
void task_uartCommand(void)
47
{
48
     if( receiveString( Buffer, sizeof(Buffer)) ) //, &BufferCnt ) )
49
       cmd_T( Buffer ); //, sizeof( Buffer ) );
50
}

Hier dann noch die getc() (Anm.: Code von Peter Fleury)
1
unsigned int uart0_getc(void)
2
{    
3
    unsigned char tmptail;
4
    unsigned char data;
5
6
7
    if ( UART0_RxHead == UART0_RxTail )
8
    {
9
        return 0; //Davor return 0x0100, angepasst an: kein return (Fehler?)
10
    }
11
    
12
   
13
    // calculate /store buffer index
14
    
15
    tmptail = (UART0_RxTail + 1) & UART0_RX_BUFFER_MASK;
16
    UART0_RxTail = tmptail; 
17
    
18
19
    // get data from receive buffer
20
    
21
    data = UART0_RxBuf[tmptail];
22
    
23
24
    return (UART0_LastRxError << 8) + data;
25
26
}


Jetzt noch eine abschließende Frage,
Leide muss ich nicht immer Text verarbeiten. Nicht falsch verstehen über 
den UART empfange ich immer ASCII - Zeichen.

Aber es kann auch vorkommen dass eine Zahl (0 <= Zahl <=65535) 
eingetippt wird
z.B
Hypertrm: '1'
oder Hypertrm: '1233'

Diese müssen dann in ein int gewandelt und verarbeitet werden.

Ich wollte es folgendermaßen machen:
1
void command_Integer(unsigned char commandValue, char *rx_buffer)
2
{
3
  static unsigned char pin = 0;
4
  static unsigned int period = 0;
5
6
  if ( commandValue == TRIGGER_PIN )
7
  {
8
    pin = atoi(rx_buffer);
9
  }
10
  else if ( commandValue == TRIGGER_PER )
11
  {
12
      period = atoi(rx_buffer);
13
  }
14
15
  else if ( commandValue == TRIGGER_START )
16
  {
17
    togglePeriod_slow(period, pin);
18
  }
19
    
20
}
21
22
void cmd_T( char *rx_buffer )
23
{
24
    static unsigned char command = 0;
25
26
  if( strcmp( rx_buffer, "TRPIN" ) == 0 )
27
    command = TRIGGER_PIN;// togglePeriod_slow(100, 4);
28
29
  else if( strcmp( rx_buffer, "TRPER" ) == 0 )
30
    command = TRIGGER_PER; //togglePeriod_slow(100, 2);
31
32
  else if( strcmp( rx_buffer, "TRSTART" ) == 0 )
33
    command = TRIGGER_START; //togglePeriod_slow(100, 2);   
34
35
36
  command_Integer(command, rx_buffer);
37
38
39
  // nächstes Kommando
40
}
Und es Funktioniert auch.
Aber:
Geht es irgendwie hier noch zu prüfen, ob nicht zwischen der zahl 
schrott gesendet wurde.
Wird erkannt:
'100'
Wird nicht erkannt:
'1trz4'

Aber bevor ich wieder nur unnötig kompliziertes Zeug mache, wollt ich 
nach eurer Meinung Fragen, wie ichs am klügsten anstellen kann??

Danke nochmal,

Gruß

von Karl H. (kbuchegg)


Lesenswert?

µC-noob wrote:

> Geht es irgendwie hier noch zu prüfen, ob nicht zwischen der zahl
> schrott gesendet wurde.
> Wird erkannt:
> '100'
> Wird nicht erkannt:
> '1trz4'

atoi ist hier die falsche Funktion.
Im Grunde gibt es 3 Möglichkeiten:

* die Konversion selbst schreiben. Dann kann man klarerweise
  die entsprechenden Tests einbauen

* Eine Prüffunktion schreiben, die den String abklappert, ob
  auch nur Ziffern und eventuell noch '+' und '-' darin
  vorkommen. Diese Funktion stellt nur fest, ob der angegebene
  String eine Zahl sein kann. Nicht mehr. Nennen wir sie mal
1
  uint8_t IsZahl( const char* String )
2
  {
3
    // gibt es ein Vorzeichen?
4
    if( *String == '+' || *String == '-' )
5
      String++;
6
7
    // ein leerer String wird nicht als Zahl akzeptiert
8
    if( *String == '\0' )
9
      return 0;
10
11
    // ein String ist dann eine Zahl, wenn er nur aus
12
    // Digits, also den Buchstaben '0' bis '9' besteht
13
    while( *String ) {
14
      if( !isdigit( *String ) )  // Oha. Kein Digit -> keine Zahl
15
        return 0;
16
      String++;
17
    }
18
19
    // alles in Ordnung
20
    return 1;
21
  }

* eine andere Konvertier - Funktion nehmen.
  Was müsste das Ziel sein?
  Das Ziel müsste sein, nach der Konversion nachsehen, ob
  auch alle Zeichen des Strings konsumiert wurden. Wenn
  dein String also zb. so aussieht "123" und nach der
  Konversion hast du festgestellt, dass auch 3 Zeichen
  konsumiert wurden, dann waren offensichtlich keine
  Schrottzeichen im String enthalten.

  Mit diesenm Hintergedanken, lies dir mal diese Site durch:
  http://www2.informatik.uni-halle.de/lehre/c/c_str2n.html

von Fred (Gast)


Lesenswert?

Oder du sparst dir den ganzen Stress und benutzt sscanf()...:]

Ein Kommando-Interpreter sollte folgendes machen:

- nach dem ersten Leerzeichen suchen
- nachschauen ob die Zeichen vor dem Leerzeichen ein Kommando darstellen
- Kommandofunktion aufrufen und den Rest des empfangenen Strings (nach 
dem Kommando

von Fred (Gast)


Lesenswert?

Oder du sparst dir den ganzen Stress und benutzt sscanf()...:]

Ein Kommando-Interpreter sollte folgendes machen:

- nach dem ersten Leerzeichen suchen
- nachschauen ob die Zeichen vor dem Leerzeichen ein Kommando darstellen
- Kommandofunktion aufrufen und den Rest des empfangenen Strings (nach
  dem Kommando) der sscanf vorwerfen

Funktioniert so

iReturn = sscanf(sParastring, " %u %d", &uPara1, &iPara2);

Wenn dein Kommando 2 Parameter erwartet (einen unsigned int udn einen 
int) prüfst du ob iReturn = 2 ist und wertest uPara1 und iPara2 aus. 
Ansonsten gibst du einen Fehler aus.

von Karl H. (kbuchegg)


Lesenswert?

Fred wrote:
> Oder du sparst dir den ganzen Stress und benutzt sscanf()...:]

Ist sicherlich eine Möglichkeit.
Auf der anderen Seite sind sscanf  scanf  printf / sprintf
nicht gerade Resourcenschoner. Auf einem Mega128 spielt das
keine grosse Rolle. Auf einem Mega8 kann das aber den Unterschied
machen zwischen: Programm passt in den Speicher und Programm
passt nicht in den Speicher.

Was mit sscanf auch nicht so schön ist. Die Ausgabe von
qualifizierten Fehlermeldungen, ala: 'Parameter 2 invalid'
ist schwierig. Muss kein Problem sein, kann es aber manchmal
sein.

von Fred (Gast)


Lesenswert?

Resourcenfresser: Genau deiner Meinung...

Fehlermeldungen: Ich mach es in der Regel so, daß ich ein "Syntax: xy 
<0..5> <-255..255>" ausgebe. Der Benutzer muss sich selbst überlegen wo 
er Mist gebaut hat.

von µC-noob (Gast)


Lesenswert?

Ok, danke erstmal,

bei mir haperts noch an einer Stelle:
1
digitValue = (unsigned int)strtoul(rx_buffer, &controlChar, 5);

Aber was für einen Wert bekommt control Char wenn alles stimmt,
hab mirs übers LCD anzeigen lassen und dort war ein Schwarzer balken zu 
sehen, also ASCII 0xDB

Dann wollt ich das so machen:
1
digitValue = (unsigned int)strtoul("546", &controlChar, 5);
2
3
for (i = 0; i < 5; i++)
4
{
5
 if(controlChar[i] != 0xDB)
6
   digitError = 1;
7
}


Aber so läuft gar nix mehr... sollte doch eigentlich, da ich ja nur 
zahlen im String stehen hab??

Gruß

von Karl H. (kbuchegg)


Lesenswert?

1
#include <stdio.h>
2
#include <stdlib.h>
3
4
int main()
5
{
6
  char Text[] = "123";
7
  char* End;
8
9
  unsigned long Zahl = strtoul( Text, &End, 10 );
10
11
  if( *End == '\0' )
12
    printf( "OK %u\n", Zahl );
13
14
  else if( End == Text )
15
    printf( "Keine Zahl vorhanden\n" );
16
17
  else
18
    printf( "Zahl vorhanden %u, aber da kommt noch was im String\n", Zahl );
19
20
}

Das 2-te Arugument zu strtoul ist die Adresse eines Character
Poitners. Dort hinterlässt strtoul, wo es aufgehört hat die
Zahl zu lesen. Geschah dies am Ende des Strings dann sind
da keine Zeichen mehr vorhanden. Geschieht dies irgendwo
im String, dann kommen noch der Zahl noch Zeichen, die nicht
zur Zahl gehört haben. Hat strtoul überhaupt nichts gelesen,
dann ist der Ende Pointer ganz am Anfang des Strings
(ist auch logisch, strtoul hat ja sofort aufgehört zu lesen) und
es war überhaupt nichts im String was eine Zahl sein könnte.

von µC-noob (Gast)


Lesenswert?

Gaaaanz großen Dank...

Gruß
Joe

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.