strstr() gibt keinen NULL pointer zurück? (atmega 2560)

OP #5914168
Hallo zusammen,

ich habe folgendes Problem:
Ich sende einen String den ich aus einer Datei lese per UART an den MCU 
(atmega 2560). Dort will ich aus diesem mit strstr() X und Y Koordinaten 
extrahieren.
Leider bleibt der Code in der While-Schleife hängen da scheinbar 
strstr() nie einen NULL Pointer zurück gibt. Ist der NULL Character '\0' 
zur Beendung des Strings falsch gesetzt?
Ich kann meinen Fehler leider nicht finden. Vielleicht könnt ihr mir 
helfen!?

Ich sende den String: "G01 X69.204775 Y23.337389 Z-0.100000 G01 
X80.964849 Y21.666507 Z-0.100000 G00 Z0.100000 (End cutting path id: 
path4285"

Zurück bekomme ich am Serial Port:
1
G01 X69.204775 Y23.337389 Z-0.100000 G01 X80.964849 Y21.666507 Z-0.100000 G00 Z0.100000 (dppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppp
 usw.

Mein Code sieht folgendermaßen aus ( zu beachten USART_Transmit('p'); um 
das while loop zu zeigen):
1
void USART_Init(unsigned int ubrr); 
2
void USART_Transmit(unsigned char data); 
3
unsigned char USART_Receive( void );
4
char uart_char;
5
char uart_string[100] = {""};
6

7
int main(void) 
8
{ 
9
  int char_counter = 0;
10
  USART_Init(MYUBRR); 
11
  while(uart_char != '('){
12
    uart_char = USART_Receive();
13
    uart_string[char_counter] = uart_char;
14
    char_counter++;
15
  }
16
  uart_string[char_counter] = '\0';
17
  
18
  for(int i = 0;i<sizeof(uart_string);i++){
19
    USART_Transmit(uart_string[i]);
20
  }
21

22
  char *hier;
23
  char x_values[50][7];
24
  char y_values[50][7];
25
  int number_of_coordinates = 0;
26
  USART_Transmit(sizeof(uart_string));
27
  while( (hier = strstr(uart_string, "G01 X")) != NULL){
28
    strncpy(x_values[0],hier+5,6);
29
    strncpy(y_values[0],hier+5+11,6);     
30
    number_of_coordinates++;
31
    USART_Transmit('p');
32
  }
33
  USART_Transmit('r');
34
  uint8_t coordinates [number_of_coordinates][2];
35
  for(int i=0;i<number_of_coordinates;i++){
36
    coordinates[i][0] = (int) atof(x_values[i]);
37
    coordinates[i][1] = (int) atof(y_values[i]);
38
  }
39
}
Gast #5914176
Hans L. schrieb:
1
while( (hier = strstr(uart_string, "G01 X")) != NULL) {
2
    strncpy(x_values[0],hier+5,6);
3
    strncpy(y_values[0],hier+5+11,6);
4
    number_of_coordinates++;
5
    USART_Transmit('p');
6
}

Da du innerhalb der while Schleife den gefundenen String nicht aus 
uart_string entfernst, findest du ihn immer wieder erneut.
Gast #5914197
Hans L. schrieb:
> while( (hier = strstr(uart_string, "G01 X")) != NULL){
>     strncpy(x_values[0],hier+5,6);
>     strncpy(y_values[0],hier+5+11,6);
>     number_of_coordinates++;
>     USART_Transmit('p');
>   }
Suche wird immer an der gleichen Stelle fortgesetzt!
1
char *pNext;   // !!!!
2

3
int main(void) 
4
{ 
5
  int char_counter = 0;
6
  USART_Init(MYUBRR); 
7
  while(uart_char != '('){
8
    uart_char = USART_Receive();
9
    uart_string[char_counter] = uart_char;
10
    char_counter++;
11
  }
12
  uart_string[char_counter] = '\0';
13
  
14
  for(int i = 0;i<sizeof(uart_string);i++){
15
    USART_Transmit(uart_string[i]);
16
  }
17

18
  char *hier;  
19
  char x_values[50][7];
20
  char y_values[50][7];
21
  int number_of_coordinates = 0;
22
  USART_Transmit(sizeof(uart_string));
23

24
  pNext=uart_string; //!!!!
25

26
  while( (hier = strstr(pNext, "G01 X")) != NULL){ //!!!!
27
    strncpy(x_values[0],hier+5,6);
28
    strncpy(y_values[0],hier+5+11,6);     
29
    number_of_coordinates++;
30
    USART_Transmit('p');
31
    pNext=hier; // !!!! hier wird bei der Suche weiter gesprungen
32
  }
33
  USART_Transmit('r');
34
  uint8_t coordinates [number_of_coordinates][2];
35
  for(int i=0;i<number_of_coordinates;i++){
36
    coordinates[i][0] = (int) atof(x_values[i]);
37
    coordinates[i][1] = (int) atof(y_values[i]);
38
  }
39
}

So sollte es gehen.
OP #5914230
Vielen Dank!!! :-)
Jetzt macht es Sinn!!

habe es jetzt so umgesetzt und es funktioniert:
1
  while( (hier = strstr(uart_string, "G01 X")) != NULL){
2
    strncpy(x_values[number_of_coordinates],hier+5,6);
3
    strncpy(y_values[number_of_coordinates],hier+5+11,6);
4
    strcpy(uart_string,hier+5);     
5
    number_of_coordinates++;
6
  }
Gast #5914263
Stefanus F. schrieb:
> Der Kopiervorgang ist allerdings wesentlich teurer, als den Zeiger zu
> versetzen.

Das ist der Grund warum C schneller ist als so mach andere Sprache ist. 
Zeiger machen es möglich. Aber es ist gefährlich wenn man nicht weiß was 
man damit anstellt.
#5914271
Hans L. schrieb:
> strncpy(x_values[0],hier+5,6);

Das funktioniert nicht so, wie du dir das vorstellst.

Wenn in den 6 Zeichen keine '\0' gefunden wird, wird auch keine kopiert.
Der String in x_Values ist nicht terminiert.

Warum überhaupt der Umweg über das 2D-char-Array.
atof hört da auf, wo es keine gültig Zahl erkennt.

Warum überhaupt atof, wenn du eigentlich atoi möchtest.
besser noch strtoul.
Gast #5914593
Es geht kürzer und klarer.
Das Einfügen der Z-Koordinaten sind jetzt ein Kinderspiel.

1
#include <stdio.h>
2
#include <stdlib.h>
3
#include <string.h>
4
#include <math.h>
5

6
char uart_string[]="G01 X69.204775 Y23.337389 Z-0.100000 G01 X80.964849 Y21.666507 Z-0.100000 G00 Z0.100000";
7

8
int main(void)
9
{
10
    char *px;
11
    float coordinates[10][2];
12

13
    int number_of_coordinates = -1;
14

15
    px=uart_string;
16

17
    memset(coordinates,0,sizeof(coordinates));
18

19
    while (*px)
20
    {
21
        switch (*px)
22
        {
23
            case 'G':
24
                number_of_coordinates++;
25
                break;
26

27
            case 'X':
28
                px++;
29
                coordinates[number_of_coordinates][0]=atof(px);
30
                break;
31

32
            case 'Y':
33
                px++;
34
                coordinates[number_of_coordinates][1]=atof(px);
35
                break;
36

37
            default:
38
                break;
39
        }
40
        px++;
41
    }
42

43
    for (number_of_coordinates=0;number_of_coordinates<10;number_of_coordinates++)
44
    {
45
        printf("%d\tx=%f\t\ty=%f\r\n",number_of_coordinates,coordinates[number_of_coordinates][0],coordinates[number_of_coordinates][1]);
46
    }
47
}

Vorteil :

-weniger Variable
-weniger Code
-vermutlich wesentlich schneller
-leichtere Ausbaufähigkeit

Auch für Prozessoren mit wenig SRAM geeignet, da strstr() ein 
Speicherfresser ist.
Angehängte Dateien:
Gast #5914653
GEKU schrieb:
> man könnte auch mit "while (uart_char)" direkt die Zeichen vom UART
> einlesen und im SWITCH die Abbruchbedingung exekutieren.

Vergessen , geht nicht so einfach, da mehrere Zeichen für FLOAT 
Variable gelesen werden müssen
OP #5915354
Hallo zusammen,

vielen Dank, dass ihr euch so viel Zeit genommen habt und meine Frage so 
detailliert beantwortet habt!
Ihr habt mir sehr geholfen und ich konnte auch viel dabei lernen!
Ich habe es jetzt so umgesetzt wie oben vorgeschlagen.

Echt klasse!!!

Antwort schreiben

Eine eigene Frage? Dieser Thread ist über 7 Jahre alt. Stell sie in einem eigenen Thread – dort lesen mehr Leute mit, und sie wird öfter und schneller beantwortet.

Neuen Thread starten

Eine Lösung, Ergänzung oder Rückmeldung zu diesem Thread? Dann antworte hier.

Formatierung
  • [c]C-Code[/c]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] – Link zu einem Artikel
  • Verweis auf einen anderen Beitrag: Rechtsklick auf dessen Beitrags-ID (#8078628), „Adresse kopieren“, in den Text einfügen

Mehr zur Formatierung

Längeren Sourcecode als Anhang, nicht in den Text. JPG nur für Fotos und Scans; Zeichnungen und Screenshots als PNG oder GIF. Siehe Bildformate.

Schon registriert? Anmelden

Wird nicht angezeigt. Wir schicken dir einen Link; sobald du damit bestätigst, erscheint dein Beitrag.

Mit dem Abschicken legst du einen kostenlosen Account an und erkennst die Nutzungsbedingungen und die Datenschutzerklärung an.