Forum: Mikrocontroller und Digitale Elektronik String Hilfe gesucht


von TDK (Gast)


Lesenswert?

Hi,
ich habe ein kleines Problem.
Ich würde gerne die ersten 3 bzw. 4 Zeichen aus einem String löschen.
Wie wäre das möglich? (Programmiersprache C)
Gemacht werden sollte das für die Serielle Schnittstelle.
Ich bekomme von der Schnittstelle an den Controller
"read portb" oder ähnliches - nachdem ich read oder set abgefragt habe 
möchte ich dies aus meinen String löschen so das nur noch "portb" drinen 
stehen würde.
Mit strncpy geht das leider nicht da nur die ersten Zeichen ausgelesen 
werden. Desweiteren geht right() nicht da die zeichen von rechts gesehen 
nicht immer gleich lang sind!
Vielen dank schon mal
mfg
TDK

: Verschoben durch User
von Klaus W. (mfgkw)


Lesenswert?

Spontan fallen mir zwei Möglichkeiten ein:
- mit memmove() kann man Speicherbereiche verschieben,
  die sich auch überlappen dürfen wie hier.
  Als Länge muß man strlen(derrestlichestring)+1 angeben, damit
  auch die abschließende 0 mitkopiert wird.
1
#define GENUG       50
2
  char  meinString[GENUG] = "read portb";
3
  memmove( meinString, meinString+strlen("read "), strlen("portb")+1 );
4
5
  printf( "jetzt nur noch %s\n", meinString ); // "portb"
- Möglicherweise braucht man gar nicht kopieren, sondern lässt
  den String einfach stehen und verwendet halt nur den hinteren Teil.
  Beispiel:
1
#define GENUG       50
2
3
    char  langerString[GENUG] = "read portb";
4
    char *restlicherString;
5
6
    restlicherString = langerString + strlen( "read " );
7
    // jetzt zeigt restlicherString auf den String "portb",
8
    // davor steht der alte Anfang und wird einfach nicht
9
    // mehr benutzt
10
    printf( "jetzt nur noch %s", restlicherString ); // "portb"

von Klaus W. (mfgkw)


Lesenswert?

noch eine dritte Möglichkeit wäre, den alten String mit
strtok() aufzuteilen. Aber keiner mag strtok(), und hier ist es
vielleicht auch übertrieben.
1
#include <stdio.h>
2
#include <string.h>
3
4
5
#define GENUG       50
6
7
int main()
8
{
9
  char  meinString[GENUG] = "read portb";
10
11
  // beim ersten Aufruf von strtok() wird an der Stelle des
12
  // Leerzeichens in meinString[] eine terminierende 0 geschrieben und
13
  // ein Zeiger auf "read" geliefert:
14
  char *p_secondToken = strtok( meinString, " " );
15
  // der zweite Aufruf (ohne String) liefert das nächste Token, hier
16
  // auch gleichzeitig das letzte ("portb"):
17
  p_secondToken = strtok( NULL, " " );
18
19
  if( p_secondToken )
20
  {
21
    printf( "jetzt nur noch %s\n", p_secondToken ); // "portb"
22
  }
23
  return 0;
24
}

von TDK (Gast)


Lesenswert?

Erstmal danke für deine ausreiche Hilfe!
Eine Frage bleibt jedoch leider offen...
Der Compiler meckert bei
1
     
2
memmove( input, input+strlen("read "), strlen("portb")+1 );
mit folgender Meldung:
[pre]
*** Error 90 "seriell.c" Line 47(39,40): Attempt to create a pointer to 
a constant
[\pre]
Den gleichen Fehler habe ich wenn ich bei
1
 
2
if(strncmp(*input,*set, 3) == 0)
statt *set = "set" verwende... Gibt es dafür eine elegantere Lösung? (so 
muss ich nämlich für jede mögliche Antwortmöglichkeit auch einen eigenen 
char erstellen :(
Danke schon mal
mfg
TDK

von Klaus W. (mfgkw)


Lesenswert?

/pre geht besser als \pre...

- welcher Compiler? Bei mir hat mein Beispiel kompiliert!
- wie ist input vereinbart?

und dann musst du natürlich strlen("read ") und strlen("portb")
je nach deinem String anpassen!

von Klaus W. (mfgkw)


Lesenswert?

Nachtrag zum strtok():
Ich habe eben das Beispiel mit avr-gcc übersetzt, der kennt
gar kein strtok().
Stattdessen geht strtok_r():
1
#define GENUG       50
2
  char  meinString[GENUG] = "read portb";
3
  char *p_save;
4
  
5
  // beim ersten Aufruf von strtok() wird an der Stelle des
6
  // Leerzeichens in meinString[] eine terminierende 0 geschrieben und
7
  // ein Zeiger auf "read" geliefert:
8
  char *p_secondToken = strtok_r( meinString, " ", &p_save );
9
  // der zweite Aufruf (ohne String) liefert das nächste Token, hier
10
  // auch gleichzeitig das letzte ("portb"):
11
  p_secondToken = strtok_r( NULL, " ", &p_save );
12
  
13
  if( p_secondToken )
14
  {
15
    printf( "jetzt nur noch %s\n", p_secondToken ); // "portb"
16
  }

(strtok() ist ohnehin nicht ganz ungefährlich, da es zwischen
zwei Aufrufen in statischem Speicher Daten hält und deshalb
nicht gleichzeitig zwei Strings zerlegt werden können, mit
strtok_r() geht das sicherer)

von TDK (Gast)


Lesenswert?

habs mit mp-lab und ccs-c compiler probiert.
Ist aber auch egal wenns mit pointern geht ;-)
Auf jeden fall vielen dank an dich ;-)
mfg

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.