BOOL TSteering::LoadMacro( LPSTR makname, LPSTR fn ) { // Function tested // Last changes 950811 FILE* hFile; int idx = nMacroNumber; char* token; char buf[MaxString+1]; int cnt; LPSTR cmd, p1, p2, p3; hFile = fopen( fn, "r" ); if (!hFile) { wsprintf( buf, "Cannot open file %s !", fn ); MessageBox( GetFocus(), buf, "Message", MBINFO ); return FALSE; } // search for macro in file while (GetFileLine( hFile, buf, MaxString )) { if (!strstr( buf, "[Common]" )) // neue Zeile holen, bis "[Common]" auftaucht continue; while (GetFileLine( hFile, buf, MaxString )) { if (buf[0] == '#') // Kommentare werden überlesen continue; token = strtok( buf, " =\r\n\t" ); // strcmp() liefert 0 bei Übereinstimmung if (!strcmp( token, "Name" )) { token = strtok( NULL, " =\r\n\t" ); if (strcmp( makname, token )) // gefundenes Makro ist nicht das gesuchte break; ParsingMacroId( aMacroList[idx], token ); strcpy( aMacroList[idx].FileName, fn ); } if (!strcmp( token, "Length" )) { token = strtok( NULL, " =\r\n\t" ); aMacroList[idx].Length = atoi( token ); } if (!strcmp( token, "[Commands]" )) { aMacroList[idx].CmdList = new TCmdTag[aMacroList[idx].Length]; cnt = 0; while (GetFileLine( hFile, buf, MaxString )) { if (buf[0] == '#') // Kommentare werden überlesen continue; if ((strstr( buf, "[End]" )) || (cnt > aMacroList[idx].Length)) // [End] erreicht oder angegebene Länge überschritten // zweiter Fall kann nicht eintreten, da er weiter unten // bereits abgefangen wird break; // Befehl und alle Parameter als Strings einlesen cmd = strtok( buf, " \r\n\t" ); p1 = strtok( NULL, " \r\n\t" ); p2 = strtok( NULL, " \r\n\t" ); p3 = strtok( NULL, "\r\n\t" ); ParsingCmd( aMacroList[idx].CmdList[cnt], cmd, p1, p2, p3 ); // aktuelle Befehlsanzahl erhöhen cnt++; if (cnt == aMacroList[idx].Length) // maximale Länge erreicht break; } // Befehlslistenlänge auf den tatsächlichen Wert setzen aMacroList[idx].Length = cnt; // the last command has to be Stop // (und zwar zwangsweise...) aMacroList[idx].CmdList[cnt-1].Id = Stop; aMacroList[nMacroNumber].bIsReady = TRUE; // Makroanzahl erhöhen nMacroNumber++; // Falls das Makro schon existiert, wird das alte ersetzt idx = nMacroNumber - 1; while (idx) { idx--; if (!strcmp( aMacroList[nMacroNumber - 1].Name, aMacroList[idx].Name )) { // alte Befehlsfolge löschen delete aMacroList[idx].CmdList; idx++; // Rest der Makroliste eins nach vorn schieben while (idx < nMacroNumber) { aMacroList[idx-1] = aMacroList[idx]; idx++; } nMacroNumber--; // Speichergrösse anpassen memset( &(aMacroList[nMacroNumber]), 0, sizeof(TMacroTag) ); // unsinniger Seitenausstieg 1 fclose( hFile ); return TRUE; } } // unsinniger Seitenausstieg 2 fclose( hFile ); return TRUE; } } } // Datei schliessen und Funktion verlassen fclose( hFile ); return TRUE; }
Die Funktion strtok( str1, str2 ) liefert den durch eins der in str2 angegebenen Trennzeichen begrenzten Teilstring von str1. Nachfolgende Aufrufe von strtok( NULL, str2 ) liefern die weiteren Teilstrings.
Beispiel:
// strtokBsp.cpp // Demonstration der Funktion strtok( char*, char* ) #include <string> #include <iostream> int main() { char text[] = "Hallo Du! "; cout << strtok( text, " " ) << endl; cout << strtok( NULL, " " ) << endl; return 0; }Obiges Programm liefert folgerichtig diese Ausschriften:
beat schuetzl 31 ( ~/projekt98/texte ) > ./strtokBsp Hallo Du! beat schuetzl 32 ( ~/projekt98/texte ) >Zurück nach oben.
Die Funktion LoadMacro() ist prinzipiell leicht verständlich, jedoch haarsträubend implementiert. Die Verschachtelung von drei while-Schleifen ist nicht nur unschön, sondern auch unübersichtlich und unnötig. Hier sind mit Leichtigkeit Änderungen vornehmbar, die sich auf die Wartbarkeit positiv auswirken wuerden.