Control characters effizient von einem char array entfernen



  • unsigned char removeControlCharacterSetFromCharArray(char *input) 
    {
    	if (!input)
    		return 0;
    
    	size_t i;
    	for (i = 0; i < strlen(input) - 1; i++) {
    		if ((input[i] == '\n') || (input[i] == '\t') || ((input[i] == 0x20) && (input[i+1] == 0x20))) {
    			input[i] = 0x20;
    		}
    	}
    
    	if ((input[i] == '\n') || (input[i] == '\t') || (input[i] == 0x20)) {
    		input[i] = 0;
    	}
    
    	return 1;
    }
    

    Code schnell ausm Kopf heraus, aber sollte alles klar sein, was gemeint ist.

    Ich gehe mal davon aus, dass du zwischen jedem x.x ein Leerzeichen haben willst. Deine Fragestellung ist etwas konfus.



  • functi0n schrieb:

    unsigned char removeControlCharacterSetFromCharArray(char *input) 
    {
    	if (!input)
    		return 0;
    
    	size_t i;
    	for (i = 0; i < strlen(input) - 1; i++) {
    		if ((input[i] == '\n') || (input[i] == '\t') || ((input[i] == 0x20) && (input[i+1] == 0x20))) {
    			input[i] = 0x20;
    		}
    	}
    
    	if ((input[i] == '\n') || (input[i] == '\t') || (input[i] == 0x20)) {
    		input[i] = 0;
    	}
    
    	return 1;
    }
    

    Code schnell ausm Kopf heraus, aber sollte alles klar sein, was gemeint ist.

    Ich gehe mal davon aus, dass du zwischen jedem x.x ein Leerzeichen haben willst. Deine Fragestellung ist etwas konfus.

    Dein Code stellt aber nicht sicher, dass zwischen jeder Zahl nur genau ein Leerzeichen ist. Und sowas wie 0x20 ist einfach nur schlechter Stil.



  • @functi0n
    Die for-Schleife

    for (i = 0; i < strlen(input) - 1; i++)
    

    sollte nie so implementiert werden. Das strlen unbedingt aus dem Schleifen Kopf nehmen. Der Compiler kann das nicht optimieren und damit schafft man es ganz leicht aus O(n) Algorithmen O(n^2) Algorithmen zu basteln.



  • noergel schrieb:

    Dir ist schon klar, das es hier um plain C geht?

    Sicher. Dir ist schon klar, dass der Algorithmus, der in std::remove_if drin steckt in ähnlicher Form in C für die Lösung dieses Problems implementierbar ist?



  • krümelkacker schrieb:

    noergel schrieb:

    Dir ist schon klar, das es hier um plain C geht?

    Sicher. Dir ist schon klar, dass der Algorithmus, der in std::remove_if drin steckt in ähnlicher Form in C für die Lösung dieses Problems implementierbar ist?

    Auch deine Variante berücksichtigt nicht, dass eben genau ein Leerzeichen bleiben muss.

    Eine Lösung in C++ wäre daher vielleicht:

    char text[] = {"-0.1 0.2 0.5   \n\t-0.5 -0.5 0.5\n\t\t"};
    
    	std::stringstream strm(text);
    
    	std::stringstream result;
    
    	float tmp;
    	while (strm >> tmp)
    	{
    		result << tmp << " ";
    	}
    
    	std::cout << "'" << result.str().substr(0, result.str().size() - 1) << "'" << std::endl;
    

    Ausgabe: '-0.1 0.2 0.5 -0.5 -0.5 0.5'

    Schau dir einfach mal meine spontane Idee weiter oben an. Die erfüllt die Kriterien, denke ich.



  • Danke für die Antworten.

    Übrigens, wie von manchen hier schon bemerkt, es sollen Leerzeichen zwischen den "Zahlen" bleiben.

    Das Array soll später in ein float array umgewandelt werden.



  • x1c3 schrieb:

    Das Array soll später in ein float array umgewandelt werden.

    Und warum dann der Aufwand?
    Sowohl die scanf-Familie als auch strod überlesen führende Whitespace (" \n\t\r\v\f").
    Und durch den **endptr bei strtod bekommst du auch die nächste Position.



  • DirkB schrieb:

    x1c3 schrieb:

    Das Array soll später in ein float array umgewandelt werden.

    Und warum dann der Aufwand?
    Sowohl die scanf-Familie als auch strod überlesen führende Whitespace (" \n\t\r\v\f").
    Und durch den **endptr bei strtod bekommst du auch die nächste Position.

    Mit strtod ist das ganze natürlich viel komfortabler! Danke

    Übrigens, den Text erhalte ich von einem XML-Parser und dieser enthält Control-Characters.



  • [quote="fghfgh
    Dein Code stellt aber nicht sicher, dass zwischen jeder Zahl nur genau ein Leerzeichen ist. Und sowas wie 0x20 ist einfach nur schlechter Stil.[/quote]

    Steht irgendwo, dass ich das behauptet habe? Genau lesen, bitte!
    Und diese Funktion spiegelt auch nicht meinen Stil wieder. 😉



  • x1c3 schrieb:

    const char text[] = {"-0.5 0.5 0.5   \n\t-0.5 -0.5 0.5\n\t\t"};
    
    void trim(char *s)
    {
      int n;
      char *z=s;
      while( 1==sscanf(s,"%s%n",z,&n) )
      {
        s+=n;
        (z+=strlen(z)+1)[-1]=' ';
      }
      z!=s?*--z=0:0;
    }
    

    sollte laufen für nicht konstante Strings.

    x1c3 schrieb:

    Das Array soll später in ein float array umgewandelt werden.

    Tja, aber deswegen muss man den String nicht säubern,

    sscanf(text,"%f%f%f%f%f%f",...)
    

    läuft sowohl für

    "-0.5 0.5 0.5   \n\t-0.5 -0.5 0.5\n\t\t"
    

    wie auch für

    "-0.5 0.5 0.5 -0.5 -0.5 0.5"
    

    gleichermaßen.


Anmelden zum Antworten