Initial commit

This commit is contained in:
2025-12-10 12:06:02 +01:00
commit ba74d0f28b
6 changed files with 769 additions and 0 deletions

31
.vscode/c_cpp_properties.json vendored Normal file
View File

@@ -0,0 +1,31 @@
{
"configurations": [
{
"name": "Win64",
"intelliSenseMode": "gcc-x64",
"compilerPath": "C:/MinGW/bin/g++.exe",
"cStandard": "c11",
"cppStandard": "c++17",
"includePath": [
"${workspaceFolder}/**"
]
}
],
"version": 4
}

31
README.md Normal file
View File

@@ -0,0 +1,31 @@
# Mein Konto (kleine Demo)
Kurze Demo-Webseite zur Verwaltung eines Kontostands.
Funktionen
- Kontostand wird in `localStorage` gespeichert (Schlüssel `konto_balance_v1`).
- Anfangswert: 1000 € (kann im `app.js` angepasst werden).
- Eingabefeld für Überweisungsbetrag.
- Validierung:
- keine gültige Zahl -> Fehlermeldung
- > 2000 € -> Abbruch mit Fehlermeldung
- Kontoüberziehung führt zu Warnung "Achtung Konto überzogen"
- Nach erfolgreicher Verarbeitung wird der Betrag abgezogen, Kontostand aktualisiert, Eingabe geleert.
- Kontostand < 0 wird rot angezeigt.
Dateien
- `index.html` einfache UI
- `styles.css` Styles
- `app.js` Logik
Benutzung
1. Lokal öffnen: Datei `index.html` im Browser öffnen.
2. Optional (lokaler Webserver, empfohlen):
```bash
# im Verzeichnis der Dateien
python -m http.server 8000
# dann im Browser öffnen: http://localhost:8000
```
Hinweis: Die Seite merkt sich den Kontostand im Browser. Zum Zurücksetzen `localStorage.removeItem('konto_balance_v1')` in der Konsole ausführen.

462
STRING_METHODS_NOTES.md Normal file
View File

