Moni65: Parser kann wegen einem Leerzeichen einen Wert nicht finden

Beitrag lesen

Hallo liebes Forum, Ich habe ein hoffentlich kleines Problem und ich hoffe auch das ich hier richtig bin und zwar geht es um folgendes:

ich habe es (nach 2 Jahren und ohne Kenntnisse im coden) endlich geschafft, ein altes Programm neu zu kompillieren. nun konnte ich den eingebauten Parser, dahingehend ändern, das er eine Chatlog Datei in englisch, anstatt wie ursprünglisch in deutsch ausliest, was nun auch funktioniert. Allerdings hakt es noch an einem einzigen Wort und ich habe auch herausgefunden wieso es liegt an einem blöden Leerzeichen.

leider weiss ich nicht, ob ich nun im code oder in der xml datei suchen muss, bzw was ich machen muss. es wäre sehr nett, wenn sich hier jemand das folgende einmal ansieht

das hier soll er lesen, aber er findet es nicht wegen dem Leerzeichen zwischen Darkness und Focus - Darkness Focus: 50 lvls

und das liest er, denn das "-" ist auch in der original Version dazwischen. - Darkness-Focus: 50 lvls

so steht es in der xml.config Datei


CChatLog::CChatLog()
{
	fChatLog = NULL;
	arItemNames =  new TStringList;
};

CChatLog::~CChatLog()
{
	CloseChatLog();
	delete arItemNames;
};

// Öffnet die ChatLog-Datei für Lesezugriff
int CChatLog::OpenChatLog(const char* Filename)
{
	if (fChatLog != NULL) delete fChatLog;
	// Seek funktioniert nur richtig im binary-mode. Nur ist jetzt immer /r hinter einem String
	fChatLog = new fstream(Filename, ios_base::in | ios_base::binary);
	iLineNo = 0;
	if (fChatLog->is_open()) return true;
	else return false;
};

void CChatLog::CloseChatLog()
{
	if (fChatLog != NULL)
	{
		fChatLog->close();
		delete fChatLog;
	}
	fChatLog = NULL;
};

// enumwerte des Parsers in Init
enum ParserStateInit
{
	STATE_START,	// Scanne nach Start einer Info-Section
	STATE_ITEM,	// Suche danach in der Sektion, das es ein Gegenstand ist
};

// Diese Funktion scannt erstmal das gesamte Log nach Gegenständen und merkt
// sich deren Position. In einem zweiten durchlauf wird versucht, die Herkunft
// der Gegenstände herauszubekommen. Doppelte Items werden herausgefiltert
void CChatLog::Init(void)
{
	int posStart;	// Startposition des aktuellen Info-Bereichs
	AnsiString strName;	// Name des aktuellen Info-Bereichs
	char Line[1024];	// Hier eine maximale Länge eines Textes heruasfinden
	bool bIsItem;

	nItems = 0;
	iLineNo = 0;
	arItemNames->Clear();
	arOffsets.Length = 0;
	ParserStateInit State = STATE_START;
	fChatLog->seekg(0, ios::beg);	// Lesezeiger auf Dateianfang
	fChatLog->getline(Line, 1024);
	while(!fChatLog->eof())
	{
		assert(StrLen(Line) < 1024);
		iLineNo++;
		switch (State)
		{
		case STATE_START:
			{	// Suche nach dem Start eines Info-Bereichs
				char *pStart = AnsiStrPos(Line, (char*)strInfoStart);
				if (pStart != NULL)
				{
					posStart = fChatLog->tellg() - fChatLog->gcount();
					AnsiString sTemp = pStart;
					strName = sTemp.SubString(sizeof(strInfoStart) + 1, StrLen(pStart) - sizeof(strInfoStart)- 2);
					// Jetzt mal schauen, ob es einen Doppelpunkt gibt.
					int p = strName.AnsiPos(':');
					if (p > 0)
					{	// Wenn ja, dann den String bis dorthin abschneiden
						strName = strName.SubString(p + 2, strName.Length() - p - 1);
					}
					bIsItem = false;
					State = STATE_ITEM;
				}
			}
			break;
		case STATE_ITEM:
			{	// Suche nach Magieboni oder Info-Sektion Ende
				char *pStart = AnsiStrPos(Line, (char*)strMagBoniStart);
				if (pStart != NULL) bIsItem = true;
				// Ist Info-Sektion zu Ende?
				pStart = AnsiStrPos(Line, (char*)strInfoStop);
				if (pStart != NULL)
				{
					State = STATE_START;	// Nach der nächsten Info-Sektion suchen
					if (bIsItem)
					{	// Ende Info-Sektion und es ist ein Gegenstand
						// Also in die Liste der zu untersuchenden Gegenstände aufnehmen
						int index;
						if ((index = arItemNames->IndexOf(strName)) == -1)
						{	// Item mit diesem Namen gibts noch nicht (im Logfile)
							arItemNames->Add(strName);
							arOffsets.Length = nItems + 1;
							arOffsets[nItems] = posStart;
							nItems++;
						}
						else
						{	// Name gibts schon. Offset aber auf diesen setzen,
							// da immer das letzte das aktuellste sein sollte
							arOffsets[index] = posStart;
						}
					}
				}
			}
			break;
		}

		fChatLog->getline(Line, 1024);
	}
}

