Dies ist eine statische Kopie unseres alten Forums. Es sind keine Interaktionen möglich.
This is a static copy of our old forum. Interactions are not possible.

oixio

Senior Schreiberling

  • "oixio" is male
  • "oixio" started this thread

Posts: 517

Date of registration: Oct 3rd 2004

1

Thursday, December 9th 2004, 12:27am

String trennen in c anhand von " - "

Hallo,

ich habe folgendes Problem:
ich will mir ein Winamp-Plug für mein LCD-Display anpassen, weil das original eine falsche Trennung macht. Es bekommt von Winamp den Interpret/Titel in folgender Form "Karl-Heinz - Lied von Kalle". Der Original-Quelltext trennt hier nun aber schon bei dem Bindestrich zwischen Karl und Heinz - und nicht bei " - " wie ich das gerne hätte

Source code

1
2
3
4
5
6
Der alte Code:
// get file info
SendMessage( plugin.hwndParent, WM_WA_IPC, (WPARAM)&basicFileInfo, IPC_GET_BASIC_FILE_INFO );
//Zerlegen in song und artist
artist = strtok( basicFileInfo.title, "-" );
song = strtok( NULL, "\0" );


Da ich von C nicht soo viel Ahnung habe, hab ich nach dem Try-And-Error-Prinzip ein bischen rumprobiert und bin auf die strstr und die strncpy Funktionen gestoßen mit deren Hilfe ich auch ohne Probleme den String so zerlegen konnte wie ich das wollte. Nur bekam ich nun jedes Mal, wenn ich Winamp beendet habe eine Fehlermeldung, dass auf einen ungültigen Adressbereich zugegriffen wurde. Anscheinend wird aiso Winamp schneller beendet als mein Plugin, so dass ich nicht mehr auf den Titel im Speicher zugreifen kann. Also hab ich mir gedacht, erzeug ich doch immer eine lokale Kopie des Titels und arbeite damit, heraus kam folgender Code:

Source code

1
2
3
4
5
6
7
8
9
10
11
12
//Zerlegen in song und artist
char buffer3[_MAX_FNAME];
char buffer4[_MAX_FNAME];

strcpy(buffer3,basicFileInfo.title);

song = strstr(buffer3, " - ");

strncpy(buffer4, buffer3, (int)(song - buffer3));

artist = &buffer4;
song = song + 3;

Das funktioniert auch soweit, d.h. der Titel und Interpret wird so angezeigt, wie ich mir das vorstelle und auch die Fehlermeldung ist wieder verschwunden.
Nur hab ich jetzt ein neues Problem:
Das ganze scheint zu lange zu dauern. Denn wenn ich nun Winamp schließe, wird das Display nicht mehr abgeschaltet, d.h. das Plugin wird nicht mehr bis zum Ende ausgeführt sondern irgendwo unterbrochen. An anderen Stellen im Quelltext hab ich nichts geändert, und mit originalen Variante wird das Display auch ordnungsgemäß abgeschaltet. Also muss das an meiner Trennung liegen....

Deshalb meine Frage:

Kennt jemand eine schnellere/elegantere/bessere Lösung den String zu zerlegen? Oder weiß irgendwie anders Rat?

mfg

oixio
Dieser Post wurde aus 100 % chlorfrei gebleichten, handelsüblichen, freilaufenden, glücklichen Elektronen erzeugt!

paradroid

Junior Schreiberling

Posts: 231

Date of registration: Feb 28th 2002

2

Thursday, December 9th 2004, 10:23am

RE: String trennen in c anhand von " - "

Ohne genauere Kenntnis von Winamp wage ich mal folgende Vermutung: Das Problem liegt - wie immer bei C - am Speichermanagement. strtok verwendet als Rückgabe einfach den Originalstring, d.h. es wird ein 0-Terminator einfach in den Speicher geschrieben. Das hat den Vorteil, dass kein neuer Speicher reserviert werden muss, das aufrufende Programm (in diesem Fall wohl Winamp) muss sich dann selbst um die Freigabe kümmern.
In deinem Fall reservierst du den Speicher in deiner Subroutine, d.h. der Speicher verschwindet, wenn die Routine beendet wird:

