Forum: PC-Programmierung strDelete und strcpy


Announcement: there is an English version of this forum on EmbDev.net. Posts you create there will be displayed on Mikrocontroller.net and EmbDev.net.
von Martin M. (ats3788)


Bewertung
0 lesenswert
nicht lesenswert
Hallo
Ich sitze hier und fudele an ein paar Funktionen und da meine Hirnbüchse
qualmt möchte ich euch fragen, in C gibt es so viele SSting Funktionen, 
die meiner Meinung, nicht wirklich nützlich sind ich komme aus der 
Pascal Welt und habe deswegen einen anderen Ansatz bei "C".
Ich suche eine Funktion wie StringDelete(char * dst, int von,int Bis)
die mir aus einem Text Array von, bis herausschneidet

und ein StringInsert wäre auch toll StringInsert(char * dst,char * 
src,int pos)
und ein stringCopy(char * dst,int von, int bis);

die habe ich mir geschrieben aber die ist so scheiße das ich mich nicht 
traue sie zu posten. Finde es schade das dies im Standard Repertoir 
nicht bei "C" vorkommt.
Danke Leute, Liebe Grüße aus dem sonnigen Font de Sa Cala

von leo (Gast)


Bewertung
0 lesenswert
nicht lesenswert
Martin M. schrieb:
> Ich suche eine Funktion wie StringDelete(char * dst, int von,int Bis)

$ man memmove

und genau zaehlen ;-)

leo

von zitter_ned_aso (Gast)


Bewertung
0 lesenswert
nicht lesenswert
Martin M. schrieb:
> eine Funktion wie StringDelete(char * dst, int von,int Bis)
> die mir aus einem Text Array von, bis herausschneidet

z.B. so
char* StringDelete(char * dst, int von,int Bis){                        
                                                                        
    memmove(dst+von, dst+Bis, strlen(dst+Bis));                         
    dst[strlen(dst)-(Bis-von)]='\0';                                    
                                                                        
    return dst;                                                         
}

von leo (Gast)


Bewertung
0 lesenswert
nicht lesenswert
zitter_ned_aso schrieb:
> memmove(dst+von, dst+Bis, strlen(dst+Bis));
>     dst[strlen(dst)-(Bis-von)]='\0';

Man kann natuerlich die '\0' mitmoven und erspart sich damit die 2. 
Zeile.

leo

von zitter_ned_aso (Gast)


Bewertung
0 lesenswert
nicht lesenswert
leo schrieb:
> Man kann natuerlich die '\0' mitmoven und erspart sich damit die 2.
> Zeile.

Ja, Danke für diesen Hinweis:
char* StringDelete(char * dst, const int von, const int Bis){           
                                                                        
    assert(von<=Bis && dst!=NULL);                                      
                                                                        
    memmove(dst+von, dst+Bis, strlen(dst+Bis)+1);                       
                                                                        
    return dst;                                                         
} 


char* StringInsert(char * dst,const char * src,const int pos){          
                                                                        
    assert(dst!=NULL && src!=NULL && pos>=0);                           
                                                                        
    memmove(dst+pos+strlen(src), dst+pos, strlen(dst+pos)+1);             
    memmove(dst+pos, src, strlen(src));                                 
                                                                        
    return dst;                                                         
}  


von zitter_ned_aso (Gast)


Bewertung
0 lesenswert
nicht lesenswert
StirngInsert(...) ist natürlich sehr gefährlich weil "source" groß genug 
für einen neuen String sein muss.

Keine Ahnung wie man hier die Gefahr einschränkt ;-)

von Johnny B. (johnnyb)


Bewertung
0 lesenswert
nicht lesenswert
Martin M. schrieb:
> in C gibt es so viele SSting Funktionen,
> die meiner Meinung, nicht wirklich nützlich sind ich komme aus der
> Pascal Welt

Da kann ich Dir C# mit .NET empfehlen, da kannst Du mit Strings ebenso 
elegant oder sogar noch eleganter hantieren wie früher mit Delphi.