@@ -0,0 +1,462 @@
# JavaScript String-Methoden und -Eigenschaften Notizen
## 1. `length` (Eigenschaft)
Gibt die Anzahl der Zeichen in einem String zurück.
```javascript
const text = "Hallo";
console.log(text.length); // 5
const empty = "";
console.log(empty.length); // 0
const withSpaces = "Hallo Welt";
console.log(withSpaces.length); // 11 (Leerzeichen zählt mit)
```
**Wichtig**: `length` ist eine Eigenschaft, keine Methode keine Klammern!
---
## 2. `indexOf()` und `lastIndexOf()`
### `indexOf(searchValue, fromIndex)`
Sucht ein Zeichen oder Substring von links nach rechts. Gibt den **Index** (Position) zurück. Wenn nicht gefunden: **-1**.
```javascript
const text = "Hallo Welt";
// Einzelnes Zeichen
console.log(text.indexOf("H")); // 0 (erstes Zeichen)
console.log(text.indexOf("o")); // 4 (erste "o")
// Substring
console.log(text.indexOf("Welt")); // 6
console.log(text.indexOf("xyz")); // -1 (nicht gefunden)
// Optional: Startposition angeben
console.log(text.indexOf("l", 3)); // 3 (erste "l" ab Position 3)
```
### `lastIndexOf(searchValue, fromIndex)`
Sucht von rechts nach links gibt **letztes** Vorkommen zurück.
```javascript
const text = "Hallo Welt";
console.log(text.lastIndexOf("o")); // 9 (letzte "o")
console.log(text.lastIndexOf("l")); // 9 (letzte "l")
console.log(text.lastIndexOf("Welt")); // 6
console.log(text.lastIndexOf("xyz")); // -1 (nicht gefunden)
// Optional: Position von rechts
const text2 = "banana";
console.log(text2.lastIndexOf("a", 4)); // 3 (letzte "a" bis Position 4)
```
**Unterschied**:
- `indexOf()` → erstes Vorkommen von links
- `lastIndexOf()` → letztes Vorkommen von rechts
---
## 3. `search()`
Sucht mit **regulärem Ausdruck** (Regex). Gibt Index des ersten Matches zurück, sonst **-1**.
```javascript
const text = "Hallo123Welt";
// Einfache Suche nach Ziffer
console.log(text.search(/\d/)); // 5 (erste Ziffer)
// Groß-/Kleinschreibung ignorieren
console.log(text.search(/welt/i)); // 8
// Mehrere Zeichen
console.log(text.search(/[0-9]+/)); // 5
// Nicht gefunden
console.log(text.search(/xyz/)); // -1
```
**Unterschied zu indexOf()**:
- `indexOf()` → exakte String-Suche, einfach und schnell
- `search()` → Regex-Suche, mächtiger und komplexer
---
## 4. `slice(start, end)`
Extrahiert einen Teil des Strings. `end` ist **exklusiv** (wird nicht mit einbezogen).
```javascript
const text = "Hallo Welt";
// 01234567890
// slice(start)
console.log(text.slice(0)); // "Hallo Welt" (ab Position 0)
console.log(text.slice(6)); // "Welt" (ab Position 6)
// slice(start, end)
console.log(text.slice(0, 5)); // "Hallo" (Position 0 bis 4)
console.log(text.slice(6, 10)); // "Welt" (Position 6 bis 9)
// Negative Indizes (von hinten)
console.log(text.slice(-4)); // "Welt" (letzte 4 Zeichen)
console.log(text.slice(0, -5)); // "Hallo " (alles außer letzten 5)
console.log(text.slice(-4, -1)); // "Wel" (2. bis 4. Zeichen von hinten)
```
**Wichtig**: `slice()` erstellt einen **neuen String**, der ursprüngliche wird nicht verändert!
---
## 5. `substring(start, end)`
Ähnlich wie `slice()`, mit kleinen Unterschieden:
- `end` ist auch **exklusiv**
- Unterstützt **keine negativen Indizes** (werden als 0 interpretiert)
- Vertauscht automatisch `start` und `end`, wenn `start > end`
```javascript
const text = "Hallo Welt";
// Normal
console.log(text.substring(0, 5)); // "Hallo"
console.log(text.substring(6, 10)); // "Welt"
// Ohne end (bis zum Ende)
console.log(text.substring(6)); // "Welt"
// Negative Werte → werden 0
console.log(text.substring(-5, 5)); // "Hallo" (negativ ignoriert)
// Vertauschte Parameter
console.log(text.substring(5, 0)); // "Hallo" (Parameter werden vertauscht)
```
**Unterschied zu slice()**:
- `slice()` → unterstützt negative Indizes, logischer
- `substring()` → keine negativen Indizes, bei Bedarf Parameter vertauschen
---
## 6. `substr()` (Veraltet!)
Extrahiert Zeichen basierend auf **Startposition** und **Länge** (nicht Ende).
```javascript
const text = "Hallo Welt";
console.log(text.substr(0, 5)); // "Hallo" (ab Position 0, Länge 5)
console.log(text.substr(6, 4)); // "Welt" (ab Position 6, Länge 4)
console.log(text.substr(-4)); // "Welt" (letzte 4 Zeichen)
console.log(text.substr(-4, 2)); // "We" (ab -4, Länge 2)
```
**Warnung**: `substr()` ist **deprecated** (veraltet). Nutzen Sie stattdessen `slice()` oder `substring()`!
---
## 7. `replace(searchValue, replaceValue)`
Ersetzt das **erste** Vorkommen eines Strings/Regex durch einen anderen.
```javascript
const text = "Hallo Hallo";
// Einfacher String
console.log(text.replace("Hallo", "Hi"));
// "Hi Hallo" (nur erstes Vorkommen!)
// Mit Regex und "g" Flag (global → alle)
console.log(text.replace(/Hallo/g, "Hi"));
// "Hi Hi" (alle Vorkommen)
// Groß-/Kleinschreibung ignorieren
console.log(text.replace(/hallo/i, "Hi"));
// "Hi Hallo"
```
**Wichtig**:
- `replace()` ersetzt nur das **erste** Vorkommen!
- Für alle: Regex mit `g` Flag verwenden
- Ursprünglicher String wird nicht verändert (neuer String wird zurückgegeben)
```javascript
const result = "abc abc".replace(/abc/g, "xyz");
console.log(result); // "xyz xyz"
```
---
## 8. `toUpperCase()` und `toLowerCase()`
Wandelt String in GROSSBUCHSTABEN oder kleinbuchstaben um.
```javascript
const text = "Hallo Welt";
// Großbuchstaben
console.log(text.toUpperCase()); // "HALLO WELT"
console.log("xyz".toUpperCase()); // "XYZ"
// Kleinbuchstaben
console.log(text.toLowerCase()); // "hallo welt"
console.log("XYZ".toLowerCase()); // "xyz"
// Mit Zahlen und Sonderzeichen
console.log("123!@#".toUpperCase()); // "123!@#" (keine Änderung)
```
**Wichtig**: Original wird nicht verändert!
```javascript
const original = "Test";
const upper = original.toUpperCase();
console.log(original); // "Test" (unverändert!)
console.log(upper); // "TEST"
```
---
## 9. `concat(...strings)`
Verbindet mehrere Strings zu einem neuen String.
```javascript
const str1 = "Hallo";
const str2 = "Welt";
// Mit concat()
console.log(str1.concat(" ", str2)); // "Hallo Welt"
console.log("a".concat("b", "c", "d")); // "abcd"
// Mit mehreren Argumenten
console.log("Hello".concat(" ", "World", "!")); // "Hello World!"
```
**Gleich wie `+` Operator**:
```javascript
const text = "Hallo" + " " + "Welt"; // "Hallo Welt"
const text2 = "Hallo".concat(" ", "Welt"); // "Hallo Welt"
```
**Besser**: In der Praxis ist der `+` Operator oder Template Literals üblicher:
```javascript
const str1 = "Hallo";
const str2 = "Welt";
// + Operator
const result1 = str1 + " " + str2;
// Template Literals (empfohlen)
const result2 = `${str1} ${str2}`;
// concat() (seltener)
const result3 = str1.concat(" ", str2);
```
---
## 10. `trim()`
Entfernt Whitespace (Leerzeichen, Tabs, Zeilenumbrüche) vom **Anfang** und **Ende** eines Strings.
```javascript
const text = " Hallo Welt ";
console.log(text.trim()); // "Hallo Welt" (Außenleerzeichen weg)
console.log(text.length); // 14
console.log(text.trim().length); // 11
// Mit Tabs und Zeilenumbrüchen
const messy = "\t\n Hallo \n\t";
console.log(messy.trim()); // "Hallo"
// Leerzeichen in der Mitte bleiben
const text2 = "Hallo Welt";
console.log(text2.trim()); // "Hallo Welt" (Mitte unverändert)
```
**Wichtig**: `trim()` entfernt nur am **Anfang** und **Ende**, nicht in der Mitte!
**Verwandte Methoden**:
```javascript
const text = " Hallo ";
// trim() beide Seiten
console.log(text.trim()); // "Hallo"
// trimStart() oder trimLeft() nur Anfang
console.log(text.trimStart()); // "Hallo "
// trimEnd() oder trimRight() nur Ende
console.log(text.trimEnd()); // " Hallo"
```
---
## 11. `charAt(index)`
Gibt das Zeichen an einer bestimmten **Position** zurück. Wenn Index ungültig, leerer String `""`.
```javascript
const text = "Hallo";
// 01234
console.log(text.charAt(0)); // "H"
console.log(text.charAt(1)); // "a"
console.log(text.charAt(4)); // "o"
console.log(text.charAt(10)); // "" (zu weit, leerer String)
console.log(text.charAt(-1)); // "" (negative Index erlaubt nicht)
```
**Alternativ: Bracket-Notation** (einfacher):
```javascript
const text = "Hallo";
console.log(text[0]); // "H"
console.log(text[4]); // "o"
console.log(text[10]); // undefined (anders als charAt!)
```
**Unterschied**:
- `charAt(index)` → gibt `""` zurück bei ungültigem Index
- `text[index]` → gibt `undefined` zurück bei ungültigem Index
---
## Vergleich und Zusammenfassung
| Methode | Zweck | Rückgabewert |
|---------|-------|------------|
| `length` | Zeichenanzahl | Zahl |
| `indexOf()` | Erste Position eines Substrings | Index oder -1 |
| `lastIndexOf()` | Letzte Position eines Substrings | Index oder -1 |
| `search()` | Position eines Regex-Matches | Index oder -1 |
| `slice()` | Extrahiert Teil (Anfang bis Ende, exklusiv) | Neuer String |
| `substring()` | Wie slice, aber ohne negative Indizes | Neuer String |
| `substr()` | Extrahiert Teil (Position + Länge) | Neuer String (**veraltet!**) |
| `replace()` | Ersetzt erstes Vorkommen | Neuer String |
| `toUpperCase()` | In Großbuchstaben | Neuer String |
| `toLowerCase()` | In Kleinbuchstaben | Neuer String |
| `concat()` | Verbindet Strings | Neuer String |
| `trim()` | Entfernt äußere Whitespaces | Neuer String |
| `charAt()` | Zeichen an Position | Einzelnes Zeichen oder `""` |
---
## Praktische Beispiele
### Validierung einer E-Mail
```javascript
const email = " user@example.com ";
const cleaned = email.trim().toLowerCase();
if(cleaned.indexOf("@") > 0 && cleaned.indexOf(".") > cleaned.indexOf("@")){
console.log("Gültige E-Mail");
} else {
console.log("Ungültige E-Mail");
}
```
### Dateiname aus Pfad extrahieren
```javascript
const path = "C:/Users/max/dokumente/file.txt";
// Letzten Schrägstrich finden
const lastSlash = path.lastIndexOf("/");
const filename = path.slice(lastSlash + 1);
console.log(filename); // "file.txt"
```
### URL-Parameter bereinigen
```javascript
const url = "https://example.com?id=123&name= Max ";
if(url.indexOf("?") > -1){
const params = url.slice(url.indexOf("?") + 1);
console.log(params); // "id=123&name= Max "
}
```
### Text durchsuchen (Regex)
```javascript
const text = "Kontakt: info@example.com oder 089-1234567";
// E-Mail finden
if(text.search(/@/) > -1){
console.log("E-Mail vorhanden");
}
// Telefonnummer finden
if(text.search(/\d{3}-\d{4}/) > -1){
console.log("Telefon vorhanden");
}
```
---
## Häufige Fehler
### ❌ Falscher Fehler 1: `replace()` ersetzt alle
```javascript
const text = "aaa";
console.log(text.replace("a", "b")); // "baa" nur erstes!
```
**Korrekt**:
```javascript
console.log(text.replace(/a/g, "b")); // "bbb"
```
### ❌ Falscher Fehler 2: `length` ist keine Methode
```javascript
const text = "Hallo";
console.log(text.length()); // TypeError!
```
**Korrekt**:
```javascript
console.log(text.length); // 5
```
### ❌ Falscher Fehler 3: Original wird nicht verändert
```javascript
let text = "hallo";
text.toUpperCase();
console.log(text); // "hallo" immer noch klein!
```
**Korrekt**:
```javascript
let text = "hallo";
text = text.toUpperCase();
console.log(text); // "HALLO"
```
### ❌ Falscher Fehler 4: `substr()` verwenden (veraltet)
```javascript
// Besser nicht:
const text = "Hello";
console.log(text.substr(0, 3)); // "Hel"
// Stattdessen:
console.log(text.slice(0, 3)); // "Hel"
```
---
## Zusammenfassung für die Praxis
1. **Länge prüfen**: `length`
2. **Position suchen**: `indexOf()` oder `lastIndexOf()` (einfach), `search()` (Regex)
3. **Substring extrahieren**: `slice()` (mit negativen Indizes), `substring()` (ohne)
4. **Ersetzen**: `replace()` mit `g` Flag für alle
5. **Groß-/Kleinschreibung**: `toUpperCase()`, `toLowerCase()`
6. **Verbinden**: `+` oder Template Literals (nicht `concat()`)
7. **Bereinigen**: `trim()` für äußere Whitespaces
8. **Einzelnes Zeichen**: `charAt()` oder `[index]`
**Wichtigste Regel**: Strings sind unveränderlich! Alle Methoden geben einen **neuen String** zurück.

