Forum: PC-Programmierung String herausfiltern unbeachtet Groß- und Kleinschreibung


von Sandra (Gast)


Lesenswert?

Hallo,

ich nutze eine Funktion die heißt StringFind und ist wie folgt 
definiert:
1
int  StringFind(
2
   string  string_value,        // string in which search is made
3
   string  match_substring,     // what is searched
4
   int     start_pos=0          // from what position search starts
5
   );
Nun möchte ich automatisiert ein Textfile nach einem bestimmten String 
durchsuchen z.B. "Tigerente", dabei soll aber auch "tIgerEnte" oder 
"tiGERente" gefunden werden.

Gibt es eine Möglichkeit, wie ich nach einem bestimmten String suchen 
kann, aber dabei die Groß-/Kleinschreibung der einzelnen Buchstaben 
nicht berücksichtigen brauche?

Mit ist schon klar wie ich ein einzelnes Zeichen von Groß- in 
Kleinschreibung umwandeln kann, aber wie ich einen String suche, von dem 
ich noch nichtmal weiß, wo die Buchstaben groß/kleingeschrieben sind, 
weiß ich nicht.

Mir fällt hier nur folgendes ein (kann ich gerade nicht 
programmierteschnisch umschreiben):
1
int SeachString(string string_value, string match_substring, int start_pos)
2
{
3
   if(1.Buchstabe von match_substring gross ODER klein gefunden)
4
     {
5
     merke die position = pos dieses Buchstaben
6
     if(2.Buchstabe von match_substring gross ODER klein gefunden)
7
     }
8
         if(3.Buchstabe von match_substring gross ODER klein gefunden)
9
              if(x.Buchstabe von match_substring gross ODER klein gefunden)
10
                   return(pos+x);
11
  else
12
     return(-1); 
13
                   
14
}

von Rolf Magnus (Gast)


Lesenswert?

Ist die Programmiersprache, in der das geschrieben ist, geheim?
Ansonsten wäre eine einfache Lösung, beide Strings z.B. komplett in 
Großbuchstaben zu konvertieren und dann erst die Suche machen.

von Daniel A. (daniel-a)


Lesenswert?

Rolf Magnus schrieb:
> Ist die Programmiersprache, in der das geschrieben ist, geheim?