von leo (Gast)


Bewertung
0 lesenswert
nicht lesenswert
zitter_ned_aso schrieb:
> StirngInsert(...) ist natürlich sehr gefährlich weil "source" groß
> genug
> für einen neuen String sein muss.
>
> Keine Ahnung wie man hier die Gefahr einschränkt ;-)

Indem man die moegliche Gesamtlaenge als Param mitgibt, prueft und sich 
darauf verlaesst, dass diese auch korrekt ist.

leo

von zitter_ned_aso (Gast)


Bewertung
0 lesenswert
nicht lesenswert
ja, hört sich vernünftig an.

von Martin M. (ats3788)


Bewertung
0 lesenswert
nicht lesenswert
Wow Danke,war nur Einkaufen und so viele antworten, Danke Danke, werde 
das nach dem essen mal ausprobieren

von Dirk B. (dirkb2)


Bewertung
0 lesenswert
nicht lesenswert
leo schrieb:
> zitter_ned_aso schrieb:
>> memmove(dst+von, dst+Bis, strlen(dst+Bis));
>>     dst[strlen(dst)-(Bis-von)]='\0';
>
> Man kann natuerlich die '\0' mitmoven und erspart sich damit die 2.
> Zeile.
>
> leo

Und wenn Bis nicht am Ende vom String liegt?

von Dirk B. (dirkb2)


Bewertung
0 lesenswert
nicht lesenswert
Martin M. schrieb:
> Finde es schade das dies im Standard Repertoir
> nicht bei "C" vorkommt.

Du kannst dir die Funktionen selber schreiben, ist eine prima Übung.

Viele Stringfunktionen der Standardlibrary haben sowieso den Nachteil, 
dass sie nicht wissen, wie groß der Zielbereich ist.

von Rolf M. (rmagnus)


Bewertung
0 lesenswert
nicht lesenswert
Dirk B. schrieb:
> Und wenn Bis nicht am Ende vom String liegt?

Dann liegt das \0 immer noch am Ende.

von Martin M. (ats3788)


Bewertung
0 lesenswert
nicht lesenswert
@Johnny B. Das ist nett aber ich programmiere damit µC also so Dinger 
wie
ESP32 und mit den Funktionen Die ihr mir gegeben habt geht das ganz gut.
Windows Sachen programmiere ich in Delphi. Danke

char* StringDelete(char * dst, int von,int Bis)
{           // Hier die + 1 eingefügt sonst siehe unten
    memmove(dst+von, dst+Bis+1, strlen(dst+Bis+1));
    dst[strlen(dst)-(Bis-von)]='\0';

    return dst;
}

sonst wird ein Char zuviel kopiert
Herzlichen Dank an Zitter_ned und Leo für ihre besondere Hilfe
Schade das das Forum keine Emotes hat.
Jetzt guck ich mal ob ich das StringCopy hinbekomme.

von Rolf M. (rmagnus)


Bewertung
0 lesenswert
nicht lesenswert
Martin M. schrieb:
> @Johnny B. Das ist nett aber ich programmiere damit µC also so Dinger
> wie ESP32 und mit den Funktionen Die ihr mir gegeben habt geht das ganz gut.

Warum hast du die Frage dann im Forum "PC-Programmierung" gepostet?

> char* StringDelete(char * dst, int von,int Bis)
> {           // Hier die + 1 eingefügt sonst siehe unten
>     memmove(dst+von, dst+Bis+1, strlen(dst+Bis+1));
>     dst[strlen(dst)-(Bis-von)]='\0';
>
>     return dst;
> }

Es wurde ja schon geschrieben, dass man auch einfach ein Zeichen mehr 
kopieren und sich dann die zweite Zeile sparen kann, vor allem auch das 
strlen, das dann nochmal den kompletten String durchiterieren muss.

von Dirk B. (dirkb2)