134
app.js Normal file
View File

@@ -0,0 +1,134 @@
// ===== STRING-METHODEN BEISPIELE IN DIESER APP =====
//
// 1. trim() Whitespace entfernen (in parseAmount)
// 2. replace() Komma durch Punkt ersetzen (in parseAmount)
// 3. toLowerCase() String zu Kleinbuchstaben (in showMessage)
// 4. length Zeichenanzahl prüfen (in transferBtn.addEventListener)
// 5. concat() und toUpperCase() können Sie in der HTML erweitern
//
// ===== WEITERE STRING-METHODEN =====
// indexOf(), lastIndexOf() Position eines Substrings finden
// slice(), substring() Teile eines Strings extrahieren
// charAt() einzelnes Zeichen an Position
// search() mit Regex suchen
//
// Siehe: STRING_METHODS_NOTES.md für detaillierte Dokumentation
const STORAGE_KEY = 'konto_balance_v1';
const INITIAL_BALANCE = 1000.00; // Anfangswert beliebig
const balanceDisplay = document.getElementById('balanceDisplay');
const amountInput = document.getElementById('amountInput');
const transferBtn = document.getElementById('transferBtn');
const messageDiv = document.getElementById('message');
function readStoredBalance(){
const raw = localStorage.getItem(STORAGE_KEY);
if(raw === null){
localStorage.setItem(STORAGE_KEY, INITIAL_BALANCE.toString());
return INITIAL_BALANCE;
}
const n = parseFloat(raw);
return Number.isFinite(n) ? n : INITIAL_BALANCE;
}
function writeStoredBalance(value){
localStorage.setItem(STORAGE_KEY, value.toString());
}
function formatCurrency(num){
return num.toLocaleString('de-DE', { style: 'currency', currency: 'EUR' });
}
function showMessage(text, type){
messageDiv.textContent = text || '';
// ===== STRING-METHODEN: toLowerCase() =====
// toLowerCase() wandelt String in Kleinbuchstaben um
// Praktisch: Konsistente Vergleiche unabhängig von Groß-/Kleinschreibung
// Beispiel: "ERROR".toLowerCase() → "error"
const normalizedType = (type || '').toLowerCase();
messageDiv.className = '';
if(normalizedType === 'error') messageDiv.classList.add('msg-error');
if(normalizedType === 'warning') messageDiv.classList.add('msg-warning');
if(normalizedType === 'success') messageDiv.classList.add('msg-success');
}
function updateDisplay(){
const bal = readStoredBalance();
balanceDisplay.textContent = formatCurrency(bal);
if(bal < 0){
balanceDisplay.classList.add('negative');
} else {
balanceDisplay.classList.remove('negative');
}
}
function parseAmount(input){
if(!input) return NaN;
// ===== STRING-METHODEN IN AKTION =====
// 1. trim() entfernt äußere Whitespaces (Leerzeichen, Tabs, etc.)
// Praktisch: Benutzereingaben bereinigen
// Beispiel: " 123.45 ".trim() → "123.45"
const trimmed = input.trim();
// 2. replace() ersetzt Zeichen oder Substring
// Akzeptiere sowohl Komma als auch Punkt als Dezimaltrenner
// replace(searchValue, replaceValue) ersetzt ERSTES Vorkommen
// Beispiel: "123,45".replace(',', '.') → "123.45"
const normalized = trimmed.replace(',', '.');
// Alternative: replace() mit Regex und "g" Flag für alle Vorkommen
// const normalized = trimmed.replace(/,/g, '.');
return parseFloat(normalized);
}
transferBtn.addEventListener('click', ()=>{
showMessage('', null);
const raw = amountInput.value;
// ===== STRING-METHODEN: length und indexOf() =====
// length gibt die Anzahl der Zeichen zurück (Eigenschaft, keine Methode!)
// Beispiel: "Hallo".length → 5
// Praktisch: Prüfe ob Eingabe nicht leer ist
if(raw.length === 0){
showMessage('Bitte geben Sie einen Betrag ein.', 'error');
return;
}
const amount = parseAmount(raw);
if(!Number.isFinite(amount) || amount <= 0){
showMessage('Bitte geben Sie einen gültigen Betrag größer als 0 ein.', 'error');
return;
}
if(amount > 2000){
showMessage('Über 2000 € können nicht überwiesen werden. Vorgang abgebrochen.', 'error');
return;
}
const current = readStoredBalance();
const newBalance = +(current - amount).toFixed(2);
if(newBalance < 0){
showMessage('Achtung Konto überzogen', 'warning');
} else {
showMessage('Überweisung erfolgreich.', 'success');
}
writeStoredBalance(newBalance);
updateDisplay();
// ===== STRING-METHODEN: Eingabefeld leeren =====
// Setze den Wert auf einen leeren String ''
// Beispiel: input.value = ''
amountInput.value = '';
amountInput.focus();
});
updateDisplay();