Scheint eine mischung aus c++ und pseudocode zu sein, mit
1
using namespace std;
 :( und
1
#include<string>

> Ansonsten wäre eine einfache Lösung, beide Strings z.B. komplett in
> Großbuchstaben zu konvertieren und dann erst die Suche machen.

Finde ich inperformant, und unschön. Ich würde eine Vergleichsfunktion 
übergeben.

Ungetestet:
1
int16_t compareFunc1(char a,char b){return (int16_t)a-b;}
2
int16_t compareFunc2(char a,char b){
3
 if(a>='A'&&a<='Z') a=a-'A'+'a';
4
 if(b>='A'&&b<='Z') b=b-'A'+'a';
5
 return (int16_t)a-b;
6
}
7
size_t findString(const std::string s,const std::string w,const size_t b,int16_t(*f)(char,char)){
8
  size_t n=s.size(),l=w.size();
9
  for(;b+l<n;b++){
10
    size_t i;
11
    for(i=0;l<i;i++){
12
      if(f(s[b+i],w[i])) break;
13
    }
14
    if(i==l) break;
15
  }
16
  if(b+l<n)
17
    return b;
18
  else
19
    return n;
20
}

: Bearbeitet durch User
von Max H. (hartl192)


Lesenswert?

In ASCII unterscheiden sich Groß- und Kleinbuchstaben nur durch ein 
bit...
Ein bitweises OR mit 0b00100000 mach aus jedem Zeichen einen 
Kleinbuchstaben.

von K. H. (hegy)


Lesenswert?


von Mike (Gast)


Lesenswert?

Hierzu gibt es in C bereits Funktionen:
http://gd.tuwien.ac.at/languages/c/cref-mleslie/master_index.html

Zuerst beide Strings in Kleinbuchsstaben umwandeln:
=> tolower function. Convert an uppercase character to lowercase.

Und dann den Substring suchen
=> strstr function. Search a string for a substring.
oder mit
=> strtok function. this function splits a string into tokens.

von Daniel A. (daniel-a)


Lesenswert?

Getestet:
1
#include<stdint.h>
2
#include<string>
3
#include<iostream>
4
5
int16_t compareFunc1(char a,char b){return (int16_t)a-b;}
6
int16_t compareFunc2(char a,char b){
7
 if(a>='A'&&a<='Z') a=a-'A'+'a';
8
 if(b>='A'&&b<='Z') b=b-'A'+'a';
9
 return (int16_t)a-b;
10
}
11
size_t findString(const std::string s,const std::string w,size_t b,int16_t(*f)(char,char)){
12
  size_t n=s.size(),l=w.size();
13
  for(;b+l<=n;b++){
14
    size_t i;
15
    for(i=0;i<l;i++){
16
      if((*f)(s[b+i],w[i])) break;
17
    }
18
    if(i==l) break;
19
  }
20
  if(l+b<=n)
21
    return b;
22
  else
23
    return n;
24
}
25
26
int main(){
27
  size_t p;
28
  std::string str("Abc eFg eFg ijK");
29
30
  p = findString(str,"aBc",0,compareFunc2);
31
  if(str.size()-p)
32
    std::cout << p << std::endl;
33
  else
34
    std::cout << "Not found" << std::endl;
35
36
  p = findString(str,"efG",0,compareFunc2);
37
  if(str.size()-p)
38
    std::cout << p << std::endl;
39
  else
40
    std::cout << "Not found" << std::endl;
41
42
  p = findString(str,"Efg",5,compareFunc2);
43
  if(str.size()-p)
44
    std::cout << p << std::endl;
45
  else
46
    std::cout << "Not found" << std::endl;
47
48
  p = findString(str,"Ijk",0,compareFunc2);
49
  if(str.size()-p)
50
    std::cout << p << std::endl;
51
  else
52
    std::cout << "Not found" << std::endl;
53
54
  p = findString(str,"xyz",0,compareFunc2);
55
  if(str.size()-p)
56
    std::cout << p << std::endl;
57
  else
58
    std::cout << "Not found" << std::endl;
59
60
}

von Jens G. (jensig)


Lesenswert?

@Max H. (hartl192)

>In ASCII unterscheiden sich Groß- und Kleinbuchstaben nur durch ein
>bit...
>Ein bitweises OR mit 0b00100000 mach aus jedem Zeichen einen
>Kleinbuchstaben.

Ein String besteht aber nicht nur aus Buchstaben, erst recht nicht nur 
aus Großbuchstaben. Du müsstest als jedes Zeichen prüfen, ob es sich so 
in klein wandeln liese.
Da kannst Du gleich tolower nehmen.

von Rolf Magnus (Gast)


Lesenswert?

Außerdem sind Umlaute auch Buchstaben, aber nicht Teil von ASCII.

Daniel A. schrieb:
>> Ansonsten wäre eine einfache Lösung, beide Strings z.B. komplett in
>> Großbuchstaben zu konvertieren und dann erst die Suche machen.
>
> Finde ich inperformant, und unschön. Ich würde eine Vergleichsfunktion
> übergeben.

Wenn man dann schon C++ hat, bietet sich an, ein Template draus zu 
machen, gerade auch für die Performance.

von Georg (Gast)


Lesenswert?

Rolf Magnus schrieb:
> Außerdem sind Umlaute auch Buchstaben, aber nicht Teil von ASCII.

Und noch schöner: mein Liebling das 'ß', wie in Grossbuchstaben?

Beispiele die nur in USA funktionieren sind praktisch völlig wertlos.

Georg

von Rolf Magnus (Gast)


Lesenswert?

Georg schrieb:
> Rolf Magnus schrieb:
>> Außerdem sind Umlaute auch Buchstaben, aber nicht Teil von ASCII.
>
> Und noch schöner: mein Liebling das 'ß', wie in Grossbuchstaben?

Da gibt's ja immerhin noch die Möglichgkeit einer Sonderbehandlung, 
indem man halt zwei Zeichen draus macht. Aber spätestens umgekehrt ist 
man dann aufgeschmissen (MASSE -> masse oder maße?).

von Heinz B. (Firma: Privat) (hbrill)


Lesenswert?

Das wäre doch ein klassischer Fall für
Reguläre Ausdrücke (RegEx - lib).
Gibt es sowas nicht für C/C++ ?
In meiner Sprache würde das so aussehen :
Print Match$("(?i)Tigerente*[A-Za-z0-9]{1,}", "Ich habe eine tIGerEntE 
zu Hause")

von Kaj (Gast)


Angehängte Dateien:

Lesenswert?

Georg schrieb:
> Beispiele die nur in USA funktionieren sind praktisch völlig wertlos.
Da stimme ich zu.

Rolf Magnus schrieb:
> Georg schrieb:
>> Rolf Magnus schrieb:
>>> Außerdem sind Umlaute auch Buchstaben, aber nicht Teil von ASCII.
>>
>> Und noch schöner: mein Liebling das 'ß', wie in Grossbuchstaben?
>
> Da gibt's ja immerhin noch die Möglichgkeit einer Sonderbehandlung
ja... und was machst du mit allen anderen "Sonderbuchstaben"?
É È ô à usw. ? Allein für den "latin_1"-Bereich gibt es mind. 70 solcher 
"Sonderbuchstaben". Die sind nicht Teil von ASCII... wie viele 
sonderbehandlungen willst du machen?

Daniel A. schrieb:
> Finde ich inperformant, und unschön.
So, du "findest" das es unperformant ist... ich "finde" auch das unsere 
regierung unperformant und unschön ist, aber dieses "empfinden" 
interessiert nicht! Ist es unperformant, oder nicht? Hast du das mal 
getestet? Und was gilt denn als "unperformant"? Da hast du ja bestimmt 
auch mal Zahlenwerte um das vergleichen zu können.

Und warum etwas neu erfinden, was es in den std. libs gibt? Die 
entsprechenden Funktionen sind mit sicherheit nicht in den std. libs 
gelandet, weil sie so super unperformant sind...


An den TO:
Wenn du nicht dazu gezwungen bist C oder C++ zu verwenden, dann nimm 
Python für sowas. Da ist die Stringhandhabung um ein vielfaches 
einfacher als in C oder C++.
1
# Funktioniert mit Python 2.7 und Python 3.x
2
MyString = "Hallo liebes Mikrocontroller.net-Forum"
3
StringToFind = "Bes mIkrO"
4
IsFound = False
5
6
if(StringToFind.lower() in MyString.lower()):
7
  IsFound = True
8
9
print(IsFound)

Heinz Brill schrieb:
> Das wäre doch ein klassischer Fall für
> Reguläre Ausdrücke (RegEx - lib).
Nicht böse gemeint, aber:
"Some people, when confronted with a problem, think: 'I know, I'll use 
regular expressions.' Now they have two problems." - Jamie W. Zawinski
:P
Aber ja, RegEx wäre auch eine Möglichkeit.

Sandra schrieb:
> Nun möchte ich automatisiert ein Textfile nach einem bestimmten String
> durchsuchen z.B. "Tigerente", dabei soll aber auch "tIgerEnte" oder
> "tiGERente" gefunden werden.

Das folgende Programm sagt dir, ob deine Tigerente in der Datei steckt, 
oder nicht.
1
StringToFind = "Tigerente"
2
IsFound = False
3
4
#Datei zum LESEN ("r") oeffnen
5
MeineDatei = open("f:\\Projekte\\python\\test.txt", "r")
6
7
#komplette Dateiinhalt lesen
8
DateiInhalt = MeineDatei.read()
9
10
if( StringToFind.lower() in DateiInhalt.lower() ):
11
  IsFound = True
12
13
#Datei wieder schliesen
14
MeineDatei.close()
15
  
16
print("\nDie Tigerente wurde gefunden: %s" % (str(IsFound)) )

Grüße

von Peter S. (psavr)


Lesenswert?

>> Ansonsten wäre eine einfache Lösung, beide Strings z.B. komplett in
>> Großbuchstaben zu konvertieren und dann erst die Suche machen.
>
>Finde ich inperformant, und unschön. Ich würde eine Vergleichsfunktion
>übergeben.
>
>Ungetestet:
>int16_t compareFunc2(char a,char b){
> if(a>='A'&&a<='Z') a=a-'A'+'a';
> if(b>='A'&&b<='Z') b=b-'A'+'a';


Also ich finde Deine Lösung ist weder schöner noch performanter!

von Yalu X. (yalu) (Moderator)


Lesenswert?

Wenn es wirklich um Performanz geht, sollte man ohnehin einen anderen 
Algorithmus verwenden. Hier sind Beispiele:

  http://de.wikipedia.org/wiki/String-Matching-Algorithmus#.C3.9Cbersicht

Der in diesem Thread bereits in verschiedenen Varianten vorgeschlagene 
Algorithmus wird dort als "naiv" bezeichnet und stellt in den 
allermeisten Fällen die am wenigsten performante Lösung dar.

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.