Quoted

Original von oixio

Source code

1
2
3
4
5
6
7
8
9
10
11
12
//Zerlegen in song und artist
char buffer3[_MAX_FNAME];
char buffer4[_MAX_FNAME];

strcpy(buffer3,basicFileInfo.title);

song = strstr(buffer3, " - ");

strncpy(buffer4, buffer3, (int)(song - buffer3));

artist = &buffer4;
song = song + 3;
Das könnte Probleme bereiten. Possible solution: buffer3 und buffer4 als globale Variablen in deinem Plugin erklären. Dann bleiben sie solange bestehen, wie das Plugin lebt.

HTH

# transmission terminated #

oixio

Senior Schreiberling

  • "oixio" is male
  • "oixio" started this thread

Posts: 517

Date of registration: Oct 3rd 2004

3

Thursday, December 9th 2004, 11:04am

RE: String trennen in c anhand von " - "

Du hast mein Problem glaub ich nicht so ganz verstanden. Das mit dem Null-Pointer ist gelöst dadurch. Nur scheint es jetzt langsamer zu laufen. Mein Problem ist, das Winamp das Plugin anscheinent "killt" beim beenden, so dass es nicht mehr bis zum ende ausgeführt wird und das Display abschalten kann. deshalb vermute ich mal, die Schleife arbeitet zu langsam, so dass das Winamp zu lange dauert und es das Plugin einfach abricht anstatt es ordentlich zu beenden.

Trotzdem schonmal danke für deine Antwort.

Edit:
Ich glaub ich seh grad was du meinst. Du glaubst das Reservieren des Speichers dauert so lange und ich soll ihn "wiederverwerten"? Ich werds heute abend mal testen..

Sonst noch wer ne Idee?
Dieser Post wurde aus 100 % chlorfrei gebleichten, handelsüblichen, freilaufenden, glücklichen Elektronen erzeugt!

This post has been edited 1 times, last edit by "oixio" (Dec 9th 2004, 11:07am)


paradroid

Junior Schreiberling

Posts: 231

Date of registration: Feb 28th 2002

4

Thursday, December 9th 2004, 2:02pm

RE: String trennen in c anhand von " - "

Quoted

Original von oixio
Du hast mein Problem glaub ich nicht so ganz verstanden. Das mit dem Null-Pointer ist gelöst dadurch. Nur scheint es jetzt langsamer zu laufen. Mein Problem ist, das Winamp das Plugin anscheinent "killt" beim beenden, so dass es nicht mehr bis zum ende ausgeführt wird und das Display abschalten kann. deshalb vermute ich mal, die Schleife arbeitet zu langsam, so dass das Winamp zu lange dauert und es das Plugin einfach abricht anstatt es ordentlich zu beenden.

Trotzdem schonmal danke für deine Antwort.

Edit:
Ich glaub ich seh grad was du meinst. Du glaubst das Reservieren des Speichers dauert so lange und ich soll ihn "wiederverwerten"? Ich werds heute abend mal testen..

Sonst noch wer ne Idee?
Ich hab das schon verstanden, aber was ich eigentlich vermute ist, dass Winamp den Segfault abfängt und dein Plugin killt, weil der Zeiger ungültig ist. Ist aber nur ne Vermutung. Generell ist die Wiederverwertung keine schlechte Idee, obwohl ich mir nicht vorstellen kann, dass die Allokation wirklich zu lange dauert.

# transmission terminated #

MAX

Senior Schreiberling

  • "MAX" is male

Posts: 822

Date of registration: Dec 11th 2001

Location: Hannover

5

Thursday, December 9th 2004, 3:05pm

Falls du mit Microsoft Compiler arbeitest, kann ich dir empfehlen, die MFC Klasse CString zu nehmen und damit auszuprobieren. Wenn nicht, versuche auch mit der string aus stl. Dort findest du bessere Methoden, um die Strings hin und her zu kopieren. Die C-Strings, die eigentlich keine Strings sind, sondern nur Pointer auf char, sind sehr unbequem und erfordern, dass man selbst Speichermanagement durchführt => sehr fehleranfällig.

string

basic_string

CString

mfg
MAX