// Diese Funktion macht die eigentliche Lesearbeit
// Input ist dabei der Index des zu beschaffenden Items und einen Zeiger
// auf eine CItem-Klasse, welche ausgefüllt werden soll
// Rückgabe ist true für keinen Fehler
int CChatLog::GetItem(int index, CItem* Item)
{
	unsigned int i;
	char Line[1024];	// Hier eine maximale Länge eines Textes heruasfinden
	char sArg[64];	// Längere Bonusbezeichnungen gibts glaub nicht
	int NextBonus = 0;	// Welche Position soll der nächste Bonus eingetragen werden
	int NextRestriction = 0;	// Nächster Index einer Klassenbeschränkung
	bool bRestriction = false;

	if ((index < 0) && (index >= nItems)) return false;	// Itemindex nicht im gültigen Bereich
	Item->Init();
	Item->Name = arItemNames->Strings[index];
	Item->Realm = player->Realm;	// Immer Realm des Spielers annehmen
	Item->Quality = 0;
	// Versuche Aufgrund des Namen auf den Itemslot zu schliessen
	AnsiString strTemp = Item->Name.LowerCase();
	for (i = 0; i < 18; i++)
	{
		for (int j = 0; j < xml_config.arItemSlots[i].arIds.Length; j++)
		{
			if (strTemp.AnsiPos(xml_config.arItemSlots[i].arIds[j]) > 0)
				Item->Position = i;
		}
	}
	// Lesezeiger auf Beginn der entsprechenden Info-Sektion stellen
	fChatLog->clear();	// Ist nötig, da wir eventuell noch im eof-state sind
	fChatLog->seekg(arOffsets[index], ios::beg);
	fChatLog->getline(Line, 1024);	// Erste Zeile Lesen (kann ignoriert werden)
	fChatLog->getline(Line, 1024);	// Erste Zeile mit Infos
	while(!fChatLog->eof())
	{
		assert(StrLen(Line) < 1024);
		int Value = 0;
		// Ist Info-Sektion zu Ende?
		char	*pStart = AnsiStrPos(Line, (char*)strInfoStop);
		if (pStart!= NULL) break;
		if (Line[11] == '-')
		{	// Alles danach ist ein Wert, der mich interessiert
			// Suche erstmal nach einem Zahlenwert. Sollte immer nur einer sein
			// Bonus-Argument ist immer der String vor einem Doppelpunkt,
			// oder der String hinter einer Zahl
			bool bValue = false;	// Gibts eine Zahl?
			bool bDoppel = false;	// gibt es einen Doppelpunkt im String
			bool bPercent = false;	// Es ist ein Prozent-Wert
			int pArg = 0;	// Aktuelle Position im Argument-String
			for (i = 13; i < StrLen(Line); i++)
			{
				if ((Line[i] >= '0') && (Line[i] <= '9'))
				{
					bValue = true;
					Value = Value * 10 + Line[i] - '0';
				}
				else if (Line[i] == ':') bDoppel = true;
				else if (Line[i] == ' ')
				{
					if (bValue && (bDoppel || (pArg > 0))) break;
					pArg = 0;
				}
				else if (Line[i] == '%')
					bPercent = true;
				else if ((Line[i] == '\r') || (Line[i] == ',')) {}	// Diese Zeichen ignorieren
				else
				{
					sArg[pArg++] = Line[i];
					sArg[pArg] = 0;
				}
			}
			if (bValue)
			{	// In xml_config nach einem entsprechendem Boni suchen
				int bid = xml_config.GetBonusId(sArg, bPercent);
				if (bid < 0)
				{	// testen, ob der gesamte Text nicht vielleicht doch ein Bonus ist
					bid = xml_config.GetBonusId(MidStr(AnsiString(Line), 14, i - 16), bPercent);
				}
				if (bid >= 0)
				{	// Es ist ein regulärer Bonus
					Item->Effect[NextBonus] = bid;
					Item->EffectValue[NextBonus] = Value;
					NextBonus++;
				}
				else
				{	// Hier ein paar zusätzliche Werte nehmen, die keine Boni sind
					if (strcmp(sArg, strAF) == 0) Item->AF = Value;
					if (strcmp(sArg, strQuality) == 0) Item->Quality = Value;
					if (strcmp(sArg, strSpeed) == 0) Item->Speed = Value;
					if (strcmp(sArg, strAbsorb) == 0)
					{	// Value in Rüstungsklasse umwandeln
						switch (Value)
						{
						case 0: Item->Class = 0; Item->Level = Item->AF;break;
						case 10: Item->Class = 1; Item->Level = Item->AF / 2; break;
						case 19: Item->Class = 2; Item->Level = Item->AF / 2; break;
						case 27: Item->Class = 3; Item->Level = Item->AF / 2; break;
						case 34: Item->Class = 4; Item->Level = Item->AF / 2; break;
						}
						//if (Item->Position < 0)
						//	Item->Position = 0;	// Alle Rüstungen als Handschuhe annehmen
						// Es gibt leider keine Info darüber im Log
						// Wenn wir die Position auf -1 lassen, dann kommt automatisch eine Auswahlbox
					}
					if (strcmp(sArg, "DPS") == 0)
					{	// Nur ersten DPS-Wert speichern
						if (Item->DPS == 0)
						{
							Item->DPS = Value;
							// Berechne den Itemlevel
							int level = (Value - 11) / 3;
							if (level > 51) level = 51;
							Item->Level = level;
						}
					}
				}
			}
		}
//		else
		{	// noch ein paar besondere Strings auswerten
			if (strncmp(&Line[11], strUnique, sizeof(strUnique) - 1) == 0)
			{	// Unique Gegenstände nicht importieren
				return false;
			}
			if (strncmp(&Line[11], strCrafted, sizeof(strCrafted) - 1) == 0)
			{	// Craftet Gegenstände nicht importieren
				return false;
			}
			if (strncmp(&Line[11], strArtifact, sizeof(strArtifact) - 1) == 0)
			{
				Item->MaxLevel = 10;
				Item->Realm = 7;
			}
			if ((strncmp(&Line[11], strBonus, sizeof(strBonus) - 1) == 0) \
			 || (strncmp(&Line[11], strBonus2, sizeof(strBonus2) - 1) == 0))
			{	// Spezielle Werte (meist Bonuserhöhungen)
				// Bonus auf BONUS: VALUE
				unsigned int i;
				for (i = 21; i < StrLen(Line); i++)
				{	// Alles bis zum Doppelpunkt in sArg kopieren
					if (Line[i] == ':') break;
					sArg[i - 21] = Line[i];
				}
				sArg[i - 21] = 0;
				for (; i < StrLen(Line); i++)
				{
					if ((Line[i] >= '0') && (Line[i] <= '9'))
					{
						Value = Value * 10 + Line[i] - '0';
					}
				}
				// In xml_config nach einem entsprechendem Boni suchen
				int bid = xml_config.GetBonusId(sArg);
				if (bid >= 0)
				{	// Es ist ein regulärer Bonus
					Item->Effect[NextBonus] = bid;
					Item->EffectValue[NextBonus] = Value;
					NextBonus++;
				}
				else
				{	// Fehlermeldung
					Application->MessageBoxA(AnsiString("Ein Bonus '" + AnsiString(sArg) + "' ist unbekannt!\nDie Datei 'config.xml' bzw. die entsprechende Sprachdatei anpassen!").c_str(), "Fehler");
				}
			}
			if (strncmp(&Line[11], strActivLevel, sizeof(strActivLevel) - 1) == 0)
			{	// Danach kommt ne Zahl, welche den Level angibt
				int level = Str2Int(&Line[11 + sizeof(strActivLevel)]);
				Item->EffectLevel[NextBonus - 1] = level;
			}
			unsigned int cp = 12;
			if ((strncmp(&Line[11], strRestriction, sizeof(strRestriction) - 1) == 0) \
			 || (strncmp(&Line[12], strRestriction, sizeof(strRestriction) - 1) == 0))
			{	// Solange nachfolgende Strings eine Klasse darstellen, solange
				// diese bei den Beschränkungen eintragen
				bRestriction = true;
				cp = 12 + sizeof(strRestriction);
			}
			while (bRestriction && (cp < StrLen(Line)))
			{
				int pArg = 0;
				for (; cp < StrLen(Line); cp++)
				{
					if ((Line[cp] == ' ') || (Line[cp] == ',') || (Line[cp] == '-') || (Line[cp] == '\r'))
					{
						sArg[pArg] = 0;
						if (pArg > 0)
						{	// Es gibt einen String. Schauen obs ne Klasse ist
							int cid = xml_config.GetClassId(sArg);
							if (cid >= 0)
							{
								Item->ClassRestriction[NextRestriction++] = cid;
							}
							else
							{	// Keine Klasse mehr, Modus aufheben
								bRestriction = false;
							}
						}
						pArg = 0;
					}
					else
					{
						sArg[pArg++] = Line[cp];
					}
				}
			}
		}
		fChatLog->getline(Line, 1024);
	}
	return true;
}

#pragma package(smart_init)