Bewertung
0 lesenswert
nicht lesenswert
Rolf M. schrieb:
> Dirk B. schrieb:
>> Und wenn Bis nicht am Ende vom String liegt?
>
> Dann liegt das \0 immer noch am Ende.

Oh Mann, ich war irgendwie bei dem StringCopy.

von Michael Gugelhupf (Gast)


Bewertung
0 lesenswert
nicht lesenswert
zitter_ned_aso schrieb:
>
> char* StringDelete(char * dst, const int von, const int Bis){
> 
>     assert(von<=Bis && dst!=NULL);
> 

Ich würde schon ein bisschen mehr testen, nämlich das "bis" nicht die 
String-Länge überschreitet.

Aber fangen wir mal von vorne an:

Martin M. schrieb:
> ich komme aus der
> Pascal Welt und habe deswegen einen anderen Ansatz bei "C".
> Ich suche eine Funktion wie StringDelete(char * dst, int von,int Bis)
> die mir aus einem Text Array von, bis herausschneidet

Pascal zählt String-Positionen ab 1, C ab 0. Der OP sollte sich zuerst 
mal überlegen ob er Pascal-Zählung in C haben möchte. Umgekehrt ist es 
auch keine besonders gute Idee eine Funktion aus Pascal nachzubasteln, 
die so heißt wie in Pascal, aber um eine Position verschoben arbeitet. 
Damit verwirrt man sich nur selbst.

Pascals normales Delete() verwendet nicht wie behauptet "von" und "bis" 
Positionen, sondern Startposition und Länge des zu löschenden Bereiches.

Damit wären wir bei

[c]
/*!
 \param s    string to delete a part from
 \param off  index (counting from 0) of first characer to delete from s
             If off exceeds strlen(s), then off is assumed to be 
strlen(s)
 \param n    maximum number of characters to be deleted.
             If off+n exceeds string length strlen(s), then only the
             remaining chars in s deleted.
 \return s

*/
char *strdel(char *s, size_t off, size_t n) {
   assert(s != NULL);

   size_t l = strlen(s);
   off = (off > l) ? l : off;
   n = (off + n) > l ? (l - off) : n;

   memmove(s + off, s + off + n, l - off - n + 1);

   return s;
}
[c]

Die Funktion korrigiert ein paar mögliche Fehler in den übergebenen 
Parametern. Eigentlich bin ich kein Fan von solchen heimlich 
vorgenommenen Reparaturen. Hier würde ich es machen um eine bequeme 
Funktion zu bekommen. Ansonsten assert().

off wird bei Überlauf bewusst auf strlen(s) und nicht strlen(s) -1 
gesetzt. Damit wird das \0-Byte immer kopiert, auch wenn es dann in 
Grenzfällen auf sich selbst kopiert wird.

Der Compiler darf gerne die Berechnungen optimieren. Dazu habe ich keine 
Lust.

von Peter D. (peda)


Bewertung
0 lesenswert
nicht lesenswert
Martin M. schrieb:
> Ich suche eine Funktion wie StringDelete
> und ein StringInsert wäre auch toll

Erfahrene Programmierer manipulieren Strings nicht direkt, sondern legen 
sich einen separaten Antwortpuffer an. Der eingehende String wird dann 
mit sscanf oder strtok geparst und abschließend mit strncat oder 
snprintf die Antwort gebastelt. Damit umgeht man elegant das Problem der 
Pufferüberläufe.

Eingehende Daten werden in der Regel nicht als Kopie, sondern als 
Pointer auf const übergeben, d.h. die aufgerufene Funktion darf die 
Daten nicht manipulieren. Daher gibt es die von Dir gewünschten 
Funktionen unter C nicht und sie werden auch nicht benötigt.

von Peter D. (peda)


Bewertung
0 lesenswert
nicht lesenswert
P.S.:
strtok ändert den String, geht also formal nicht auf const.
Auf µCs gibt es in der Regel aber keinen Schreibschutz auf RAM.

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.