# Wie erkennt man Sonderzeichen im String?



## Cookie´sCookies (18. Apr 2017)

Guten morgen zusammen,
Ich bin noch ziemlich neu in der Welt des Programmieren und zur Übung wollte ich ein Programm schreiben, wo man ein Passwort eingibt und es Kreterin erfüllen muss. 
Kreterien: Mind. Ein Großbuchstabe && Mind. Zwei Kleinbuchstabe && Mind. Eine Zahl && Mind. Ein Sondezeichen
Mein Code Sieht wie folgt aus: 

```
import java.util.Scanner;

public class passwortgenerator{
  public static void main(String[] args){
    String wort;
    System.out.println("Geben sie ihr Passwort ein");
    Scanner sc = new Scanner(System.in);
    wort = sc.next();
    char charWort = wort.charAt(0);
    for (int x = 0; x <= wort.length() && wort.length() >=9; x++) {
       
        if(Character.isUpperCase(charWort)){
            if(Character.isLowerCase(charWort)){
                if(Character.isDigit(charWort)){

                }else{
                System.out.print("Fehler");
                }
            }else{
            System.out.print("Fehler");
            }
        }else{
        System.out.print("Fehler");   
      }
    }
  }
}
```

Ich habe nun Zwei Probleme:
1. (Das wichtige) Wie erkennt man, am besten ohne ASCII, ob Sonderzeichen enthalten sind?
2. Wie kann man erkennen, wie oft (z.B.) Kleinbuchstaben enthalten sind?

Es tut mir leid nur ich habe wirklich nichts perfekt passendes gefunden, was funktioniert hat... Ich bedanke mich schon einmal Herzlich für eure Hilfe!
MfG Cookie


----------



## Thallius (18. Apr 2017)

Mit Regex geht das aber das ist noch viel komplizierter als den ASCII Wert zu vergleichen.


----------



## Cookie´sCookies (18. Apr 2017)

Mir wurde gesagt es sei Stilistisch schlecht und ich solle es deshalb nicht benutzen. Aber hättest du ein Tipp für mich für die zweite Frage?


----------



## stg (18. Apr 2017)

Cookie´sCookies hat gesagt.:


> 2. Wie kann man erkennen, wie oft (z.B.) Kleinbuchstaben enthalten sind?



Zählen...


----------



## Cookie´sCookies (18. Apr 2017)

Dankeschön  

Ist die Überprüfung des Sonderzeichens so Korrekt?

```
if(wort.charAt(x)<=47 || wort.charAt(x)>=58 && wort.charAt(x)<=64 || wort.charAt(x)>=91 && wort.charAt(x)<=96 || wort.charAt(x)>=123 ){   
                    }else{
                    System.out.print("Mindestens ein Sonderzeichen muss Enthalten sein.");  
                    }
```


----------



## JStein52 (18. Apr 2017)

Cookie´sCookies hat gesagt.:


> Wie erkennt man, am besten ohne ASCII, ob Sonderzeichen enthalten sind?


Die Character-Klasse bietet da doch genug Methoden, für diesen Fall würde sich doch 
	
	
	
	





```
if (!Character.isLetterOrDigit(...))
```
 anbieten


----------



## VfL_Freak (18. Apr 2017)

Moin,



Cookie´sCookies hat gesagt.:


> Ist die Überprüfung des Sonderzeichens so Korrekt?
> 
> ```
> if(wort.charAt(x)<=47 || wort.charAt(x)>=58 && wort.charAt(x)<=64 || wort.charAt(x)>=91 && wort.charAt(x)<=96 || wort.charAt(x)>=123 )
> ...


Im Prinzip würde es funktionieren, wobei ich die leere IF-Anweisung sehr unschön/unleserlich finde!
Du könntest die Prüfungen andersherum prüfen und dadurch das ELSE sparen !

Aber Du hast oben noch einen Denkfehler in der IF-Verschachtelung:

```
if(Character.isUpperCase(charWort))
{
    if(Character.isLowerCase(charWort))
    {
        if(Character.isDigit(charWort))
        {}
        else
        {
            System.out.print("Fehler");
        }
    }
    else
    {
        System.out.print("Fehler");
    }
}
else
{
    System.out.print("Fehler"); 
}
```
Du prüfst hier ja zunächst auf 'UpperCase'.
Wenn es KEIN Uppercase ist, gehst Du sofort mit der Ausgabe "Fehler" raus!
Die anderen Fälle ('LowerCase' und 'Digit') werden dann nicht mehr geprüft!
Wenn es aber ein Uppercase ist, dann machen die weiteren  Prüfungen auf 'LowerCase' und 'Digit' nicht wirklich Sinn (entweder IST ein Großbuchstabe oder nicht) - zumal dann immer FEHLER ausgegeben würde !!

Gruß Klaus


----------



## Cookie´sCookies (18. Apr 2017)

Aber wird damit nicht nur Abgefragt Ob ein Buchstabe oder eine Zahl enthalten ist?


----------



## VfL_Freak (18. Apr 2017)

Cookie´sCookies hat gesagt.:


> Aber wird damit nicht nur Abgefragt Ob ein Buchstabe oder eine Zahl enthalten ist?


Nein ..... 
Was ist denn 'letter' und was ist 'digit' ??? 

Gruß Klaus


----------



## JStein52 (18. Apr 2017)

Cookie´sCookies hat gesagt.:


> Aber wird damit nicht nur Abgefragt Ob ein Buchstabe oder eine Zahl enthalten ist?


Falls du mich meinst: es wird abgeprüft ob *kein *Buchstabe oder Zahl enthalten ist.


----------



## Cookie´sCookies (18. Apr 2017)

VfL_Freak hat gesagt.:


> Moin,
> 
> Du prüfst hier ja zunächst auf 'UpperCase'.
> Wenn es KEIN Uppercase ist, gehst Du sofort mit der Ausgabe "Fehler" raus!
> ...


Es ist ja ein String der an mehreren Stellen geprüft werden soll ( in diesem Fall ein Passwort ) und es soll geprüftwerden ob dies Alles vorhanden ist. Wenn ich einen Logik Fehler habe könntest du mir ja evtl. einen Tipp geben?


----------



## VfL_Freak (18. Apr 2017)

Du prüfst ja jeweils nur EIN Zeichen des Strings, nicht alles auf einmal !
Also für EIN Zeichen könntest Du es bei Deinem Ansatz so prüfen:

```
if( !Character.isUpperCase(charWort) && !Character.isLowerCase(charWort) && !Character.isDigit(charWort) )
{
    // hier weißt Du jetzt, dass das zeichen KEIN Groß- oder Kleinbuchstabe oder Digit ist!!
}
```
Jetzt musst Dir nur noch überlegen, wie Du das für alle Zeichen prüfst und dabei merkst, ob eines der Kriterien für das ganze Wort nicht erfüllt ist!

Gruß Klaus


----------



## Cookie´sCookies (18. Apr 2017)

@VfL_Freak 
Gibt es eine Möglichkeit das Ganze Wort zu prüfen? 


Und Falls ich dich Fragen darf, deine Signatur 





> * Der Pessimist sagt "Schlimmer kann es nicht mehr werden ...", der Optimist sagt "DOCH, es kann !!" *


Kommt die von Nico Semsrott?


----------



## VfL_Freak (18. Apr 2017)

Moin,



Cookie´sCookies hat gesagt.:


> Gibt es eine Möglichkeit das Ganze Wort zu prüfen?


in dem Du jedes einzelne Zeichen des Wortes prüfst (Stichwort: Schleife) ?? 



Cookie´sCookies hat gesagt.:


> Kommt die (... Signatur ...) von Nico Semsrott?


eher nicht - das ist ziemlich alt von Jürgen von der Lippe !

Gruß Klaus


----------



## JStein52 (18. Apr 2017)

Cookie´sCookies hat gesagt.:


> Gibt es eine Möglichkeit das Ganze Wort zu prüfen?


Ja, klar, mit regular Expression

Edit: und wenn du googlest findest du bestimmt eine passende für Passworte


----------



## JarJarBinks (18. Apr 2017)

Du könntest mit string.matches(regex) und einem regulären Ausdruck arbeiten.
Hier ein Link zum Tutorial für reguläre Ausdrücke:
http://www.vogella.com/tutorials/JavaRegularExpressions/article.html

Hier ein Link zum Testen deiner Ausdrücke:
http://www.regexplanet.com/advanced/java/index.html

Gruß
Jar


----------



## JStein52 (18. Apr 2017)

Und hier der reguläre Ausdruck:


```
matches("^(?=.*[0-9])(?=.*[a-z])(?=.*[A-Z])(?=.*[\\\\!§$%&/()\\[\\]{}=?ß#.:,;-<>|°+*@]).{8,20}$"));
```
Wobei die zulässigen Sonderzeichen in der letzten eckigen Klammer einzeln aufgeführt sind. Wo notwendig mit Backslashes entwertet

Edit: und die Länge eines Passwortes ist auf 8..20 Zeichen festgelegt


----------



## Thallius (18. Apr 2017)

JStein52 hat gesagt.:


> Und hier der reguläre Ausdruck:
> 
> 
> ```
> ...