This post has been edited 1 times, last edit by "MAX" (Dec 9th 2004, 3:12pm)


MAX

Senior Schreiberling

  • "MAX" is male

Posts: 822

Date of registration: Dec 11th 2001

Location: Hannover

6

Thursday, December 9th 2004, 3:20pm

Achso, sonst findust du bei msdn gute Beispiele, wie man mit c-strings umgeht
z.B.

strcpy

strstr

strncpy

mfg
MAX

oixio

Senior Schreiberling

  • "oixio" is male
  • "oixio" started this thread

Posts: 517

Date of registration: Oct 3rd 2004

7

Friday, December 10th 2004, 1:11am

Also das Global definieren hats nicht gebracht.

@MAX Thx, aber leider hab ich nicht so richtig Ahnung von C und außerdem funktioniert ja meine Version (solange Winamp an ist).
Gibt es evtl eine äquivalente Funktion zu strtok, nur mit dem Unterschied, das nicht nach einem Zeichen sondern nach 3 Zeichen gesucht wird? Oder hat villeicht jemand eine Idee wie man das mit strtok und dann einer eigenen Abfrage nach den Zeichen vor und hinter dem "-" machen kann?

Leider gibt er mir ja keine Fehlermeldung aus, anhand derer ich sehen kann, wo der Fehler liegt.

Zum weiten Verständnis des Plugins noch eine kurze Struktur

Source code

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
Globale Variablen & Co

init () //schaltet das Display ein

unsigned long __stdcall ThreadProc2( void* v )
{
//Variablen & Co
while( ThreadActive )
	{
	//Titelinfos & Co von Winamp holen
	// get file info
	SendMessage( plugin.hwndParent, WM_WA_IPC, (WPARAM)&basicFileInfo, IPC_GET_BASIC_FILE_INFO );

	<< Hier ist dann mein obiger Code >>

	//Die Sachen aufm Display darstellen

	}
//ClearLCD und so was 
}

quit() //schaltet das display aus und beendet das Plugin


