PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : Im String nach Umlauten suchen, einzelne Werte um x erhöhen.



darxun
02-01-2008, 13:16
1)
Wie ist es möglich, in Strings nach Umlauten zu Suchen? Meine ersten Zeilen zu dem Thema sind nicht wirklich ergiebig. Wenn Umlaute in dem eingegebenen String gefunden werden möchte ich eine Fehlermeldung an den Benutzer ausgeben.

2)
Ich möchte bei der Eingabe von "x" jedes Zeichen des Strings um x erhöhen. Ein A wird mit x=2 zu C, da der Ascii-Wert von A mit 2 addiert den Ascii-Wert von C entspricht.


#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
int main (void)
{
char szString[100], szSuche[]="öäü";
int Len=0;
printf("String eingeben: ");
gets(szString);
printf("Kontrollausgabe der Eingabe: %s\n",szString);
Len = strlen( szString );
printf("Laenge des Strings: %i\n",Len);
printf("Suche: %s\n",strpbrk(szString,szSuche));
return 0;
}

jeebee
02-01-2008, 13:33
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
/* unnötig, math.h enthält nur mathematische Funktionen
* wie cos, sin die hier sicher nicht gebraucht werden.
#include <math.h>
*/

/* Bufferlänge besser so definieren und dann überall im Code
* das Makro brauchen,
* So kann man auch die Bufferlänge einfach ändern,
* ohne dass neue Bugs (vorallem Buffer-Overflows) entstehen.
*/
#define STRLEN 100

int main (void)
{
char szString[STRLEN], szSuche[]="öäü";
char *res = NULL;
int i;
int Len=0;
printf("String eingeben: ");
/* gets ist nicht unbedingt zu empfehlen, es überprüft die
* Eingabelänge nicht.
*/
/* gets(szString); */
fgets(szString, STRLEN, stdin);
printf("Kontrollausgabe der Eingabe: %s\n",szString);
Len = strlen( szString );
printf("Laenge des Strings: %i\n",Len);

/* strpbrk gibt NULL zurück, falls die Vergleichszeichen
* nicht gefunden werden */
if((res = strpbrk(szString,szSuche))!=NULL) {
printf("Die Eingabe enthielt ein Sonderzeichen\n"
"Beende...\n");
return EXIT_FAILURE;
}
/* Keine Sonderzeichen, jedes Zeichen im String um 2 erhöhen.
* Dies funktioniert so, da char ein integraler Typ ist, d.h. man
* mit Variablen vom Typ char ganz normal rechnen kann.
*/
for(i=0;i<Len;i++) {
szString[i] = szString[i]+2;
}
printf("String (+2): %s\n", szString);
return 0;
}

Hoffe das hilft.