Aber irgendwie krank ist das schon oder nicht?


----------



## JStein52 (18. Apr 2017)

Thallius hat gesagt.:


> Aber irgendwie krank ist das schon oder nicht?


Kommt drauf an ...  wenn man regex mag ist es einfach. Im übrigen löst es halt alles auf einen Streich. Wenn du das auscodierst wird es auch krank.

Edit: im übrigen liest es sich doch wunderschön:
mindestens 1 Ziffer, mindestens 1 Kleinbuschstabe, mindestens 1 Grossbuchstabe und mindestens 1 Sonderzeichen aus der Menge ......  und das ganze 8 - 20 Zeichen lang. Das kannst du dem Benutzer auch noch schön in einer Infobox anzeigen. Und ist mehr oder weniger der Standard für Passworte


----------



## VfL_Freak (18. Apr 2017)

Moin,
bliebe nur die Frage, ob dies einem Newbie 


Cookie´sCookies hat gesagt.:


> Ich bin noch ziemlich neu in der Welt des Programmieren


wirklich weiter hilft ... 
Gruß Klaus


----------



## JStein52 (18. Apr 2017)

VfL_Freak hat gesagt.:


> ob dies einem Newbie
> wirklich weiter hilft ...


Na ja, 1 Stunde regex lesen. Es sieht ja schwieriger aus als es ist. Siehe mein Edit oben.


----------



## JStein52 (18. Apr 2017)

JStein52 hat gesagt.:


> Und ist mehr oder weniger der Standard für Passworte


Genau so wie es Standard regex im Internet für email-Adresse, URL usw. gibt. Warum immer per Hand kodieren ?


----------



## Cookie´sCookies (18. Apr 2017)

Ich habe das Problem nun etwas anders gelöst:

```
public boolean istGueltig() {   

        int großbuchstabe = 0; 
        int kleinbuchstabe = 0;
        int zahl = 0;
        int sonderzeichen = 0;

        for (int x = 0; x < wort.length() && wort.length() >= 9; x++) {
            if (Character.isUpperCase(wort.charAt(x))) {
                großbuchstabe++;
            }
            if (Character.isLowerCase(wort.charAt(x))) {
                kleinbuchstabe++;
            }
            if (Character.isDigit(wort.charAt(x))) {
                zahl++;
            }
            if (!Character.isLetterOrDigit(wort.charAt(x))) {
                sonderzeichen++;
            }
        }

        return großbuchstabe >= 2 && kleinbuchstabe >= 2 && zahl >= 2 && sonderzeichen >= 2;

    }
```

