# case 'char' mit mehr als einem Zeichen



## Kimble (4. Mai 2003)

hi,
wie kann ich bei folgendem Code Snippet es schaffen, dass der Compiler nicht meckert:

```
void GL_ReadCFG::ReadCFG (void) {
	f = fopen ("mpark.cfg", "w");

	while((fscanf(f, "%d.%s", &value, var)) != EOF) {
		switch (var) {
		case 'width':
			break;
		case 'height':
			break;
		case 'bpp':
			break;
		case 'title':
			break;
		}
	}
}
```
wenn ich das compilen will, kommt immmer:

```
D:\gl\mpark\g_framework.cpp(224) : error C2015: Zu viele Zeichen in der Konstante
D:\gl\mpark\g_framework.cpp(226) : error C2015: Zu viele Zeichen in der Konstante
D:\gl\mpark\g_framework.cpp(226) : error C2196: Wert fuer case '0' wurde bereits verwendet
D:\gl\mpark\g_framework.cpp(230) : error C2015: Zu viele Zeichen in der Konstante
D:\gl\mpark\g_framework.cpp(230) : error C2196: Wert fuer case '0' wurde bereits verwendet
```

der Inhalt meiner mpark.cfg ist z.b. so:
640.width
und da will ich halt wissen ob var width ist, usw.


----------



## rook (4. Mai 2003)

case funktioniert nur mit einem integer..
"bla" <- ein string
'bla' <- ungültig
'b' <- ein zeichen, als int wäre das 98

versuch das mal ohne switch...

```
if(!memcmp(var, "width", sizeof(var)))
{
// var == "width"
}
```

ich hoffe du verstehst was ich meine


----------



## Patrick Kamin (4. Mai 2003)

*-*



> case funktioniert nur mit einem integer..


Das sind keine Integer, sondern ordinale Datentypen


----------



## Kimble (4. Mai 2003)

gibts ne Moeglichkeit, das irgendwie mit switch zu machen?


----------



## Thomas Darimont (4. Mai 2003)

Servus!

Such doch einfach mal in der MSDN nach ner c-Funktion, die dir zu einem beliebigen String einen Hash Code errechnet ... das ist dann eine Integer (Bzw. Long) Zahl die du im switch Statement benutzen kannst ... (bei long musst du eben Casten...)

Wenn du keine hashCode Funktion feindest musst du dir eben selber eine basteln ... :
String s;

hashValue = s[0]*31^(n-1) + s[1]*31^(n-2) + ... + s[n-1]; ...

....

PseduoCode:

String myvalue = "blablabla"
int myHash;

myHash = createHashCode(myvalue);

switch (myHash){
  case createHashCode("width")
           break;
  case createHashCode("height")
          break;

 ....

}

Gruss Tom


----------



## Kimble (4. Mai 2003)

hm, gibts da keine einfachere Moeglichkeit


----------



## rook (4. Mai 2003)

> Das sind keine Integer, sondern ordinale Datentypen


also für mich ist 98 ein integer, fertig 

@kimble
ich denke nicht, wozu brauchst du denn unbedingt switch?
ich überprüfe somit immer meine strings.. oder besser gesagt ich habe mir meine eigene funktion gebaut...
wenn du unbedingt switch benutzen willst, mach es doch einfach so.. *g*


```
int wert = 0;
if(!memcmp(var, "width", sizeof(var)))
{
    wert = 1;
}
if(!memcmp(var, "height", sizeof(var)))
{
    wert = 2;
}
// usw..
// und dann deine switch abfrage

switch(wert)
{
    case 1:
        //...
        break;
//...
}
```

is aber total umständlich *lach*


----------



## goela (5. Mai 2003)

Ich schätze, entweder Du realisierst dies mit dem Hashcode oder machst eine ordinäre if-else Anweisung.

Andere Möglichkeit: Du steigst auf C# um, da geht so was von Haus aus!


----------



## Mr.Undertaker (5. Mai 2003)