29
index.html Normal file
View File

@@ -0,0 +1,29 @@
<!doctype html>
<html lang="de">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width,initial-scale=1">
<title>Mein Konto</title>
<link rel="stylesheet" href="styles.css">
</head>
<body>
<main>
<h1>Sparrkasse</h1>
<section class="balance">
<label for="balanceDisplay">Kontostand:</label>
<div id="balanceDisplay" class="amount">--</div>
</section>
<section class="transfer">
<label for="amountInput">Überweisungsbetrag</label>
<input id="amountInput" type="text" placeholder="z. B. 120.50" aria-label="Überweisungsbetrag">
<button id="transferBtn">Überweisen</button>
</section>
<div id="message" role="status" aria-live="polite"></div>
</main>
<script src="app.js"></script>
</body>
</html>

82
styles.css Normal file
View File

@@ -0,0 +1,82 @@
:root{
--bg:#f7f7fb;
--card:#ffffff;
--text:#222;
--danger:#c82333;
--warning:#f39c12;
--success:#28a745;
}
*{
box-sizing:border-box
}
body{
font-family:Segoe UI, Roboto, Arial, sans-serif;
background:var(--bg);
color:var(--text);
padding:32px
}
main{
max-width:480px;
margin:0 auto;background:var(--card);
padding:24px;
border-radius:8px;
box-shadow:0 6px 18px rgba(0,0,0,.06)
}
h1{
margin-top:0;
color: red;
}
.balance{
display:flex;
align-items:center;
gap:12px;margin-bottom:16px
}
.balance .amount{
font-weight:700;
font-size:1.4rem;
}
.transfer{
display:flex;
gap:8px;
align-items:center;
margin-bottom:12px
}
input[type="text"]{
flex:1;
padding:8px;
border:1px solid #d7d7df;
border-radius:4px
}
button{
padding:8px 12px;
border:none;
background:red;
color:white;border-radius:4px;
cursor:pointer
}
button:active{
transform:translateY(1px)
}
#message{
min-height:1.6em
}
.msg-error{
color:var(--danger)
}
.msg-warning{
color:var(--warning)
}
.msg-success{
color:var(--success)
}
.negative{
color:var(--danger)
}