Also es ist für mich die beste lösung gewesen und danke den anderen für die Hilfe, Außerdem hoffe ich ich kann noch jemanden hiermit helfen.


Tipps:
isUpperCase -> Testet auf Großbuchstaben
isLowerCase -> Testet auf Kleinbuchstaben
isDigit -> Testet auf Zahlen
!(not) isLetterOrDiggit  -> Testet auf Sonderzeichen ( Alles außer Buchstaben und Zahlen )


----------



## VfL_Freak (18. Apr 2017)

Moin,

na, sieht doch soweit prima aus!

Tipp: ich würde dies hier


Cookie´sCookies hat gesagt.:


> return großbuchstabe >= 2 && kleinbuchstabe >= 2 && zahl >= 2 && sonderzeichen >= 2;


immer noch zusätzlich klammern ...


Cookie´sCookies hat gesagt.:


> return( (großbuchstabe >= 2) && (kleinbuchstabe >= 2) && (zahl >= 2) && (sonderzeichen >= 2) );


Das ist hier zwar grundsätzlich obsolet, schafft aber Leserlichkeit und vermeidet ggf. Fehler (etwa wenn etwas geändert wird).

Allerdings werden Deine eingangs beschriebenen Kriterien


Cookie´sCookies hat gesagt.:


> Kreterien: Mind. Ein Großbuchstabe && Mind. Zwei Kleinbuchstabe && Mind. Eine Zahl && Mind. Ein Sondezeichen


nicht wirklich erfüllt, da Du jetzt nur dann TRUE ausgibst, wenn von allen vier Zeichenarten mindestens _*zwei*_ vorhanden sind !!
Du kannst dies ja zur Übung auch mal korrigieren!

Gruß Klaus


----------



## Cookie´sCookies (20. Apr 2017)

Danke @VfL_Freak, Ich habe mir die Kriterien (Für meine Maße) etwas erschwert um mehr Übung vom Praktischem zu bekommen, falls ich etwas Verwirrung dadurch gestiftet habe tut mir das leid und ich Korrigiere die Kriterien in der Frage falls weitere Anfänger dies auch als Übung benutzen wollen. Weiterhin Danke für den Tipp damit mein Code Leserlicher wird.





> return( (großbuchstabe >= 2) && (kleinbuchstabe >= 2) && (zahl >= 2) && (sonderzeichen >= 2) );


Ich hoffe, ich habe die meisten oder alle Forums Regeln beachtet und freue mich weiterhin mich hier zu bereichern. 
Lg Cookie


----------



## VfL_Freak (20. Apr 2017)

Moin,

hmm, jetzt bin ich endgültig verwirrt ....
Gilt denn nun das eingangs beschriebene Kriterium oder nicht ??

Gruß Klaus


----------



## Cookie´sCookies (21. Apr 2017)

Also am Anfang haben die Kriterien die Oben standen gegolten, aber um mir selber alles etwas zu erschweren habe ich gesagt das jedes Kriterium 2x Vorkommen muss.

Mit den Oben stehenden Kriterien sieht der Code wie Folgt aus:


```
public boolean istGueltig() {   

        int keinbuchstabe = 0;  
        int kleinbuchstabe = 0;
        int zahl = 0;
        int sonderzeichen = 0;

        for (int x = 0; x < wort.length() && wort.length() >= 9; x++) {
            if (Character.isUpperCase(wort.charAt(x))) {
                großbuchstabe++;
            }
            if (Character.isLowerCase(wort.charAt(x))) {
                 kleinbuchstabe++;
            }
            if (Character.isDigit(wort.charAt(x))) {
                zahl++;
            }
            if (!Character.isLetterOrDigit(wort.charAt(x))) {
               sonderzeichen++;
            }
        }

        return ((großbuchstabe>0) && (kleinbuchstabe >= 2) && (zahl>0) && (sonderzeichen>0)); //Rückgabe von

    }
```

Tut mir leid für die Verwirrung


----------

