Array of Char Arrays



  • Hallo,

    ich habe die Aufgabe in einem Array of Char arrays jedes Char array auf leerzeichen zu untersuchen und diese zu entfernen.Soweit bin ich nun:

    #include "stdafx.h"
    #include <stdio.h> 
    #include <stdlib.h> 
    #include <string.h> 
    
    int main() 
    { 
        char name[] = "a bb ccc d"; 
        char t[] = ""; 
    
        char *splitted = strtok(name," "); 
    
        while(splitted != NULL) 
        { 
    
            strcat(t,splitted); 
            splitted = strtok(NULL," "); 
    
        } 
        printf("%s",t); 
        return 0; 
    }
    

    Also ich weiß nicht genau wie man jetzt nun ein Array of Char Arrays daraus macht. Ein Char array habe ich nun.

    Sorry ich bin noch nicht allzu bewandert mit C++ also wäre ich über jede Hilfe sehr dankbar.

    LIeben Gruß



  • Dieser Thread wurde von Moderator/in SeppJ aus dem Forum C++ (auch C++0x und C++11) in das Forum C (C89, C99 und C11) verschoben.

    Im Zweifelsfall bitte auch folgende Hinweise beachten:
    C/C++ Forum :: FAQ - Sonstiges :: Wohin mit meiner Frage?

    Dieses Posting wurde automatisch erzeugt.



  • Also ich habe diesen schnipsel soweit von einem anderen Post. Meine Idee wäre jetzt so in der Art vorzugehen:

    #include "stdafx.h"
    #include <stdio.h> 
    #include <stdlib.h> 
    #include <string.h> 
    
    int main() 
    { 
        char *name[] = {"a bb ccc d","t e s t", "L e e r z e i c h en"; 
        char t[] = ""; 
      for(i=0;i<*name.length;i++){
        char *splitted = strtok(name[i]," "); 
    
        while(splitted != NULL) 
        { 
    
            strcat(t,splitted); 
            splitted = strtok(NULL," "); 
    
        } 
        printf("%s",t); 
        return 0; 
      }
    }
    


  • KonstiYo schrieb:

    #include "stdafx.h" /* Müll, raus damit */
    #include <stdio.h> 
    #include <stdlib.h> 
    #include <string.h> 
      
    int main() 
    { 
        char *name[] = {"a bb ccc d","t e s t", "L e e r z e i c h en"; /* kann niemals compilieren, es fehlt die schließende Klammer; definiert ein Array aus 3 Zeigern auf char, die aber UB bei Änderung bedeuten, also für dich hier falsch */
        char t[] = ""; 
      for(i=0;i<*name.length;i++){  /* was soll das hier? name versteht kein length */
        char *splitted = strtok(name[i]," "); 
      
        while(splitted != NULL) 
        { 
      
            strcat(t,splitted); 
            splitted = strtok(NULL," "); 
      
        } 
        printf("%s",t); 
        return 0; 
      }
    }
    

    Was soll "entfernen" bedeuten?
    Ein Array in C hat eine feste Größe, da kannst du nichts "entfernen".
    Außerdem ist bei dir die Rede von char-Arrays, du verwendest aber str* Funktionen, was in diesem Fall falsch ist.



  • char t[] = "";
    

    macht t zu einem char[1]. Da ist genau für ein Zeichen Platz drin (den Terminator). Wenn du später also hingehst und

    strcat(t,splitted);
    

    schreibst, schreibst du schon mehr in t rein, als da reinpasst. Das erzeugt undefiniertes Verhalten (in der Praxis wird halt der Kram überschrieben, der zufällig in der näheren Umgebung liegt), und von da an hast du ein großes Problem.

    Die Speicherbehandlung musst du von Hand machen. Es gibt mehrere Wege, da vorzugehen; so oder so ist das in C aber ziemliches Gefummel. Der kanonische Weg dürfte sein, ein dynamisch angefordertes Array von Zeigern auf dynamisch angeforderte Speicherbereiche zu halten, die dann die eigentlichen Strings enthalten. Dynamisch angefordert deshalb, weil du zur Compilezeit noch nicht weißt, um wieviele wie lange Strings es geht und MSVC (den du scheinbar benutzt) C99 nicht beherrscht. Grob sieht das so aus:

    int n;
    char **string_array = malloc(sizeof(char*) * length); // Platz für length Zeiger
    
    for(n = 0; n < length; ++n) {
      string_array[n] = _strdup("foo"); /* _strdup ist MSVC-spezifisch (in POSIX strdup); erzeugt eine Kopie eines Strings auf dem Heap.
                                         * Was passieren soll, wenn _strdup NULL zurückgibt, muss bedacht werden. */
    }
    
    /* Vergößerung des Bereichs nach diesem Muster: */
    char **tmp = realloc(string_array, sizeof(char*) * length * 2);
    if(tmp != NULL) {
      string_array = tmp;
    } else {
      /* Fehlerbehandlung hier. Freigabe nicht vergessen. */
      int i;
    
      for(i = 0; i < wieviele_strings_halt_schon_in_string_array_sind; ++i) {
        free(string_array[i]);
      }
      free(string_array);
    
      return NULL; /* Wenn du in einer Funktion bist, die einen Zeiger zurückgibt. Was hier sinnvoll wäre. */
    }
    

    Die Freigabe, die hier in der Fehlerbehandlung steht, muss nach Gebrauch auch passieren; es empfiehlt sich, sie in eine eigene Funktion auszulagern.

    Dieser Ansatz ist relativ straightforward, wenn man erstmal irgendwas haben will, aber ziemlich mühsam, wenn man eine ordentliche Fehlerbehandlung machen (also damit umgehen, dass malloc und realloc auch mal NULL zurückgeben können) will. Ich bin deshalb ein großer Freund davon, solche Dinge in einem von Hand verdrahteten Speicherblock zu machen, was etwa so aussieht:

    #include <stddef.h>
    #include <stdlib.h>
    #include <stdio.h>
    #include <string.h>
    
    typedef struct {
      size_t       size;
      char        *data[1]; /* Das Array ist nicht wirklich einen Zeiger breit; wir legen gleich noch ausreichend
                             * Speicherplatz dahinter, um es als ein längeres benutzen zu können. */
    } string_array;
    
    string_array *explode(char const *str, char const *delim) {
      string_array *result;
      size_t n = 0;
      size_t pos = strspn(str, delim);
      char *buffer;
    
      /* Vorher einmal drüberlaufen und Teilstrings zählen */
      while(str[pos]) {
        ++n;
        pos += strcspn(str + pos, delim);
        pos += strspn (str + pos, delim);
      }
    
      /* Genug Speicher für alles (also Zeigerarray und Daten, in die diese Zeiger
       * zeigen sollen) anfordern, String in den dafür vorgesehenen Bereich
       * kopieren, Länge setzen. pos ist an dieser Stelle strlen(str)
       */
      result = malloc(sizeof(string_array) + (n - 1) * sizeof(char*) + pos);
      if(!result) return NULL;
      result->size = n;
      buffer = (char*) (result->data + n);
      memcpy(buffer, str, pos);
    
      /* Und dann ein zweites mal über den String laufen, um diesen in die
       * Teilstrings zu zerlegen. */
      n = 0;
      pos = strspn(str, delim);
    
      while(str[pos]) {
        result->data[n++] = buffer + pos;
    
        pos += strcspn(str + pos, delim);
        buffer[pos] = '\0';
        pos += strspn (str + pos, delim);
      }
    
      return result;
    }
    
    int main(void) {
      unsigned n;
      string_array *arr = explode("  foo  bar baz  qux  ", " ");
    
      if(arr == NULL) {
        fputs("Fehler: Stringzerlegung fehlgeschlagen. Speicher voll?\n", stderr);
        return -1;
      }
    
      for(n = 0; n < arr->size; ++n) {
        printf("arr[%u] = \"%s\"\n", n, arr->data[n]);
      }
    
      free(arr);
    
      return 0;
    }
    

    Da nur einmal Speicher angefordert wird, kann die Anforderung nur einmal fehlschlagen und die Fehlerbehandlung beschränkt sich auf Zeile 30. Auch die Freigabe in Zeile 64 ist so schmerzfreier.

    Im Übrigen handelt es sich dabei nicht um C++, sondern um C. In C++ wäre das alles bedeutend einfacher, weil du einen std::vectorstd::string benutzen könntest und dich nicht selbst um die Speicherverwaltung kümmern müsstest.



  • Was soll das ganze?

    #include <stdio.h>
    #include <string.h>
    
    int main()
    {
    	char str[] = "In diesem Text sind einige   L e e r z e i c h e n  enthalten!";
    
    	int i;
    
    	for (i = 0; i < strlen(str); ++i)
    	{
    		if (str[i] == ' ')
    		{
    			int j;
    
    			for (j = i; j < strlen(str); ++j)
    			{
    				str[j] = str[j + 1];
    			}
    
    			--i;
    		}
    	}
    
    	printf("%s", str);
    }
    


  • Aber erkauft Ihr Euch damit nicht pöse quadratische Laufzeit?

    //Ah, endlich eine konsistente Weise gefunden, Leerzeichen zu setzen.
    //Immer Buchstabencluster und SOnderzeichencluster trennen. Das kann
    //Sogar ein Bot. Damit gehe ich bestimmt in die Gichichte ein.
    

    Ich würde nicht die Leerzeichen löschen, sondern die Nicht-Leerzeichen kopieren.

    #include <stdio.h>
    
    int main (){
        char str []= "In diesem Text sind einige   L e e r z e i c h e n  enthalten!" ;
    
        char * s ,* l ;
        for ( s = l = str ;*(* l != ' ' ? s ++: s )=* l ; l -=- 1 );
            printf ( "%s" , str );
    }
    


  • Erstmal danke für die ganzen Antworten ich hoffe ich komme nun etwas weiter.

    @ die fehlende } : ich bin hier nicht angemeldet also kann deshalb nicht editieren :S


Anmelden zum Antworten