@rook
Integer ist ein ordinaler Datentyp (das bedeutet nämlich ein abzählbarer Datentyp).Und da char integerwerte enthält ist der einwand von caminus zwar richtig, aber nur klug******erei ;-) ;-). Das kennt er wahrscheinlich von Pascal, oder??


----------



## Kimble (5. Mai 2003)

tdar2: steht n bei deinem Vorschlag fuer die Laenge des Strings?


----------



## Thomas Darimont (5. Mai 2003)

Servus!

Jo n steht für die Länge des Strings und S(1), S(2), S(3) ...S(x) stehen für das jeweilige Zeichen an der Indexposition x.


Gruss Tom


----------



## Patrick Kamin (5. Mai 2003)

*-*



> _Original geschrieben von Mr.Undertaker _
> *@rook
> Integer ist ein ordinaler Datentyp (das bedeutet nämlich ein abzählbarer Datentyp).Und da char integerwerte enthält ist der einwand von caminus zwar richtig, aber nur klug******erei ;-) ;-). Das kennt er wahrscheinlich von Pascal, oder?? *


Richtig!
Auch bei Pascal kann man als Marken nur ordinale Datentypen verwenden.

Aber ich weiß nicht so recht, was du hiermit meinst:


> Und da char integerwerte enthält


??


----------



## Mr.Undertaker (5. Mai 2003)

Mh, am besten ich erklärs am Source-Code  :

char test=65;
std::cout<<test;

Natürlich nicht 65, sondern das A aus der ASCII-Tabelle an der Stelle 65. Der Compiler geht mit chars auch um wie mit integern, siehe

++test;
std::cout<<test;

da gibt er nun B aus.
Logisch oder?


----------



## Patrick Kamin (5. Mai 2003)

*-*

Selbstverständlich ist das logisch, deshalb sind es ja ordinal Zahlen. 
Trotzdem hat der Ordianalwert eines Zeichens nichts mit einem Integer zu tun.
Aber ist ja auch egal, wir wissen ja beide bescheid. ;-]


----------



## Kimble (5. Mai 2003)

hm, also ich hab das so gemacht. Ist das falsch tard2?
Als Ergebnis komme immer eine negative Zahl raus...

Der String wird richtig uebergeben und die Anzahl der Buchstaben stimmt auch! Aber fuer Hallo kommt -858978080 raus...


```
#include <iostream>
#include <string>

using namespace std;

int hash (char s[]) {
	int n = strlen(s);
	unsigned long hashValue;
	int x = 0;

	do {
		hashValue += s[x]*31^(n-(x+1));

		x++;
	} while (x<n);

	return hashValue;
}

int main () {
	int test;

	test = hash ("Hallo");

	cout << test;

	return 0;
}
```


----------



## Christian Fein (6. Mai 2003)

> _Original geschrieben von goela _
> *Ich schätze, entweder Du realisierst dies mit dem Hashcode oder machst eine ordinäre if-else Anweisung.
> 
> Andere Möglichkeit: Du steigst auf C# um, da geht so was von Haus aus!  *



wie in java schon lange *SCNR*


----------



## Thomas Darimont (6. Mai 2003)

Servus!

Versuchs mal so...:

    int hashCode(char[] s) {
	int h = 0;
        int off = 0;
        char val[] = s;
	int len = strlen(s);

        for (int i = 0; i < len; i++) {
             h = 31*h + val[off++];
        }

     return h;
    }

...

Gruss Tom


----------



## Kimble (6. Mai 2003)

hm, jetzt geht's ohne Probleme 

hab vergessen int hashValue auf 0 zu setzen.

hashValue war ja gar nicht initialisert also wurde einfach was dazugezaehlt!
So geht's:

```
int hash (char s[]) {
	int n = strlen(s);
	unsigned long hashValue = 0;
	int x = 0;

	cout << s << "\n" << n << "\n" << endl;

	do {
		hashValue += s[x]*31^(n-(x+1));

		x++;
	} while (x<n);

	return hashValue;
}
```

Danke nochmal tdar2!!!


----------



## Thomas Darimont (6. Mai 2003)

Servus!

Null Problemo!

Gruss Tom


----------



## Kimble (6. Mai 2003)

so,
ich hab das jetzt versucht einzubauen:

```
/*
================================================================================
H_HashCode () : returns hash code
================================================================================
*/
int H_HashCode::hash (char s[]) {
	this->n = strlen (this->s);

	do {
		this->hashValue += this->s[this->x]*31^(this->n-(this->x+1));

		this->x++;
	} while (this->x < this->n);

	return hashValue;
}

/*
================================================================================
ReadCFG () : Read all important data from CFG File
================================================================================
*/
void GL_ReadCFG::ReadCFG (void) {
	if ((this->f = fopen ("mpark.txt", "r")) != NULL) {
		while ((fscanf(f, "%d.%s", &this->value, this->var)) != EOF) {
			int myHash = 0;

			myHash = this->hash->hash (this->var);

			switch (myHash) {
			case this->hash->hash ("width"):
				this->width = this->value;
				break;

			case this->hash->hash ("height"):
				this->height = this->value;
				break;
			
			case this->hash->hash ("bpp"):
				this->bpp = this->value;
				break;

			default:
				break;
			}
		}
	} else {
		this->CreateCFG ();
	}
}
```
Die Klasse sieht so aus:

```
// H_HashCode
class H_HashCode {
public:
	H_HashCode ();
	~H_HashCode ();

	unsigned int		hashValue;

	int	hash (char s[]);

private:
	int					n;
	int					x;
	char				s[50];
};


// GL_ReadFromFile
class GL_ReadCFG {							// Reads data from File
public:
	int					width;
	int					height;
	int					bpp;

	FILE*				f;
	char				var[50];
	int					value;

	H_HashCode			*hash;

	void ReadCFG(void);
	void CreateCFG(void);
};
```

Allerdings kommt jetzt als Fehlermdeldung:

```
D:\gl\mpark\g_framework.cpp(312) : error C2051: case-Ausdruck ist keine Konstante
D:\gl\mpark\g_framework.cpp(316) : error C2051: case-Ausdruck ist keine Konstante
D:\gl\mpark\g_framework.cpp(320) : error C2051: case-Ausdruck ist keine Konstante
D:\gl\mpark\g_framework.cpp(326) : warning C4065: switch-Anweisung enthaelt 'default', aber keine case-Marken
Fehler beim Ausführen von cl.exe.

mpark.exe - 3 Fehler, 1 Warnung(en)
```

Was hab ich da jetzt falsch gemacht???


----------



## Thomas Darimont (6. Mai 2003)

Servus! 

... ich glaub da haben wir pech gehabt ... anscheinden muss der Char bzw. Integer Wert schon zur Compile Zeit bekannt sein...
bei unserer Methode jedoch wird er erst zur Laufzeit errechnet ...

dann musst du es wohl doch ganz im sinne des guten alten if-then-else lösen ...

Gruss Tom


----------



## rook (6. Mai 2003)

vieleicht geht es aber auch wenn die funktion einen konstanten wert zurückliefert...


```
const int H_HashCode::hash (char s[])
```
wäre dann eine konstante, bin mir aber nicht sicher ob das funkt...


----------



## Tensi (11. Mai 2003)

quote:
----------------------------------------------------------------------
Original geschrieben von goela 
Ich schätze, entweder Du realisierst dies mit dem Hashcode oder machst eine ordinäre if-else Anweisung.

Andere Möglichkeit: Du steigst auf C# um, da geht so was von Haus aus!  
----------------------------------------------------------------------




> _Original geschrieben von Chris _
> *wie in java schon lange *SCNR*  *



Muß sowas denn wirklich sein???
Dafür gibt es doch verschiedene Programmiersprachen, oder?!


----------



## TheBrain (11. Mai 2003)

Hi Kimble!

So wie es aussieht willst du doch in deiner switch-Anweisung nur auf bestimmte Worte überprüfen. Wenn es so ist, kannst du mit der Hash-Methode ja schon einmal die Werte für die einzelenen Worte berechnen und sie dann in deinem Programm schon als Konstante angeben.

Ich weiß nicht, ob es funktioniert, aber probieren kann man es ja mal

Mfg
  TheBrain


----------

