Lexikographische Sortierung



  • DocShoe schrieb:

    Nö, ich meine stricmp, das ist sowohl ANSI-C als auch ANSI-C++ Standard.

    Hab nochmal drüber nachgedacht. Hast du einen Nachweis dafür bzw. in welchem Paper steht das?



  • Nun? Doc?

    Nach kurzer Recherche denke ich deine Aussage bezüglich stricmp() ist nicht zu halten. Das Ding gehört nicht zum Standard. Trotzdem würde es lil_pingu die Arbeit abnehmen, das zumindest ist gewiss.:)



  • Und unter Linux/gcc heißt die Funktion dann strcasecmp() (http://linux.die.net/man/3/strcasecmp).

    Leider ist stricmp/strcasecmp aber kein Standard (auch nicht mit Unterstrich).



  • So, hab nun das Problem gelöst.

    //zeichenlesen.cpp
    #include <cstdio>
    #include <cstring>
    #include <cctype>
    
    int main(){
    	const int n = 5;	
    	char eingabe[n][10];
    
    	for(int i = 0; i < n; i++){
    		printf("Bitte geben Sie das %i.te Wort ein: ",i+1);
    		scanf("%s",eingabe[i]);
    	}
    
    	printf("\nSie haben folgende Wörter eingegeben: \n");
    	printf("[");
    	for(int i = 0; i < n; i++){
    		printf("%s",eingabe[i]);
    		if(i != n-1)printf(", ");
    		else printf("]\n");
    	}
    
    	//lexikalische Sortierung
    	char tmp[10];
    	char s1[10];
    	char s2[10];
    	int x = n;
    	do{
    		for(int i = 0; i < n-1; i++){
    			strcpy(s1,eingabe[i]);
    			strcpy(s2,eingabe[i+1]);			
    
    			//alles in Großbuchstaben umformen
    			for(int k = 0; s1[k] != '\0'; ++k) 
    				s1[k] = (char)toupper(s1[k]);
    			for(int k = 0; s1[k] != '\0'; ++k) 
    				s2[k] = (char)toupper(s2[k]);
    
    			if(strcmp(s1, s2) > 0){
    				strcpy(tmp,eingabe[i]);
    				strcpy(eingabe[i],eingabe[i+1]);
    				strcpy(eingabe[i+1],tmp);
    			}
    		}
    	} while(x--);
    
    	//lexikographisch sortierte Ausgabe
    	printf("\nLexikographisch sortiert:\n");
    	for(int j = 0; j < n; j++) printf("%s\n",eingabe[j]);
    
    	return 0;
    }
    
    Bitte geben Sie das 1.te Wort ein: Zickzack
    Bitte geben Sie das 2.te Wort ein: X-Men
    Bitte geben Sie das 3.te Wort ein: Mama
    Bitte geben Sie das 4.te Wort ein: Hiho
    Bitte geben Sie das 5.te Wort ein: jura
    
    Sie haben folgende Wörter eingegeben: 
    [Zickzack, X-Men, Mama, Hiho, jura]
    
    Lexikographisch sortiert:
    Hiho
    jura
    Mama
    X-Men
    Zickzack
    

    Hab heute übrigens mit meinem Prof geredet und gesagt, dass es mich verdammt stört, dass wir darauf ausdrücklich hingewiesen werden, alles C-like zu machen. Hab ihm gesagt, wie schnell die Lösung mit <string> und <vector> gehen würde. Er meinte, wir sollen das so machen, um uns mit C-Strings vertraut zu machen (was ich einerseits verstehen kann, denn das ist wirklich etwas schwieriger als string). Aber trotzdem ist es nicht gut, streams, stl, usw nicht richtig zu erklären. Als er heute kurz mal eine cout-Ausgabe (mit Namespace-Prefix) zeigte, wurden alle ganz panisch...Als ich damals für ein Praktikum C++ lernen musste, habe ich mich auch tagelang damit rumgequält, die STL zu verstehen, weil meine C++-Lektüre auch im C-Stil war...hab dann im Forum um Rat gebeten und man hat mir die beiden Vols von "Thinking in C++" empfohlen. Die sind wirklich genial! 🙂



  • *räusper* *hüstel*

    //...
    for(int k = 0; s1[k] != '\0'; ++k)
        s1[k] = (char)toupper(s1[k]);
    
    for(int k = 0; s1[k] != '\0'; ++k) // !!!!!!!!!!
        s2[k] = (char)toupper(s2[k]);
    //...
    


  • Mitleid schrieb:

    *räusper* *hüstel*

    //...
    for(int k = 0; s1[k] != '\0'; ++k)
        s1[k] = (char)toupper(s1[k]);
    
    for(int k = 0; s1[k] != '\0'; ++k) // !!!!!!!!!!
        s2[k] = (char)toupper(s2[k]);
    //...
    

    Was ist damit? Es hat bei mir nicht rumgemeckert...



  • lil_pingu schrieb:

    Mitleid schrieb:

    *räusper* *hüstel*

    //...
    for(int k = 0; s1[k] != '\0'; ++k)
        s1[k] = (char)toupper(s1[k]);
    
    for(int k = 0; s1[k] != '\0'; ++k) // !!!!!!!!!!
        s2[k] = (char)toupper(s2[k]);
    //...
    

    Was ist damit? Es hat bei mir nicht rumgemeckert...

    gucks doch noch mal an... 😛



  • 😮 😮 😮 oje, ich sehs. In der zweiten for-Schleife muss s2[k] != ... stehen...Danke für den Hinweis 👍 😋



  • Muhaha, sehr witzig hier Leute schreiben zu sehen, mit denen ich zusammen diesen C++ Kurs gerade mache. Ich habe diese Aufgabe auch bearbeitet, aber auf vorgefertigte Funktionen zu Übungszwecken verzichtet. Ich bin übrigens der Meinung, dass die starke C-Orientierung im Kurs viel Sinn macht. Die Grundlagen müssen zuerst sitzen, dann kann man auch gerne zur STL greifen.

    #include <cstdio>
    
    int strlen(const char * string)
    {
    	for(int i = 0;; ++i)
    	{
    		if(string[i] == '\n' || string[i] == '\0')
    		{
    			return i;
    		}
    	}
    }
    
    // Alphabetischer Char Vergleich: a > b -> 1 / a < b = -1 / a == b = 0
    // Zahlen und Sonderzeichen sind kleiner als Buchstaben
    int cmp(char a, char b)
    {
    	bool a_letter = false;
    	bool b_letter = false;
    
    	// Gross -> Klein
    	if(a < 91 && a > 64)
    	{
    		a += 32; a_letter = true;
    	}
    	if(a < 123 && a > 96)
    		a_letter = true;
    
    	if(b < 91 && a > 64)
    	{
    		b += 32; b_letter = true;
    	}
    	else if(b < 123 && b > 96)
    		b_letter = true;
    
    	if(a_letter && b_letter)
    	{
    		if(a > b) return 1;
    		else if(a == b) return 0;
    		else return -1;
    	}
    	else if(a_letter && !b_letter)
    		return 1;
    	else if(!a_letter && b_letter)
    		return -1;
    	else
    	{
    		if(a == b) return 0;
    		return (a > b) ? 1 : -1;
    	}
    }
    
    // Char[] Vergleich: a > b -> true
    bool strcmp(char * a, char * b)
    {
    	int compare;
    	int la = strlen(a);
    	int lb = strlen(b);
    	int l = (la > lb) ? lb : la;
    
    	for(int i = 0; i < l; ++i)
    	{
    		compare = cmp(a[i], b[i]);
    		if(compare == 1)
    		{
    			return true;
    		}
    		else if(compare == -1)
    		{
    			return false;
    		}
    	}
    
    	return (lb <= la) ? true : false;
    }
    
    int partition(int links, int rechts, char ** words)
    {
    	char * tmp;
        int i = links; 
        int j = rechts - 1;
    
    	do
    	{
    		while(strcmp(words[rechts], words[i]) && i < rechts) i++; 
    		while(strcmp(words[j], words[rechts]) && j > links) j--;
    
    		if(i < j)
    		{
    			tmp  = words[i];
    			words[i] = words[j];
    			words[j] = tmp;
    			j--;
    			i++;
    		}
    	}
    	while(i < j);
    
    	if(strcmp(words[i],words[rechts]))
    	{
    		tmp  = words[i];
    		words[i] = words[rechts];
    		words[rechts] = tmp;
    	}
    
    	return i;
    }
    
    void qsort(int links, int rechts, char ** words)
    {
    	if(links < rechts)
    	{
             int teiler = partition(links, rechts, words);
             qsort(links, teiler-1, words);
    		 qsort(teiler+1, rechts, words);
    	}
    }
    
    int main()
    {
    	int n = 8;
    	int i;
    	char ** words = new char*[n];
    
    	for(i = 0; i < n; ++i)
    	{
    		words[i] = new char[20];
    	}
    
    	for(i = 0; i < n; ++i)
    	{
            printf("Bitte geben Sie das %i. Wort ein: ",i+1);
            if(fgets(words[i], 20, stdin) == NULL)
    		{
    			printf("Fehler beim Einlesen!\n");
    			return 1;
    		}
        }
    
    	qsort(0, (n-1), words);
    
    	printf("Lexikografische Ausgabe:\n");
    	for(i = 0; i < n; i++)
    	{
    		printf("%s",words[i]);
    		delete words[i];
    	}
    
    	delete words;
    }
    


  • Ich bin übrigens der Meinung, dass die starke C-Orientierung im Kurs viel Sinn macht.

    Die Diskussion hatten wir hier schon ca. 82938mal - es gibt da wohl mehrere ansichten - ich weiß allerdings nicht, wieso man als C++ Anfänger char*-gefrickel vor std::string erlernen sollte...

    Michamab schrieb:

    Ich habe diese Aufgabe auch bearbeitet, aber auf vorgefertigte Funktionen zu Übungszwecken verzichtet.

    auch hier lässt sich über den Sinn streiten - allerdings ist es zumindest nicht unnötig...

    Die Grundlagen müssen zuerst sitzen, dann kann man auch gerne zur STL greifen.

    siehe 1.

    int strlen(const char * string)
    {
    	for(int i = 0;; ++i)
    	{
    		if(string[i] == '\n' || string[i] == '\0')
    		{
    			return i;
    		}
    	}
    }
    

    '\n' hat nichts darüber auszusagen, ob ein string zu ende ist...
    Bsp.: "Hallo\r\nWelt!"

    richtiger wäre:

    int strlen(const char *str)
    {
      int R;
    
      for(R = 0; str[R] != '\0'; ++R)
        ;
    
      return R;
    }
    

    (nebenbemerkung:
    nur ist es in C++ nicht üblich, int für einen zähler zu nutzen - hier nimmt man std::size_t:

    size_t strlen(const char *str)
    {
      size_t R(0);
    
      if(str[R] != '\0')
        return R;
    
      while(str[++R] != '\0')
        ;
    
      return R;
    }
    

    hab auch keine ahnung, ob es was gebracht hat, das for mit dem if+while zu ersetzen)

    warum es nicht sonderlich klug ist, auf vorgefertigte fkt zu verzichten wird auch hier wieder klar: es muss eben nicht immer funktionieren... es wird zwar auf PCs funktionieren, aber ist nicht festgeschrieben, dass a..z direkt nacheinander kommen - auch bei A..Z nicht.
    normalerweise müsste man das wohl mit riesen switch-blöcken machen müssen...
    schrecklich ist vor allem, dass du die ascii-werte nimmst - völlig unnötig...

    char is_letter(char character)
    {
      return is_lower(character) || is_upper(character);
    }
    
    bool is_lower(char buchstabe)
    {
      return buchstabe >= 'a' && buchstabe <= 'z';
    }
    
    bool is_upper(char buchstabe)
    {
      return buchstabe >= 'A' && buchstabe <= 'Z';
    }
    
    char to_lower(char buchstabe)
    {
      if(is_lower(buchstabe))
        return buchstabe;
    
      return buchstabe-'A'+'a';
    }
    
    // Alphabetischer Char Vergleich: a > b -> 1 / a < b = -1 / a == b = 0
    // Zahlen und Sonderzeichen sind kleiner als Buchstaben
    int cmp(char a, char b)
    {
      if(is_letter(a) && is_letter(b))
      {
        a = to_lower(a);
        b = to_lower(b);
        if(a == b)
          return 0;
        return a > b ? 1 : -1;
      }
    
      if(!is_letter(b))
      {
        if(is_letter(a))
          return 1;
    
        if(a == b)
          return 0;
        return a > b ? 1: -1;
      }
    
      return -1; //bleibt nur noch !is_letter(a) && is_letter(b) übrig
    }
    

    bool strcmp(char * a, char * b)
    wie wärs mit
    bool strcmp(const char *a, const char *b) ?
    oben hast du doch auch noch const char* genommen und nicht char*...

    // Char[] Vergleich: a > b -> true
    bool strcmp(const char *a, const char *b)
    {
      for(int i(0), e(strlen(a)); i != e; ++i)
      {
        bool same( cmp(a++, b++) == 0 );
        if(!same)
          return false;
      }
    
      return true;
    }
    

    zu mehr hab ich gerade keine lust - vll kommt später noch mehr^^

    man könnte auch noch mehr auslagern - z.bsp. eine fkt:

    bool is_delimiter(char x)
    {
      return x == '\0';
    }
    

    bei strlen verwenden.
    bei strcmp könnte man dann auch auf das strlen verzichten und die fkt nehmen...
    man könnte auch jz schon auf strlen verzichten, aber hässlich, wie ich finde^^
    ich will in nem strcmp nicht unbedingt selbst auf '\0' testen sondern wenn ich teste, will ich die '\0' dort weghaben...

    bb



  • unskilled schrieb:

    Ich bin übrigens der Meinung, dass die starke C-Orientierung im Kurs viel Sinn macht.

    Die Diskussion hatten wir hier schon ca. 82938mal - es gibt da wohl mehrere ansichten - ich weiß allerdings nicht, wieso man als C++ Anfänger char*-gefrickel vor std::string erlernen sollte...

    Damit er keine häßliche Kacke baut.

    Um genau zu sein, damit

    unskilled schrieb:

    // Char[] Vergleich: a > b -> true
    bool strcmp(const char *a, const char *b)
    {
      for(int i(0), e(strlen(a)); i != e; ++i)
      {
        bool same( cmp(a++, b++) == 0 );
        if(!same)
          return false;
      }
    
      return true;
    }
    

    sowas nicht passiert. Boah, ey, ist das häßlich!



  • volkard schrieb:

    unskilled schrieb:

    Ich bin übrigens der Meinung, dass die starke C-Orientierung im Kurs viel Sinn macht.

    Die Diskussion hatten wir hier schon ca. 82938mal - es gibt da wohl mehrere ansichten - ich weiß allerdings nicht, wieso man als C++ Anfänger char*-gefrickel vor std::string erlernen sollte...

    Damit er keine häßliche Kacke baut.

    Um genau zu sein, damit

    unskilled schrieb:

    // Char[] Vergleich: a > b -> true
    bool strcmp(const char *a, const char *b)
    {
      for(int i(0), e(strlen(a)); i != e; ++i)
      {
        bool same( cmp(a++, b++) == 0 );
        if(!same)
          return false;
      }
    
      return true;
    }
    

    sowas nicht passiert. Boah, ey, ist das häßlich!

    tz 😕
    wie sähe denn deine variante aus? Oo

    mir ist auch gerad aufgefallen, dass die fkt falsch ist - macht zwar das, wonach sie klingt, aber sie soll eben was anderes tun ^^

    bool smaller(const char *lhs, const char *rhs)
    {
      int compare(-1);
    
      for(int i(0), e(strlen(lhs)); i != e; ++i)
      {
        compare = cmp(lhs++, rhs++);
    
        if(compare != 0)
          break;
      }
    
      return compare < 0;
    }
    

    bb



  • unskilled schrieb:

    size_t strlen(const char *str)
    {
      size_t R(0);
    
      if(str[R] != '\0')
        return R;
    
      while(str[++R] != '\0')
        ;
    
      return R;
    }
    

    hab auch keine ahnung, ob es was gebracht hat, das for mit dem if+while zu ersetzen)

    while ist hier natürlich das mittel der wahl. verloren hast du, als du [++R] geschrieben hast, statt die dinge getrennt zu behandeln. wozu machst du sowas bloß?

    size_t strlen(const char *str)
    {
      size_t R=0;
      while(str[R]!='\0')
        ++R;
      return R;
    }
    
    // Alphabetischer Char Vergleich: a > b -> 1 / a < b = -1 / a == b = 0
    // Zahlen und Sonderzeichen sind kleiner als Buchstaben
    int cmp(char a, char b)
    {
      if(is_letter(a) && is_letter(b))
      {
        a = to_lower(a);
        b = to_lower(b);
        if(a == b)
          return 0;
        return a > b ? 1 : -1;
      }
    
      if(!is_letter(b))
      {
        if(is_letter(a))
          return 1;
    
        if(a == b)
          return 0;
        return a > b ? 1: -1;
      }
    
      return -1; //bleibt nur noch !is_letter(a) && is_letter(b) übrig
    }
    

    Augenkrebs.

    // Alphabetischer Char Vergleich: a>b -> result>0 / a<b -> result<0 / a==b -> result==0
    // Zahlen und Sonderzeichen sind kleiner als Buchstaben
    int cmp(char a, char b)
    {
      static_assert(mal sicherstellen, daß 256 reicht)
      if(is_letter(a))
        a=to_lower(a)+256;
      if(is_letter(b))
        b=to_lower(b)+256;
      return a-b;
    }
    


  • unskilled schrieb:

    wie sähe denn deine variante aus? Oo

    bool smaller(const char *lhs, const char *rhs)
    {
      int compare(-1);
    
      for(int i(0), e(strlen(lhs)); i != e; ++i)
      {
        compare = cmp(lhs++, rhs++);
    
        if(compare != 0)
          break;
      }
    
      return compare < 0;
    }
    

    Naja, das strlen muß vor allem da oben raus. Aber das geht ja schnell. Vielleicht so

    bool smaller(const char *lhs, const char *rhs)
    {
      int compare(-1);
    
    //  for(int i(0), e(strlen(lhs)); i != e; ++i)
      while(*lhs!='\0')
      {
        compare = cmp(lhs++, rhs++);
    
        if(compare != 0)
          break;
      }
    
      return compare < 0;
    }
    

    Und dann vielleicht die Tatsachen dahin tragen, wo sie entstehen.

    bool smaller(const char *lhs, const char *rhs)
    {
    //  for(int i(0), e(strlen(lhs)); i != e; ++i)
      while(*lhs!='\0')
      {
        int compare = cmp(lhs++, rhs++);
    
        if(compare != 0)
          return compare < 0;
      }
    
      return true;
    }
    

    Ups, ich dachte, ich hätte Deinen Code nur umgesetzt, ohne die Bedeutung zu ändern. War wohl nicht der Fall. Denn hier sieht man, daß er bei zwei leeren strings true returnt. Und bei gleichen Strings auch.

    Na, ist ja schnell repariert.

    bool smaller(const char *lhs, const char *rhs)
    {
      while(*lhs!='\0')
      {
        int compare = cmp(lhs, rhs);
        if(compare != 0)
          return compare < 0;
        ++lhs;
        ++rhs;
      }
      return *rhs!='\0';
    }
    

    komisch. ich müßte mal compare in die laufbedingung machen und innen auf *left==0 testen.



  • volkard schrieb:

    unskilled schrieb:

    size_t strlen(const char *str)
    {
      size_t R(0);
    
      if(str[R] != '\0')
        return R;
    
      while(str[++R] != '\0')
        ;
    
      return R;
    }
    

    hab auch keine ahnung, ob es was gebracht hat, das for mit dem if+while zu ersetzen)

    while ist hier natürlich das mittel der wahl. verloren hast du, als du [++R] geschrieben hast, statt die dinge getrennt zu behandeln. wozu machst du sowas bloß?

    size_t strlen(const char *str)
    {
      size_t R=0;
      while(str[R]!='\0')
        ++R;
      return R;
    }
    

    hmm... jugendlicher leichtsinn 😉
    kA - iwie ists mir einfach nicht eingefallen 😃

    // Alphabetischer Char Vergleich: a > b -> 1 / a < b = -1 / a == b = 0
    // Zahlen und Sonderzeichen sind kleiner als Buchstaben
    int cmp(char a, char b)
    {
      if(is_letter(a) && is_letter(b))
      {
        a = to_lower(a);
        b = to_lower(b);
        if(a == b)
          return 0;
        return a > b ? 1 : -1;
      }
    
      if(!is_letter(b))
      {
        if(is_letter(a))
          return 1;
    
        if(a == b)
          return 0;
        return a > b ? 1: -1;
      }
    
      return -1; //bleibt nur noch !is_letter(a) && is_letter(b) übrig
    }
    

    Augenkrebs.

    // Alphabetischer Char Vergleich: a>b -> result>0 / a<b -> result<0 / a==b -> result==0
    // Zahlen und Sonderzeichen sind kleiner als Buchstaben
    int cmp(char a, char b)
    {
      static_assert(mal sicherstellen, daß 256 reicht)
      if(is_letter(a))
        a=to_lower(a)+256;
      if(is_letter(b))
        b=to_lower(b)+256;
      return a-b;
    }
    

    [/quote]
    hmm.. ich hatte auch drüber nachgedacht, das anders zu machen... aber mir ist 0 eingefallen...
    die idee find ich gut(und das es stimmt glaub ich einfach mal ;D) - allerdings ist char wahlweise unsigned oder signed - und wenn es signed ist, ist das verhalten bei einem überlauf nicht definiert, richtig!?
    also bräuchte man 2 tmp-ints!?

    bb



  • unskilled schrieb:

    allerdings ist char wahlweise unsigned oder signed - und wenn es signed ist, ist das verhalten bei einem überlauf nicht definiert, richtig!?
    also bräuchte man 2 tmp-ints!?

    Mir würde es besser gefallen, den Code nur für unsigend char zu definieren und die funktionen für signed char und für char sind nur wrapper für die funktion von unsigned char.
    sonst hat man auch die probs, daß je nach char-signedness mal þ<# und mal þ># ist.


  • Mod

    unskilled schrieb:

    volkard schrieb:

    // Alphabetischer Char Vergleich: a>b -> result>0 / a<b -> result<0 / a==b -> result==0
    // Zahlen und Sonderzeichen sind kleiner als Buchstaben
    int cmp(char x, char b)
    {
      static_assert(mal sicherstellen, daß 256 reicht)
      if(is_letter(a))
        a=to_lower(a)+256;
      if(is_letter(b))
        b=to_lower(b)+256;
      return a-b;
    }
    

    hmm.. ich hatte auch drüber nachgedacht, das anders zu machen... aber mir ist 0 eingefallen...
    die idee find ich gut(und das es stimmt glaub ich einfach mal ;D) - allerdings ist char wahlweise unsigned oder signed - und wenn es signed ist, ist das verhalten bei einem überlauf nicht definiert, richtig!?
    also bräuchte man 2 tmp-ints!?

    Ein Überlauf findet nicht statt, da bereits vor der Addition in int konvertiert wird. Allerdings bringt auch die Addition bei vorzeichenlosen 8-bit chars nichts, wenn wir das Ergebnis gleich wieder in diesen chars speichern.

    int sgn(int x)
    {
      return x <= 0 ? x < 0 ? -1 : 0 : 1;
    }
    // Alphabetischer Char Vergleich:
    // a<b -> -1
    // a==b -> 0
    // a>b -> 1
    // Zahlen und Sonderzeichen sind kleiner als Buchstaben
    int cmp(char a, char b)
    {
      if ( int x = is_letter(a) - is_letter(b) )
        return x;
      return sgn( to_lower(b) - to_lower(b) );
    }
    

    Die signed/unsigned-Frage halte ich für weniger relevant, da Zeichen des erweiterten Zeichensatzes - abgesehen von der locale-Abhängigkeit - so oder so nicht zwingend richtig einsortiert werden.



  • camper schrieb:

    ...
    

    👍
    Langsam kann man den Code hübsch nennen.



  • unskilled schrieb:

    Ich bin übrigens der Meinung, dass die starke C-Orientierung im Kurs viel Sinn macht.

    Die Diskussion hatten wir hier schon ca. 82938mal - es gibt da wohl mehrere ansichten - ich weiß allerdings nicht, wieso man als C++ Anfänger char*-gefrickel vor std::string erlernen sollte...

    Naja, du solltest halt den Kontext einbeziehen. In dem Kurs sitzen hauptsächlich Studierende der Informatik, die mindestens im 3. Semester sind. Die haben in der Regel schon Kenntnisse in mehreren Programmiersprachen und sind durchaus in der Lage sich irgendwelche fertigen Libarys anzuschauen und zu benutzen. Doch das bringt halt alles nichts, wenn die Grundlagen der Sprache nicht verstanden worden sind. Gerade Pointer/References (C-Strings sind hierzu doch ein gute Übungsmöglichkeit) sind häufige Fehlerquellen für Anfänger.

    unskilled schrieb:

    int strlen(const char * string)
    {
    	for(int i = 0;; ++i)
    	{
    		if(string[i] == '\n' || string[i] == '\0')
    		{
    			return i;
    		}
    	}
    }
    

    '\n' hat nichts darüber auszusagen, ob ein string zu ende ist...
    Bsp.: "Hallo\r\nWelt!"

    richtiger wäre:

    int strlen(const char *str)
    {
      int R;
    
      for(R = 0; str[R] != '\0'; ++R)
        ;
    
      return R;
    }
    

    Das der Zeilenumbruch einen String nicht beendet war mir bewusst. Die Aufgabenstellung war jedoch Wörter einzulesen, keine Sätze. Und beim Einlesen des String mit fgets() wird halt nunmal auch immer ein \n angehängt. Das wollte ich halt nicht mitzählen.

    unskilled schrieb:

    warum es nicht sonderlich klug ist, auf vorgefertigte fkt zu verzichten wird auch hier wieder klar: es muss eben nicht immer funktionieren... es wird zwar auf PCs funktionieren, aber ist nicht festgeschrieben, dass a..z direkt nacheinander kommen - auch bei A..Z nicht.
    normalerweise müsste man das wohl mit riesen switch-blöcken machen müssen...
    schrecklich ist vor allem, dass du die ascii-werte nimmst - völlig unnötig...

    Mir ist schon klar, dass in der Praxis vorgefertigte Funktionen sicherer und effizienter sind. Doch darum ging es hier ja garnicht, deshalb verstehe ich jetzt die Belehrungen auch nicht.

    Mir ist auch bewusst, dass mein Code nicht hübsch ist. Das war eine freiwillige Übungsaufgabe für mich, die ich nicht bis zur Perfektion verfolgt habe. Ich habe sie hier halt nur gepostet, weil jemand exakt das selbe machen musste und ein paar Anregungen vielleicht dabei waren.


Anmelden zum Antworten