Strings vergleichen und sortieren

Thomasio

Erfahrenes Mitglied
Ich brauche für verschiedene Sachen eine oder mehrere Funktionen, die std::strings vergleicht, etwa so wie das in PHP mit strnatcmp() und strnatcasecmp() funktioniert.
So dass strings alphabetisch sortiert, aber Zahlen im string als Zahlen behandelt werden.
Gibt es sowas in C++ oder wie kann man das am Einfachsten anstellen?
 
Für std::strings direkt wüsste ich da nichts. Mit Vektoren sortieren geht aber:

Es gibt die Möglichkeit mit sort() in #include <algorithm>
http://www.cplusplus.com/reference/algorithm/sort/
Damit kann man Vektoren sortieren. Ich glaube, ich habe noch ein Snipplet rumliegen... Hier:
C++:
std::vector<std::string> v;
sort( v.begin(),v.end(),std::less<std::string>());
Sortiert den Vektor alphabetisch, sodass du die Reihenfolge mit einem Iterator durchgehen kannst.

Was ich nicht verstanden habe ist folgendes:
So dass strings alphabetisch sortiert, aber Zahlen im string als Zahlen behandelt werden.
Du möchtest nicht, dass strings mit Zahlen sortiert werden? Oder was möchtest du?

Gruss
cwriter
 
Danke für die Antworten.

std::string MyString1 = "Irgendwas 10 Sonstwas";
std::string MyString2 = "Irgendwas 9 Sonstwas";

Ich möchte, dass beim alphabetischen Vergleich der beiden Strings MyString2 kleiner als MyString1 erkannt wird.

Das natsort Projekt schaue ich mir noch näher an.
 
Hallo

Ich muss zugeben, dass es mich gereizt hat. Und deshalb habe ich gleich einmal versucht, so einen Code zu schreiben. Fehler können da sein, müssen aber nicht. Code:
C++:
#include <stdio.h>
#include <stdlib.h>
#include <string>
#include <string.h>
#include <algorithm>
#include <vector>

#define MAXLEN 100	//eigenen Wert angeben

int main(int argc, char* argv[])
{
	std::string MyString1 = "Irgendwas 10 Sonstwas";
	std::string MyString2 = "Irgendwas 9 Sonstwas";
	std::vector<std::string> v;
	std::vector<std::string> v2;	//Brauchen wir später noch
	std::vector<std::string>::iterator i;
	
	v.push_back(MyString1);
	v.push_back(MyString2);
	v.push_back("MyTest und nochwas");	//Hier beachten: Es wird nur bis 100 geprüft (siehe defines)
	
	i = v.begin();
	while(i != v.end())
	{
		printf("%s\n",i->c_str());
		++i;
	}
	printf("\nNun sortiert:\n");
	sort( v.begin(),v.end(),std::less<std::string>());
	
	i = v.begin();
	while(i != v.end())
	{
		printf("%s\n",i->c_str());
		++i;
	}
	printf("\nJetzt sind die Nummern noch nicht geordnet... Machen wir mal:\n");
	i = v.begin();
begin:
	while(i != v.end())
	{
		//Sorry für die C-Funktionen, aber die beherrsche ich besser als C++
		char temp[1024];
		strcpy(temp,i->c_str());
		char Zahl[10];	//Mehr als zehnstelig sollte die Zahl wohl nicht sein...
		int ii = 0;
		int ziffern = 0;
		while(!isdigit(temp[ii]))
		{
			if(temp[ii] == '\0')
			{
				//damit die Einträge ohne Zahlen nicht benachteiligt sind:
				v2.push_back(temp);
				++i;
				goto begin;
			}
			ii++;
		}
		Zahl[0] = temp[ii];
		while(isdigit(temp[ii]))
		{
			Zahl[ziffern] = temp[ii];
			ziffern++;
			ii++;
		}
		Zahl[ziffern] = '\0';
		printf("%s hat folgende Zahl: %s\n",i->c_str(),Zahl);
		char fuerV2[512];
		sprintf(fuerV2,"%s|%s!",Zahl,i->c_str());	// | = Beginn des strings, ! = Ende des Strings
		v2.push_back(fuerV2);
		//Wir leeren wieder
		Zahl[0] = '\0';
		++i;
	}
	printf("\nDas Ganze kann man jetzt nutzen:\n");
	sort( v2.begin(),v2.end(),std::less<std::string>());
	
	std::vector<std::string> v3;	//Sollte der letzte sein :-)
	int ii = 0;
	while(ii != MAXLEN + 1)
	{
		i = v2.begin();
		while(i != v2.end())
		{
			char t[512];	//Wieder ein buffer
			strcpy(t,i->c_str());
			if(strstr(t,"|") == NULL || strstr(t,"!") == NULL) {++i;continue;}
			char* pch = strtok(t,"|");
			if(pch == NULL) {++i; continue;}
			if(ii == atoi(pch))
			{
				pch = strtok(NULL,"!");
				if(pch == NULL)	//da stimmt was nicht...
				{
					perror("Falsches Format");
					return -1;
				}
				v3.push_back(pch);
				i->erase();		//Damit es keine Doppeltreffer gibt
			}
			++i;
		}
		ii++;
	}
	//Der Rest in v2 ist jetzt ohne Zahlen. Holen wir die Dinge ab:
	i = v2.begin();
	while(i != v2.end())
	{
		char t[512];
		strcpy(t,i->c_str());
		if(isalnum(t[0])) v3.push_back(t);
		++i;
	}
	i = v3.begin();
	while(i != v3.end())
	{
		printf("%s\n",i->c_str());
		++i;
	}
	printf("\nEndlich fertig!\n");
	system("PAUSE");
	return 0;
}
Ausgabe:
Code:
Irgendwas 10 Sonstwas
Irgendwas 9 Sonstwas
MyTest und nochwas