Normalerweise startet und beendet Winamp so ein Plug in über die Funktionen init und quit. Wenn ich meinen Code aber wie oben beschrieben veränder, dann scheint Winamp die quit-Funktion gar nicht mehr aufzurufen. Und ich hab kA was an meinem Code das bewirkt... ?(

Naja, ich werd mir jetzt mal mein Kopfkissen nen bischen genauer anschauen, vielleicht findet mein Unterbewusstsein ja die Lösung über Nacht (ist schon vorgekommen, obwohl ich da eher schwarz sehe...)

mfg
oixio

PS: @MAX: Jupp es ist in Microsofts Entwicklungsumgebung geschrieben
Dieser Post wurde aus 100 % chlorfrei gebleichten, handelsüblichen, freilaufenden, glücklichen Elektronen erzeugt!

paradroid

Junior Schreiberling

Posts: 231

Date of registration: Feb 28th 2002

8

Friday, December 10th 2004, 8:16am

Versuch mal folgendes Fragment:

Source code

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
// get file info
SendMessage( plugin.hwndParent, WM_WA_IPC, (WPARAM)&basicFileInfo,IPC_GET_BASIC_FILE_INFO );
//Zerlegen in song und artist
int c = 0;
artist = basicFileInfo.title;
for( song = artist; *song; song++) {
   if(c==0 && *song==' ') c=1;
   else if(c==1 && *song=='-') c=2;
   else if(c==2 && *song==' ') {
      c=3;
      break;
   }
   else if(c>0) c=0;
}

if(c==3) *(song-2)=0;
Wenn's tatsächlich am "Memory-Recycling" liegt, sollte es so gehen.

# transmission terminated #

MAX

Senior Schreiberling

  • "MAX" is male

Posts: 822

Date of registration: Dec 11th 2001

Location: Hannover

9

Friday, December 10th 2004, 2:29pm

Quoted


Gibt es evtl eine äquivalente Funktion zu strtok, nur mit dem Unterschied, das nicht nach einem Zeichen sondern nach 3 Zeichen gesucht wird? Oder hat villeicht jemand eine Idee wie man das mit strtok und dann einer eigenen Abfrage nach den Zeichen vor und hinter dem "-" machen kann?

Die Fuktion strtok sucht nach einem Token, nicht nur nach einem Zeichen (siehe strtok ) An dem Beispiel kannst du wunderbar sehen, wie die Funktion zu benutzen ist. Sogar für deine Anwendung ist das Beispiel super geeignet.
mfg
MAX

This post has been edited 1 times, last edit by "MAX" (Dec 10th 2004, 2:30pm)


MAX

Senior Schreiberling

  • "MAX" is male

Posts: 822

Date of registration: Dec 11th 2001

Location: Hannover

10

Friday, December 10th 2004, 3:02pm

Das Beispiel für strtok aus der msdn habe ich etwas modifiziert:

Source code

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
#include <string>
#include <stdio.h>
#include <iostream>

char string[] = "Karl-Heinz - Lied von Kalle";
char seps[]   = " ";
char *token;

int main( void )
{
   printf( "Tokens:\n" );
   /* Establish string and get the first token: */
   token = strtok( string, seps );
   while( token != NULL )
   {
	/* While there are tokens in "string" */
	if ( strcmp(token, "-") == 0  )
	      break;
	printf( " %s\n", token );
	/* Get next token: */
	token = strtok( NULL, seps );	   
   }

   token = strtok( NULL, seps );
   while( token != NULL )
   {
	/* While there are tokens in "string" */		
	printf( " %s", token );
	/* Get next token: */
	token = strtok( NULL, seps );
   }
   //Damit das Fenster nicht sofort geschlossen wird
   char c;
   std::cin >> c;
}


Hier erfolgt nur eine Ausgabe. Man müsste also nur in die entsprechenden Variablen speichern. Ich hoffe es hilft. Sonst wie gesagt schaue dir die Tamplate Klasse string aus der STL oder die Klasse CString aus MFC an. Auch wenn du keine Ahnung von c hast, kannst du dir ja etwas schon bei so einem kleinen Beispiel aneignen.
mfg
MAX

This post has been edited 2 times, last edit by "MAX" (Dec 10th 2004, 3:05pm)


MAX

Senior Schreiberling

  • "MAX" is male

Posts: 822

Date of registration: Dec 11th 2001

Location: Hannover

11

Friday, December 10th 2004, 3:19pm

Und noch ein Beispiel, wie man es mit string aus STL machen kann

Source code

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
#include <string>
#include <iostream>

int main( void )
{
	using namespace std;
	string strInterprUndLied ("Karl-Heinz - Lied von Kalle");
	string strInerpreter;
	string strLied;
	string strStringToFind(" - ");
	string::size_type strPosToFind = strInterprUndLied.find(strStringToFind);
	strInerpreter = strInterprUndLied.substr(0, strPosToFind);
	strLied = strInterprUndLied.substr(strPosToFind + strStringToFind.length(), strInterprUndLied.length());
	cout << "Interpreter: " << strInerpreter << "\n";
	cout << "Lied: " << strLied << "\n";
  
   //Damit das Fenster nicht sofort geschlossen wird
   char c;
   std::cin >> c;
}

Alles kompilierbar und ausfürbar. Wie man sieht, ist jetzt die Geschichte viel einfacher und kürzer geworden, ohne Schleifen oder sonstiges, gekapselt durch string Klasse.
Ich hoffe es hilft.
mfg
MAX

This post has been edited 1 times, last edit by "MAX" (Dec 10th 2004, 3:21pm)


oixio

Senior Schreiberling

  • "oixio" is male
  • "oixio" started this thread

Posts: 517

Date of registration: Oct 3rd 2004

12

Friday, December 10th 2004, 8:52pm

@ paradroid:

THX!!! Deine Variante funktioniert. Scheint also echt daran gelegen zu haben. Mit deinem Code schaltet er das Display ordnungsgemäß ab.

Danke auch an alle anderen für die Mühe (ich hab jetzt die String-Klassen nicht mehr getestet, da es mit de mCode von Paranoid funzt und mehr will ich ja auch nicht :)

mfg

oixio
Dieser Post wurde aus 100 % chlorfrei gebleichten, handelsüblichen, freilaufenden, glücklichen Elektronen erzeugt!