simu`

edit: wenn du das Erhöhen mit einer Eingabe machen willst, dann kannst du das leicht dazufügen. atoi() wandelt einen String in einen Integer um.

int atoi(const char *nptr);

darxun
02-01-2008, 13:53
1) Was genau passiert bei "#define STRLEN 100"? Wird damit die Maximale Zeichenanzahl festgelegt, also 100?

2) Ist es möglich, die Zeichenanzahl der Eingabe anzupassen, sodass es keine obere Zeichengrenze gibt (bzw. selbige sehr groß ist)?

3) Wenn es keine maximale Zeichenanzahl gibt, kann man dann auch die gets()-Funktion verwenden?

4) Eigentlich sollte die Erhöhung um x (sozusagen die Verschlüsselung) immer dann stattfinden, wenn keine Fehlermeldung wegen Umlauten ausgegeben werden muss.

5) Wieso ist "res" ein Zeiger, eigentlich geht es auch wenn "res" eine int-Variable ist.

ContainerDriver
02-01-2008, 14:44
1) Was genau passiert bei "#define STRLEN 100"? Wird damit die Maximale Zeichenanzahl festgelegt, also 100?

Damit gibts du dem Präprozessor die Anweisung alle Vorkommnisse von STRLEN im Quelltext durch 100 zu ersetzen; d.h. du legst die Größe des Arrays szString fest.


2) Ist es möglich, die Zeichenanzahl der Eingabe anzupassen, sodass es keine obere Zeichengrenze gibt (bzw. selbige sehr groß ist)?

Mit dynamischer Speicherverwaltung (malloc(), realloc(), free()) sollte das möglich sein, dazu musst du aber erst die C Grundlagen verstanden haben.


3) Wenn es keine maximale Zeichenanzahl gibt, kann man dann auch die gets()-Funktion verwenden?

Du kannst gets nur mit einem char-Pointer als Argument aufrufen, das dazugehörige Feld ist immer in der Größe beschränkt (d.h. es gibt immer eine maximale Zeichenanzahl)! Wenn du mit gets() mehr Zeichen einliest, als das entsprechende Feld groß ist, dann kommt es zu einem Bufferoverflow.


Never use gets(). Because it is impossible to tell without knowing the
data in advance how many characters gets() will read, and because
gets() will continue to store characters past the end of the buffer, it
is extremely dangerous to use. It has been used to break computer
security. Use fgets() instead.




4) Eigentlich sollte die Erhöhung um x (sozusagen die Verschlüsselung) immer dann stattfinden, wenn keine Fehlermeldung wegen Umlauten ausgegeben werden muss.

5) Wieso ist "res" ein Zeiger, eigentlich geht es auch wenn "res" eine int-Variable ist.
Die Funktion strpbrk liefert aber einen char-Zeiger zurück!

jeebee
02-01-2008, 17:39
2) Ist es möglich, die Zeichenanzahl der Eingabe anzupassen, sodass es keine obere Zeichengrenze gibt (bzw. selbige sehr groß ist)?
Das geht am einfachsten wenn du bei #define STRLEN etwas wie 32768 anstatt 100 hinschreibst ( dann hast du 2^15 Zeichen zur Verfügung, brauchst allerdings auch 32kB Speicher für dein Array... ).

4) Eigentlich sollte die Erhöhung um x (sozusagen die Verschlüsselung) immer dann stattfinden, wenn keine Fehlermeldung wegen Umlauten ausgegeben werden muss.

Dies tut ja mein Code auch. Wenn ein Umlaut vorkommt, dann bricht das Progamm mit EXIT_FAILURE (Fehler) ab. Sonst wird zu jedem Zeichen in deinem String x (im Moment einfach 2) dazugezählt. Also immer wenn du einen String ohne Umlaute eingibst.


5) Wieso ist "res" ein Zeiger, eigentlich geht es auch wenn "res" eine int-Variable ist.
Eigentlich würde für das if auch
if(strpbrk(szString,szSuche)!=NULL) { /* Fehlerbehandlung */ } reichen, wenn dich das Resultat, falls etwas gefunden wird nicht kümmert. Das res hab ich dazu verwenden wollen um den Umlaut auszugeben, ist aber bei UTF-8 nicht ganz einfach.

Den Rest hat ja ContainerDriver schon beantwortet.

panzi
02-01-2008, 19:38
Also in C++ kann man eine Zeile ohne größenbegrenzung so einlesen (und wieder ausgeben):


#include <string>
#include <iostream>

int main() {
string s;
getline(cin, s);
cout << s;
return 0;
}

In C ist es schon schwiriger, da es da keine getline Funktion gibt, die eine ganze Zeile ließt. Hab da mal was zamgebastelt:


#include <string.h>
#include <stdio.h>
#include <stdlib.h>

#define BUFFER_SIZE 256

/**
* Diese Funktion liest eine ganze Zeile ein, egal wie lange sie ist.
* Wenn ein Fehler auftritt oder das Ende der Datei erreicht wurde wird NULL
* zurück gegeben.
* Eventuell wäre ein quadratisches wachsen der Puffergröße besser als
* ein lineares (also immer * 2 statt + BUFFER_SIZE).
*/
char* getline(FILE* fp) {
char* s = NULL;
char* olds = NULL;
size_t size = 0;
size_t len = 0;
size_t oldlen = 0;

for (;;) {
olds = s;
s = realloc(s, size + BUFFER_SIZE);

if (s == NULL) {
free(olds);
break;
}

clearerr(fp);
if (fgets(s + len, size + BUFFER_SIZE - len, fp) == NULL) {
if (!feof(fp) || len == 0) {
free(s);
s = NULL;
}
break;
}

oldlen = len;
len += strlen(s + len);

if (len == oldlen || s[len - 1] == '\n') {
break;
}

size += BUFFER_SIZE;
}

return s;
}

int main() {
char* s = NULL;

printf("enter a line: ");
s = getline(stdin);

if (s == NULL) {
if (feof(stdin)) {
puts("\n<end of file>");
}
else {
perror("\nERROR: getline");
}
}
else {
puts(s);
free(s);
}

return 0;
}

darxun
04-01-2008, 11:29
Dies tut ja mein Code auch. Wenn ein Umlaut vorkommt, dann bricht das Progamm mit EXIT_FAILURE (Fehler) ab. Sonst wird zu jedem Zeichen in deinem String x (im Moment einfach 2) dazugezählt. Also immer wenn du einen String ohne Umlaute eingibst.

Wenn ich das Prg laufen lasse, wird auch wenn ein Umlaut eigegeben wurde, das Zeichen umgeschrieben (in diesem Fall +2). Die Fehlermeldung taucht gar nicht auf.

Ich habe hier mal noch eine Version programmiert die den Schlüssel einliest, allerdings funktioniert nun gar nichts mehr.


#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#define STRLEN 100

int main (void)
{
char szString[STRLEN], szSuche[]="öäü";
char *res = NULL;
int i=0, x=0;
int Len=0;
printf("String eingeben: ");
gets(szString);
printf("Kontrollausgabe der Eingabe: %s\n",szString);
Len = strlen( szString );
printf("Laenge des Strings: %i\n",Len);

/* strpbrk gibt NULL zurück, falls die Vergleichszeichen
* nicht gefunden werden */
if((res = strpbrk(szString,szSuche))!=NULL)
{
printf("Die Eingabe enthielt ein Sonderzeichen");
}
else
{
printf("Geben Sie einen Schluessel ein: ");
scanf("%i",x);

for(i=0;i<Len;i++)
{
szString[i] = szString[i]+x;
}
/* Keine Sonderzeichen, jedes Zeichen im String um 2 erhöhen.
* Dies funktioniert so, da char ein integraler Typ ist, d.h. man
* mit Variablen vom Typ char ganz normal rechnen kann.
*/
}
printf("String (%i): %s\n",x, szString);
return 0;
}

jeebee
04-01-2008, 13:34
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#define STRLEN 100

int main (void)
{
char szString[STRLEN], szSuche[]="öäü";
char *res = NULL;
int i=0, x=0;
int Len=0;
printf("String eingeben: ");
fgets(szString,STRLEN,stdin);
printf("Kontrollausgabe der Eingabe: %s\n",szString);
Len = strlen( szString );
printf("Laenge des Strings: %i\n",Len);

/* strpbrk gibt NULL zurück, falls die Vergleichszeichen
* nicht gefunden werden */
if((res = strpbrk(szString,szSuche))!=NULL)
{
printf("Die Eingabe enthielt ein Sonderzeichen\n"
"Beende...\n");
/* hier entweder direkt beenden, oder dann den ganzen Rest im
* else Teil abhandeln.
*/
return EXIT_FAILURE;
}
else
{
printf("Geben Sie einen Schluessel ein: ");
/* nochmal die Dokumentation von scanf lesen!
* scanf erwartet als Argumente nach dem Formatstring
* Zeiger auf die Variablen in denen die Eingaben abgelegt
* werden sollen.
*/
scanf("%i",&x);

for(i=0;i<Len;i++)
{
szString[i] = szString[i]+x;
}
/* Keine Sonderzeichen, jedes Zeichen im String um 2 erhöhen.
* Dies funktioniert so, da char ein integraler Typ ist, d.h. man
* mit Variablen vom Typ char ganz normal rechnen kann.
*/
}
printf("String (%i): %s\n",x, szString);
return 0;
}


Bei mir funktioniert der Code so anstandslos. Ich habe nochmal die fehleranfällige Funktion gets durch fgets ersetzt.

ContainerDriver
04-01-2008, 14:08
[...]
printf("Geben Sie einen Schluessel ein: ");
scanf("%i",x);
[...]


Probiers mal mit scanf("%d",&x).

darxun
04-01-2008, 14:11
Bei mir funktioniert der Code so anstandslos. Ich habe nochmal die fehleranfällige Funktion gets durch fgets ersetzt.

Bei mir funktionierts leider nicht, zwar wird nun alles verschlüsselt (also im ASCII um x "verschoben") aber bei einem String mit ö,ü oder ä kommt nicht die Meldung "Die Eingabe enthielt ein Sonderzeichen". Ich habe keine Idee, wieso es bei dir funktionieren sollte und bei mir nicht.

(Ich benutze Visual Studio 2005 Prof. Edition)