Nun sortiert:
Irgendwas 10 Sonstwas
Irgendwas 9 Sonstwas
MyTest und nochwas

Jetzt sind die Nummern noch nicht geordnet... Machen wir mal:
Irgendwas 10 Sonstwas hat folgende Zahl: 10
Irgendwas 9 Sonstwas hat folgende Zahl: 9

Das Ganze kann man jetzt nutzen:
Irgendwas 9 Sonstwas
Irgendwas 10 Sonstwas
MyTest und nochwas

Endlich fertig!
Drücken Sie eine beliebige Taste . . .

Mit freundlichen Grüssen
cwriter
 
Kein Problem, macht mir ja auch Freude :)
Aber freu dich nicht zu früh - ich habe eine "einzigartige" Art zu programmieren ;-)

Zudem ist es nur für einige Dinge geeignet; möglicherweise solltest du das Programm modifizieren, damit es am besten passt.


cwriter
 
Keine Sorge, ich schreibe vermutlich noch viel eigenartiger als du, das bastele ich mir schon zurecht.
Portabel muss es nicht sein, ich brauche das nur in einer einzelnen Anwendung, und es reicht (fürs Erste) völlig wenn es dort geht.
 
Ah, portabel sollte es sein - ist mit Standard-C++-Mitteln gebastelt.
Achja, was noch ein Problem ist: Geordnet wird bei dem Programm zuerst die Einträge, die Zahlen beinhalten, und das nur nach Zahlen. Dann kommen die Einträge ohne Zahlen, die dann alphabetisch geordnet werden. Ich schaue mal, ob ich noch eine andere Lösung finde...

cwriter
 
Willst eine Aufgabe dazu?
Versuchs mal mit diesen strings

aaa 123 aaa
aba 99 aaa
aaa 09 aaa
aaa aaa
xyz xyz 10
xyz xyz 9
xyz 10 xyz
xyz 9 xyz
xyz xyz

Sortiert sollten das ergeben:

aaa 09 aaa
aaa 123 aaa
aaa aaa
aba 99 aaa
xyz 9 xyz
xyz 10 xyz
xyz xyz
xyz xyz 9
xyz xyz 10

Willst es richtig schwierig machen? Dann vielleicht noch case insensitive, sprich A = a.
Willst es übertreiben? Dann das Ganze für UNICODE, sprich wstring.

ÄÖÜ߀ 3³ äöüß
äöü߀ 4² ÄÖÜß

Das brauche ich nicht wirklich, aber ich hatte den Eindruck du suchst eine Herausforderung. :D
 
Zurück