Softwareentwicklung



Programmiersprache

Definition

Programmiersprache (Programmiersprache) ist eine Brücke zwischen Menschen und Computern. Es wird verwendet, um Anweisungen zu schreiben, Computeroperationen zu steuern und verschiedene Anwendungen zu implementieren.

Einstufung

gängige Programmiersprachen

Faktoren, die bei der Auswahl einer Sprache zu berücksichtigen sind

Anwendungsgebiete von Programmiersprachen

Studienvorschläge



Umfassende Linkliste zur Programmentwicklung

  • Microsoft Technology Learning Center/Microsoft Learn
  • vscode/Vidual Studio Code
  • Meta-/Facebook-Entwickler
  • Chrome-Entwickler

    Ranking der Programmiersprachen

    Laut der neuesten Rangliste der Programmiersprachen sind hier die 20 besten Programmiersprachen im Jahr 2024:



    Lambda-Ausdruck

    1. Was ist ein Lambda-Ausdruck?

    Ein Lambda-Ausdruck ist eine anonyme Funktion, die häufig zur Vereinfachung von Code verwendet wird, insbesondere wenn Sie kleine Funktionen oder Rückrufe übergeben müssen. Die Syntax des Lambda-Ausdrucks ist prägnant und die Funktionslogik kann in einer Zeile definiert werden. Lambda-Ausdrücke kommen am häufigsten vor in Sprachen wie C++, JavaScript, Python und C#.

    2. Grundlegende Syntax von Lambda-Ausdrücken

    Die grundlegende Syntax von Lambda-Ausdrücken umfasst normalerweise Parameter und Pfeilsymbole=>und Funktionskörper, zum Beispiel:

    (Parameter) => Funktionskörper

    Die genaue Syntax variiert von Sprache zu Sprache, zum Beispiel:

    3. Beispiele für Lambda-Ausdrücke in verschiedenen Sprachen

    C++-Beispiel

    
    #include <iostream>
    #include <vector>
    #include <algorithm>
    
    int main() {
        std::vectorZahlen = {1, 2, 3, 4, 5};
    
        // Lambda-Ausdruck verwenden, um die Summe gerader Zahlen zu berechnen
        int Summe = 0;
        std::for_each(numbers.begin(), zahlen.end(), [&sum](int n) {
            if (n % 2 == 0) sum += n;
        });
    
        std::cout << „Die Summe gerader Zahlen:“ << Summe << std::endl;
        0 zurückgeben;
    }

    Python-Beispiel

    # Verwenden Sie den Lambda-Ausdruck, um die Summe zweier Zahlen zu berechnen
    add = Lambda x, y: x + y
    print(add(5, 10)) # Ausgabe: 15

    C#-Beispiel

    
    using System;
    using System.Collections.Generic;
    using System.Linq;
    
    class Program {
        static void Main() {
            List numbers = new List{ 1, 2, 3, 4, 5 };
            
            // Verwenden Sie einen Lambda-Ausdruck, um gerade Zahlen herauszufiltern und die Summe zu berechnen
            int sum = zahlen.Where(n => n % 2 == 0).Sum();
            
            Console.WriteLine($"Die Summe der geraden Zahlen: {sum}");
        }
    }

    4. Anwendungsszenarien von Lambda-Ausdrücken

    5. Vor- und Nachteile



    Reflection

    Konzept

    Reflection ermöglicht es Programmen, während der Ausführung Typen (Kategorien/Strukturen), Eigenschaften, Felder, Methoden und Anmerkungen (Metadaten) dynamisch zu überprüfen und zu bearbeiten. Der genaue Typ muss zur Kompilierungszeit nicht bekannt sein, um Member zu lesen und zu schreiben oder Methoden aufzurufen.

    Häufige Verwendungen

    Vor- und Nachteile

    Status der Sprachunterstützung

    Typisches Beispiel

    # Python: Objekteigenschaften auflisten und lesen
    Klassenbenutzer:
        def __init__(self): self.id = 0; self.name = "Ann"
    u = Benutzer()
    für k, v in vars(u).items():
        print(k, v) # id 0 / name Ann
    // C#: Holen Sie sich das Feld/die Eigenschaft und lesen Sie den Wert
    Verwenden des Systems;
    Verwenden von System.Reflection;
    
    var t = typeof(MyType);
    foreach (var p in t.GetProperties(BindingFlags.Instance|BindingFlags.Public|BindingFlags.NonPublic))
        Console.WriteLine($"{p.Name}={p.GetValue(obj)}");
    // JavaScript: dynamische Aufzählung und Aufruf
    const obj = { x: 1, y: 2, add(){ return this.x + this.y; } };
    for (const [k,v] of Object.entries(obj)) console.log(k, v);
    console.log(obj["add"]()); // 3
    // Java: Felder mithilfe von Reflektion lesen/schreiben
    import java.lang.reflect.*;
    Klasse U { private int id = 42; }
    U u = neues U();
    Feld f = U.class.getDeclaredField("id");
    f.setAccessible(true);
    System.out.println(f.getInt(u)); // 42
    // Los: Besuchsstruktur widerspiegeln
    „reflektieren“ importieren
    func Dump(v any) {
        val := reflektieren.ValueOf(v)
        für i := 0; ich < val.NumField(); i++ {
            name := val.Type().Field(i).Name
            fmt.Println(name, val.Field(i).Interface())
        }
    }

    Best Practices

    Wann sollte man es vermeiden?



    Überprüft, ob eine Struktur nur aus Nullen besteht

    Konzeptzusammenfassung

    Vergleich der Sprachunterstützung

    SpracheUnterstützungveranschaulichen
    PythonDynamische, vollständige Reflexion, einfache rekursive Objekt-/Behälterinspektion.
    JavaScript / TypeScriptDas Objekt ist ein Schlüsselwert und verfügbarObject.valuesRekursion.
    Rubyinstance_variablesreflektierendes Element.
    PHPget_object_vars()Oder Reflexion.
    C# (.NET)Reflection erhält Felder/Eigenschaften und weist eine gute Typsicherheit auf.
    Javajava.lang.reflectScanbare Felder.
    KotlinDie JVM-Reflexion ist vollständig, ähnlich wie bei Java.
    GoreflectZugänglich für Strukturfelder.
    SwiftMirrorBesuche sind möglich, aber die Szenen sind begrenzt und eine zusätzliche Bearbeitung ist erforderlich.
    C++ (bis C++23)Keine Laufzeitreflexion, Sie müssen Prüfungen für Typen manuell schreiben.
    RustKeine Laufzeitreflexion, oft implementiert durch Derive/Trait.

    Python-Beispiel

    def is_all_zero(obj, eps=1e-6):
        if isinstance(obj, (int, float)): # Grundlegender numerischer Wert
            return abs(obj) < eps
        elif isinstance(obj, (list, tuple, set)): # sequence/set
            return all(is_all_zero(x, eps) für x in obj)
        elif isinstance(obj, dict): # Wörterbuch
            return all(is_all_zero(v, eps) für v in obj.values())
        elif hasattr(obj, "__dict__"): # Allgemeine Objekte
            all(is_all_zero(v, eps) für v in vars(obj).values()) zurückgeben
        sonst:
            Gibt False zurück
    
    # Test
    Klassenpunkt:
        def __init__(self, x=0, y=0): self.x, self.y = x, y
    Klassenzeile:
        def __init__(self, p1=None, p2=None):
            self.p1 = p1 oder Point()
            self.p2 = p2 oder Point()
    
    print(is_all_zero([[0,0],[0,0]])) # True
    print(is_all_zero(Line(Point(0,0),Point(0,0)))) # True
    print(is_all_zero(Line(Point(1,0),Point(0,0)))) # False

    JavaScript-Beispiele

    Funktion isAllZero(obj, eps = 1e-6) {
      const isNumZero = n => Math.abs(n) < eps;
      if (typeof obj === "number") return isNumZero(obj);
      if (Array.isArray(obj)) return obj.every(v => isAllZero(v, eps));
      if (obj && typeof obj === "object")
        return Object.values(obj).every(v => isAllZero(v, eps));
      return false;
    }
    
    console.log(isAllZero([[0,0],[0,0]])); // wahr
    console.log(isAllZero({x:0, y:{z:0}})); // wahr
    console.log(isAllZero({x:0.000001, y:0})); // hängt von EPS ab

    C# (.NET) Beispiel

    Verwenden des Systems;
    mit System.Linq;
    Verwenden von System.Reflection;
    
    öffentliche statische Klasse ZeroCheck {
        public static bool IsAllZero(object obj, double eps = 1e-6) {
            if (obj == null) return true;
            Schalter (obj) {
                case int i: return i == 0;
                case long l: return l == 0;
                case float f: return Math.Abs​​(f) < eps;
                case double d: return Math.Abs​​(d) < eps;
            }
    
            var t = obj.GetType();
            if (t.IsArray)
                return ((Array)obj).Cast<object>().All(x => IsAllZero(x, eps));
    
            //Felder und Attribute scannen
            foreach (var f in t.GetFields(BindingFlags.Instance|BindingFlags.Public|BindingFlags.NonPublic))
                if (!IsAllZero(f.GetValue(obj), eps)) return false;
    
            foreach (var p in t.GetProperties(BindingFlags.Instance|BindingFlags.Public|BindingFlags.NonPublic))
                if (p.CanRead && !IsAllZero(p.GetValue(obj, null), eps)) return false;
    
            return true;
        }
    }

    Gehen Sie Beispiele

    package main
    
    import (
        "math"
        "reflect"
    )
    
    func IsAllZero(v interface{}, eps float64) bool {
        val := reflect.ValueOf(v)
        switch val.Kind() {
        case reflect.Float32, reflect.Float64:
            return math.Abs(val.Float()) < eps
        case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
            return val.Int() == 0
        case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
            return val.Uint() == 0
        case reflect.Slice, reflect.Array:
            for i := 0; i < val.Len(); i++ {
                if !IsAllZero(val.Index(i).Interface(), eps) { return false }
            }
            return true
        case reflect.Map:
            for _, k := range val.MapKeys() {
                if !IsAllZero(val.MapIndex(k).Interface(), eps) { return false }
            }
            return true
        case reflect.Struct:
            for i := 0; i < val.NumField(); i++ {
                if !IsAllZero(val.Field(i).Interface(), eps) { return false }
            }
            return true
        case reflect.Pointer, reflect.Interface:
            if val.IsNil() { return true }
            return IsAllZero(val.Elem().Interface(), eps)
        default:
            return false
        }
    }
    

    C++/Rust-Einschränkungen und -Praktiken

    Praktische Vorschläge



    Nachrichtenwarteschlange

    Definition und Funktion

    Message Queue (MQ) ist ein Architekturmuster für die asynchrone Kommunikation zwischen Softwaresystemen. Es ermöglicht unabhängigen Anwendungen oder Diensten den Austausch von Informationen durch Senden und Empfangen von Nachrichten, ohne dass sie sich gegenseitig direkt anrufen oder sich auf den Echtzeitstatus des jeweils anderen verlassen müssen. Die Kernaufgabe von MQ besteht darin, als mittlere Schicht zu fungieren, die Nachrichten vorübergehend speichert, bis der beabsichtigte Empfänger bereit ist, sie zu verarbeiten.

    Hauptkomponenten

    Gängige Nachrichtenmuster

    Schemaname beschreiben Typische Anwendungsszenarien
    Punkt-zu-Punkt (P2P) Eine Nachricht wird an eine Warteschlange gesendet und **nur ein** Empfänger nimmt sie aus der Warteschlange und konsumiert die Nachricht. Sobald die Nachricht verbraucht ist, wird sie gelöscht. Auftragsabwicklung, Aufgabenverteilung und Arbeitslastverteilung.
    Veröffentlichen/Abonnieren, Pub/Sub Eine Nachricht wird zu einem Thema veröffentlicht und **alle** Empfänger (Abonnenten), die das Thema abonniert haben, erhalten eine Kopie der Nachricht. Übertragung von Systemereignissen, Protokollerfassung, Benachrichtigung über Datenänderungen.

    Hauptvorteile von Message Queuing

    Abschluss

    Nachrichtenwarteschlangen sind der Grundstein moderner verteilter Systeme, Microservices-Architekturen und Hochverfügbarkeitsanwendungen. Es verbessert die Belastbarkeit, Skalierbarkeit und Robustheit des Systems erheblich, indem es zeitliche und räumliche Indirektion einführt.



    Message Queuing vs. HTTP-API

    Unterschiede in den Kommunikationsmodi

    Merkmal Nachrichtenwarteschlange (MQ) HTTP API (REST/RPC)
    Kommunikationstyp Asynchron Synchron
    Kupplung Geringe Kopplung (Sender und Empfänger interagieren nicht direkt) Hohe Kopplung (der Client muss die Adresse des Servers kennen und auf eine Antwort warten)
    Datenfluss In eine Richtung, über den Zwischenmakler geleitet Bidirektional, Anfrage und Antwort (Request-Response)
    Fehlertoleranz Hoch: Der Broker speichert die Nachricht und die Nachricht geht nicht verloren, auch wenn der Empfänger offline ist. Niedrig: Der Server ist offline oder es kommt zu einer Zeitüberschreitung, wodurch die Anforderung fehlschlägt.
    Skalierbarkeit Hohe, mehrere Verbraucher können problemlos hinzugefügt werden, um die Last zu bewältigen Relativ niedrig, da für die Verteilung von Anfragen der Load Balancer verwendet wird

    Anwendbarer Situationsvergleich

    Vorteile und Anwendungsszenarien von Message Queuing (MQ)

    Vorteile und Anwendungsszenarien der HTTP-API

    abschließend

    MQ und HTTP API sind keine Ersatztechnologien, sondern für unterschiedliche Probleme konzipiert.

    In modernen verteilten Systemen existieren die beiden Modi oft nebeneinander und kooperieren miteinander, um unterschiedliche Geschäftsanforderungen zu erfüllen.




    Anwendungsbeispiele passend für Message Queues

    1. Asynchrone Aufgabenverarbeitung

    In vielen Netzwerkanwendungen sind einige Vorgänge zeitaufwändig, und wenn Benutzer gleichzeitig warten müssen, führt dies zu einer schlechten Benutzererfahrung. MQ ermöglicht die asynchrone Ausführung dieser Aufgaben.

    2. Reduzierung und Pufferung von Verkehrsspitzen

    MQ ist bei der Bewältigung vorübergehender Szenarien mit hohem Datenverkehr von entscheidender Bedeutung und kann Backend-Dienste vor Abstürzen schützen.

    3. Systementkopplung und Microservice-Kommunikation

    In komplexen verteilten Systemen und Microservice-Architekturen wird MQ verwendet, um Dienste zu isolieren und gegenseitige Abhängigkeiten zu reduzieren.

    4. Protokollerfassung und -überwachung

    Sammeln Sie große Mengen an Protokolldaten von Front-End-Anwendungen oder Servern in einem zentralen Verarbeitungssystem.

    5. Daten-Streaming-Verarbeitung

    Insbesondere MQ-/Streaming-Plattformen mit hohem Durchsatz wie Apache Kafka eignen sich ideal für die Verarbeitung kontinuierlicher Echtzeitdatenströme.



    HTTP-API überträgt Bilder und Videos

    Herausforderungen bei der Übertragung großer Binärdaten

    Die größten Herausforderungen bei der Verwendung der HTTP-API zur Übertragung großer Binärdaten (Binärdaten) wie Bilder und Videos sind:

    HTTP-API-Methode zum Hochladen (Senden) von Bildern/Videos

    1. Verwenden Sie das Multipart-/Formulardatenformat (am häufigsten zum Hochladen von Dateien verwendet).

    Dies ist die standardmäßigste und gebräuchlichste Methode für einen Browser oder eine Clientanwendung zum Hochladen von Dateien.

    2. Verwenden Sie den Binärkörper direkt

    Wenn Sie nur eine einzelne Datei hochladen müssen, können Sie den binären Inhalt der Datei direkt als Betreff der Anfrage verwenden.

    3. Base64-Kodierung verwenden (nicht empfohlen für große Dateien)

    Konvertieren Sie Binärdaten in ASCII-Strings und betten Sie sie zur Übertragung in Textformate wie JSON oder XML ein.

    HTTP-API-Methode zum Herunterladen (Empfangen) von Bildern/Videos

    Das Herunterladen von Binärdaten ist relativ einfach. Der Server gibt den ursprünglichen Binärinhalt der Datei direkt als Textkörper der HTTP-Antwort (Response Body) zurück.

    Optimierung der Videoübertragung: Chunked-Übertragung und Streaming

    Bei besonders großen Dateien (insbesondere Videos) werden die folgenden Techniken zur Verbesserung der Zuverlässigkeit und Effizienz empfohlen:



    Streaming-Schlüsseltechnologien

    1. Transportprotokolle (Protokolle)

    Der Kern der Streaming-Übertragung besteht darin, Audio- und Videoinhalte effizient, stabil und mit geringer Latenz vom Server zum Client zu übertragen.

    2. Kerntechnologien und -konzepte

    Adaptives Bitraten-Streaming (ABR)

    Dies ist der Grundstein moderner Streaming-Dienste. Der Server kodiert denselben Videoinhalt in mehrere Versionen unterschiedlicher Qualität (Bitrate, Auflösung).

    Content Delivery Network (CDN)

    CDN ist für Streaming-Dienste, die sich an globale Benutzer richten, unverzichtbar.

    Audio- und Video-Codecs (Codecs)

    Wird zum Komprimieren und Dekomprimieren von Audio- und Videodaten verwendet, um die Dateigröße zu reduzieren.

    3. Inhaltsschutz und Monetarisierung



    Shell

    Bash - $?

    In Bash $? stellt den Exit-Statuscode (Exit Status) des zuletzt ausgeführten Befehls dar. Dies ist ein ganzzahliger Wert, der normalerweise verwendet wird, um festzustellen, ob der vorherige Befehl erfolgreich ausgeführt wurde.

    Die Bedeutung des Exit-Statuscodes

    Beispiel 1: Überprüfung erfolgreich ausgeführter Befehle

    #!/bin/bash
    ls
    echo „Der Exit-Statuscode des vorherigen Befehls war: $?“

    In diesem Beispiel,lsDer Befehl listet den Verzeichnisinhalt auf. Nach erfolgreicher Ausführung,$?Der Wert wird 0 sein.

    Beispiel 2: Auf fehlgeschlagene Befehle prüfen

    #!/bin/bash
    ls /nichtexistentes-Verzeichnis
    echo „Der Exit-Statuscode des vorherigen Befehls war: $?“

    In diesem Beispiel,lsDer Versuch, ein nicht vorhandenes Verzeichnis aufzulisten, schlägt fehl.$?Der Wert von wird eine Zahl ungleich Null sein.

    Beispiel 3: Verwendung des Exit-Statuscodes für eine bedingte Beurteilung

    #!/bin/bash
    cp file1.txt /some/directory/
    wenn [ $? -eq 0 ]; dann
        echo „Datei erfolgreich kopiert.“
    sonst
        echo „Dateikopie fehlgeschlagen.“
    fi

    In diesem Beispiel wird basierend auf dem Exit-Status des Befehls bestimmt, welche Meldung angezeigt werden soll.



    Bash wenn

    Grundgrammatik

    if [Bedingung]; dann
        Anweisungen
    fi

    Verwenden Sie AND

    Um in if mehrere Bedingungen gleichzeitig zu erfüllen, verwenden Sie:

    1. Verwendung-a(veraltet, aber verfügbar)

    if [ "$a" -gt 0 -a "$b" -gt 0 ]; dann
        echo „a und b sind beide größer als 0“
    fi

    2. Verwendung[[ ]] &&(empfehlen)

    if [[ "$a" -gt 0 && "$b" -gt 0 ]]; dann
        echo „a und b sind beide größer als 0“
    fi

    3. Verwenden Sie mehrere if-Kombinationen&&

    if [ "$a" -gt 0 ] && [ "$b" -gt 0 ]; dann
        echo „a und b sind beide größer als 0“
    fi

    Verwenden Sie OR

    Es kann ausgeführt werden, solange eine der Bedingungen erfüllt ist:

    1. Verwendung-o(veraltet, aber verfügbar)

    if [ "$a" -eq 0 -o "$b" -eq 0 ]; dann
        echo „a oder b ist 0“
    fi

    2. Verwendung[[ ]] ||(empfehlen)

    if [[ "$a" -eq 0 || "$b" -eq 0 ]]; dann
        echo „a oder b ist 0“
    fi

    3. Verwenden Sie mehrere if-Kombinationen||

    if [ "$a" -eq 0 ] || [ "$b" -eq 0 ]; dann
        echo „a oder b ist 0“
    fi

    Mischen Sie UND und ODER

    Kann mit Klammern verwendet werden, um die Priorität zu steuern:

    if [[ ( "$a" -gt 0 && "$b" -gt 0 ) || "$c" -eq 1 ]]; dann
        echo „a und b sind beide größer als 0 oder c ist gleich 1“
    fi

    Häufige Verwendung von NOT

    In Bash,ifAnweisungen werden normalerweise mit gepaart[ ](Testbefehl) oder[[ ]](Erweiterter Testbefehl) wird verwendet. Um NICHT auszudrücken, verwenden Sie ein Ausrufezeichen!

    Wenn [ ! Zustand ]; dann
        # Code, der ausgeführt werden soll, wenn die Bedingung falsch ist
    fi

    1. Prüfen Sie, ob die Datei oder das Verzeichnis existiert

    Dies ist die häufigste Verwendung, zum Beispiel: Erstellen Sie eine Datei, wenn sie „nicht existiert“.

    # Wenn keine Datei mit dem Namen config.txt existiert
    wenn [ ! -f "config.txt" ]; dann
        echo „Datei existiert nicht, wird erstellt …“
        Berühren Sie config.txt
    fi
    
    # Wenn das Verzeichnis nicht existiert
    wenn [ ! -d "/var/log/myapp" ]; dann
        mkdir -p "/var/log/myapp"
    fi

    2. String-Vergleich

    Prüfen Sie, ob die Zeichenfolge „ungleich“ oder „nicht leer“ ist.

    STR="Hallo"
    
    # Überprüfen Sie, ob die Variable nicht gleich „Welt“ ist.
    if [ "$STR" != "world" ]; dann
        echo „String stimmt nicht überein“
    fi
    
    # Überprüfen Sie, ob die Zeichenfolge nicht leer ist (! -z entspricht -n)
    wenn [ ! -z "$STR" ]; dann
        echo „Die Variable enthält Daten“
    fi

    3. Numerischer Vergleich

    Obwohl der Zahlenwert relativ ist-ne(nicht gleich), können aber auch abgeglichen werden!verwenden.

    NUM=10
    
    wenn [ ! "$NUM" -eq 20 ]; dann
        echo „Die Zahl ist ungleich 20“
    fi

    Vergleichstabelle der bedingten Logik

    Operator veranschaulichen Beispiel
    ! -f Datei existiert nicht [ ! -f file ]
    ! -d Verzeichnis existiert nicht [ ! -d dir ]
    != String ist nicht gleich [ "$a" != "$b" ]
    ! -z String ist nicht leer [ ! -z "$str" ]
    -ne Wert ist nicht gleich [ "$n" -ne 5 ]

    Vorteile der Verwendung von Doppelklammern [[ ]]

    In moderneren Bash-Skripten wird die Verwendung empfohlen[[ ]], das verarbeitet wird!Leistungsstärker und weniger fehleranfällig in Kombination mit Logik.

    # Mehrere Bedingungen kombinieren: Wenn es sich nicht um ein Verzeichnis handelt und nicht gelesen werden kann
    wenn [[ ! -d $pfad && ! -r $pfad ]]; dann
        echo „Ungültiger Pfad oder unzureichende Berechtigungen“
    fi

    Dinge zu beachten



    Bedingte Bash-Verzweigung

    grundlegende grammatikalische Struktur

    caseDie Anweisung wird verwendet, um den Wert einer Variablen mit mehreren Mustern (Mustern) zu vergleichen, und ihre Funktion ähnelt der in anderen Sprachen.switch. Seine grammatikalische Struktur ist wie folgt:

    Fallvariable in
        Modus 1)
            # Anweisungen ausführen
            ;;
        Modus 2)
            # Anweisungen ausführen
            ;;
        *)
            # Standardausführungsbefehl (ähnlich dem Standard)
            ;;
    esac

    Häufige Anwendungsbeispiele

    1. Einfache Menübeurteilung

    Dies ist die häufigste Verwendung, bei der verschiedene Aktionen basierend auf Benutzereingaben ausgeführt werden.

    read -p „Bitte geben Sie (Ja/Nein) ein:“ Eingabe
    
    Fall „$input“ in
        „ja“)
            echo „Sie haben Ja ausgewählt“
            ;;
        „nein“)
            echo „Haben Sie „Nein“ gewählt?
            ;;
        *)
            echo „Eingabefehler“
            ;;
    esac

    2. Mehrere Muster kombinieren (ODER)

    verwenden|Symbole ermöglichen mehreren Modi die Ausführung desselben Befehlsblocks.

    read -p "Bitte geben Sie die Monatsabkürzung ein: " Monat
    
    Fall „$Monat“ in
        Jan.|Feb.|März)
            echo „Staffel 1“
            ;;
        April|Mai|Jun)
            Echo „Staffel 2“
            ;;
        *)
            echo „andere Monate“
            ;;
    esac

    3. Verwenden Sie Platzhalter

    Der Mustervergleich unterstützt erweiterte Symbole wie Dateipfade (z. B.*, ?, [a-z])。

    read -p „Bitte geben Sie ein Zeichen ein:“ char
    
    Fall „$char“ in
        [a-z])
            echo „Das ist ein Kleinbuchstabe“
            ;;
        [A-Z])
            echo „Das ist ein Großbuchstabe“
            ;;
        [0-9])
            echo „Das ist eine Zahl“
            ;;
        *)
            echo „Dies ist ein Sonderzeichen oder mehrere Zeichen“
            ;;
    esac

    Erklärung der wichtigsten Symbole

    Symbol Funktionsbeschreibung
    ) Das End-Tag des Musters.
    ;; Die Endmarkierung des Anweisungsblocks (ähnlich wiebreak)。
    * Vergleicht eine beliebige Zeichenfolge, die normalerweise als Standardoption an letzter Stelle steht.
    | Wird verwendet, um mehrere übereinstimmende Muster zu trennen (repräsentiert „oder“).
    esac caseRückwärts geschrieben stellt es das Ende des Grammatikblocks dar.

    Vorsichtsmaßnahmen für den Gebrauch

    Groß- und Kleinschreibung beachten

    Standardverhalten: Groß- und Kleinschreibung beachten. In einer Standard-Bash-UmgebungcaseDie Aussage istGroß- und Kleinschreibung beachtenvon. Das bedeutet, dass „A“ und „a“ als unterschiedliche Muster behandelt werden.

    read -p "Geben Sie ein Zeichen ein: " char
    Fall „$char“ in
        a) echo „Das ist ein Kleinbuchstabe a“ ;;
        A) echo „Das ist Großbuchstaben A“ ;;
    esac
    ---

    Methode 1: Verwenden Sie die Option nocasematch

    Wenn Sie das Ganze wollencaseDie Anweisung ignoriert die Groß-/Kleinschreibung und kann verwendet werdenshoptBefehl aktiviertnocasematchaufstellen. Dies wirkt sich auf alle nachfolgenden Zeichenfolgenvergleiche aus undcaseRichter.

    # Groß-/Kleinschreibung ignorieren aktivieren
    shopt -s nocasematch
    
    read -p „Geben Sie die Eingabe „yes“ oder „YES:“ ein
    Fall „$input“ in
        ja) echo „Übereinstimmung erfolgreich (Groß-/Kleinschreibung ignorieren)“ ;;
    esac
    
    # Groß-/Kleinschreibung ignorieren deaktivieren (Standard wiederherstellen)
    shopt -u nocasematch
    ---

    Methode 2: Geben Sie den Bereich im Muster manuell an

    Wenn Sie die globale Einstellung nicht ändern möchten, ist die Definition des Fallbereichs direkt im Schema der standardmäßigste und konsistenteste Ansatz.

    read -p "Geben Sie einen Buchstaben ein: " char
    Fall „$char“ in
        [aA])
            echo „Du hast a oder A eingegeben“
            ;;
        [b-zB-Z])
            echo „Sie haben zusätzliche Buchstaben eingegeben“
            ;;
    esac
    ---

    Methode 3: Pipe-Symbole kombinieren (OR)

    Für bestimmte Wörter können Sie verwenden|um alle möglichen Schreibweisen aufzulisten.

    Fall „$input“ in
        Stopp|STOP|Stopp)
            echo „Ausführung stoppen“
            ;;
    esac
    ---

    Vergleich der Einstellmethoden

    Verfahren Vorteil Mangel
    shopt -s nocasematch Der Programmcode ist prägnant und für groß angelegte Vergleiche geeignet. Dies wirkt sich auf das Verhalten des gesamten Skripts aus. Denken Sie also daran, es manuell zu deaktivieren.
    [a-zA-Z]Umfang Präzise Steuerung ohne Beeinträchtigung anderer Teile. Wenn die Wörter sehr lang sind, wird das Schreiben sehr umständlich.
    Pipe-Charakter| Hohe Lesbarkeit, geeignet für einige wenige Wörter. Zufällige Fallkombinationen (z. B. Ja) können nicht verarbeitet werden.


    Rangfolge der Bash-Operationen

    Verwenden Sie Klammern innerhalb von (( ))

    Arithmetische Erweiterungen in Bash(( ))Intern können Sie einfach Klammern verwenden( )um die Priorität von Operationen explizit anzugeben, im Einklang mit der Logik von C oder den meisten Programmiersprachen. Dies ist sehr wichtig, wenn es um komplexe Logik (Verknüpfung von UND, ODER, Addition, Subtraktion, Multiplikation und Division) geht.

    # Beispiel: (A und B) oder C
    if (( (MIN > 91 && MIN< 110) || FORCE_MODE == 1 )); then
        echo "條件成立"
    fi

    Vorrangregeln

    existieren(( ))Dabei folgt die Rangfolge der Operationen standardmäßigen mathematischen und logischen Konventionen:

    1. Elemente in Klammern: ( )Höchste Priorität.
    2. Multiplikation und Division: *, /, %
    3. Addition und Subtraktion: +, -
    4. Vergleichsoperationen: <, >, <=, >=
    5. Logische Operationen: &&(UND) hat Vorrang vor|| (OR)。

    Beispiel für eine komplexe Bedingung

    Angenommen, Sie müssen Folgendes bestimmen: Der Wert muss innerhalb des Bereichs liegen und (muss ein bestimmtes Vielfaches sein oder sich im erzwungenen Modus befinden):

    if (( MIN > 91 && (MIN % 5 == 0 || FORCE_MODE == 1) )); dann
        {
            echo „Komplexe bedingte Beurteilung auslösen“
            IS_SHUTDOWN=true
        } |& tee -a "$LOGFILE"
    fi

    Vergleiche und Empfehlungen

    Syntaxtyp Gruppierungssymbole Dinge zu beachten
    (( ... )) ( ) Die intuitivsten Symbole müssen nicht maskiert werden und werden für reine numerische Operationen empfohlen.
    [[ ... ]] ( ) existieren[[ ]]Es ist auch zulässig, Klammern zur logischen Gruppierung zu verwenden.
    [ ... ] \( ... \) TraditiontestSyntax: Klammern müssen mit Backslashes maskiert werden, was nicht empfohlen wird.


    Verwendung des Bash-Exits

    Exit-Befehl und Statuscode

    In einem Bash-Skript:exitWird verwendet, um die Skriptausführung zu beenden und einen Statuscode (Exit-Status) an das übergeordnete Programm zurückzugeben.

    if [ -f "config.txt" ]; dann
        echo „Datei existiert“
        Ausgang 0
    sonst
        echo „Fehler: Profil nicht gefunden“
        Ausgang 1
    fi

    Exit-Statuscode abrufen

    Nach der Ausführung eines Skripts oder einer Anweisung können Sie spezielle Variablen verwenden$?um das vorherige Programm zu erhaltenexitStatuscode.

    ./script.sh
    echo „Skript-Endstatus: $?“

    Verwenden Sie Backtick `` oder $(), um den Ausgabewert zu erhalten

    wenn du anrufst.shDatei und möchte deren Inhalt „ausgeben“ (d. h.echoBeim Speichern des Inhalts einer Variablen können Sie Backticks oder verwenden$(). Dies wird als Befehlssubstitution bezeichnet.

    Beispielskript (get_name.sh)

    #!/bin/bash
    # Dies ist der Ausgabeinhalt und wird erfasst
    echo „Ubuntu_User“
    # Dies ist der Endzustand und wird nicht von Backticks erfasst
    Ausgang 0

    Aufruf von einem anderen Skript oder Terminal

    # Backticks verwenden
    RESULT=`./get_name.sh`
    
    # Verwenden Sie $() (empfohlene moderne Schreibweise)
    ERGEBNIS=$(./get_name.sh)
    
    echo „Das erhaltene Ergebnis ist: $RESULT“

    Wichtiger Unterschied: Rückgabewert vs. Ausgabeinhalt

    Ziel So erhalten Sie verwenden
    Exit-Status (Statuscode) $? Bestimmen Sie, ob die Befehlsausführung erfolgreich war (0 oder 1).
    Standardausgabe (Ausgabeinhalt) ` `oder$( ) Rufen Sie die nach der Ausführung des Skripts generierten Zeichenfolgendaten ab.

    Wenn Sie beides gleichzeitig erhalten möchten, können Sie sich auf das folgende Beispiel beziehen:

    OUTPUT=$(./script.sh)
    STATUS=$?
    
    echo „Inhalt ist: $OUTPUT“
    echo „Der Statuscode ist: $STATUS“


    Bash-Return-Nutzung

    Grundlegende Definition von Rendite

    In Bash,returnAnweisungen werden speziell verwendet, umFunktionoder durchsourceDas auszuführende Skript. Es stoppt die Ausführung der aktuellen Funktion oder des aktuellen Skripts und gibt den angegebenen Statuscode an den Aufrufer zurück, schließt jedoch nicht das aktuelle Shell-Programm.

    1. Verwenden Sie return innerhalb einer Funktion

    Dies ist die häufigste Verwendung.returnZurückgegeben wird der Statuscode (0-255), nicht die Zeichenfolgendaten.

    Beispielskript (func_test.sh)

    #!/bin/bash
    
    # Funktion definieren
    check_file() {
        if [ -f "$1" ]; dann
            return 0 # Erfolg
        sonst
            return 1 # fehlgeschlagen
        fi
    }
    
    # Funktion aufrufen
    check_file „test.txt“
    ERGEBNIS=$?
    
    if [ $RESULT -eq 0 ]; dann
        echo „Datei existiert“
    sonst
        echo „Datei existiert nicht“
    fi

    2. Verwenden Sie return (mit Quelle) in der .sh-Datei

    Wenn Sie möchten, dass die Variablen und die Umgebung nach der Ausführung eines Skripts im aktuellen Terminal verbleiben, verwenden Sie normalerweisesource. Muss zu diesem Zeitpunkt verwendet werdenreturnstattexit

    Aufgerufener (sub_script.sh)

    # Simulieren Sie logisches Urteilsvermögen
    if [ "$USER" != "root" ]; dann
        echo „Unzureichende Berechtigungen, nur für Root-Verwendung“
        # Wenn Sie Exit verwenden, schließen Sie das Terminal direkt. Wenn Sie Return verwenden, stoppen Sie nur die Ausführung dieses Skripts.
        Rückkehr 1
    fi
    
    export APP_STATUS="Bereit"
    0 zurückgeben

    Aufrufer (direkt in CMD oder einem anderen Skript)

    Quelle ./sub_script.sh
    echo „Skript gibt Status zurück: $?“
    echo „Umgebungsvariablen abrufen: $APP_STATUS“

    3. So erhalten Sie den „Rückgabewert“ über den Rückgabemechanismus

    WeilreturnEs können nur Zahlen (Statuscodes) zurückgegeben werden. Um Zeichenfolgen oder große Datenmengen zu erhalten, empfiehlt sich die KombinationechoUndBefehlsersetzung

    Angerufener (get_data.sh)

    #!/bin/bash
    berechne() {
        lokaler Wert=$(( $1 + $2 ))
        # Ergebnisse auf stdout ausgeben
        echo „$val“
        # Ausführungsstatuscode zurückgeben
        0 zurückgeben
    }
    
    Berechnen Sie 10 20

    Anrufer

    # Holen Sie sich den Ausgabeinhalt
    DATA=$(./get_data.sh)
    # Holen Sie sich den Statuscode der Rückgabe
    STATUS=$?
    
    echo „Das Berechnungsergebnis ist: $DATA“
    echo „Ausführungsstatus: $STATUS“

    Nutzungszusammenfassung und Vergleich

    Schlüsselwörter Anwendungsbereich Auswirkungen auf das Hauptprogramm
    exit 0/1 Unabhängige Skripte und Unterprogramme Beendet die gesamte aktuelle Shell (bei Ausführung mit Quelle).
    return 0/1 Funktion, Quellskript geladen Verlässt nur den aktuellen Bereich und hat keinen Einfluss auf die Hauptprogramm-Shell.
    echo "..." überall Wird verwendet, um dem Aufrufer den eigentlichen „Dateninhalt“ zu übergeben.


    Bash prüft, ob die Variable leer ist

    In Bash können Sie mithilfe der bedingten Beurteilung prüfen, ob eine Variable leer ist. Hier sind einige gängige Methoden:

    Beispiel 1: Verwendung-zÜberprüfen Sie, ob die Variable leer ist

    #!/bin/bash
    
    var=""
    if [ -z "$var" ]; dann
        echo „Die Variable ist leer“
    sonst
        echo „Die Variable ist nicht leer“
    fi

    -zWird verwendet, um zu prüfen, ob die Variable leer ist. Wenn die Variable leer ist, ist die Bedingung wahr.

    Beispiel 2: Verwendung-nÜberprüfen Sie, ob die Variable nicht leer ist

    #!/bin/bash
    
    var="irgendein Wert"
    if [ -n "$var" ]; dann
        echo „Die Variable ist nicht leer“
    sonst
        echo „Die Variable ist leer“
    fi

    -nWird verwendet, um zu prüfen, ob die Variable nicht leer ist. Wenn die Variable einen Wert hat, ist die Bedingung wahr.

    Beispiel 3: Vergleich mit doppelten Anführungszeichen verwenden, um zu prüfen, ob eine Variable leer ist

    #!/bin/bash
    
    var=""
    if [ "$var" == "" ]; dann
        echo „Die Variable ist leer“
    sonst
        echo „Die Variable ist nicht leer“
    fi

    Diese Methode vergleicht die Variable direkt mit der leeren Zeichenfolge, um zu prüfen, ob die Variable leer ist.



    Array-Struktur in Bash

    Einführung

    Bash unterstützt zwei Arten von Arrays:

    Indexarray

    Definierter Weg

    fruits=("apple" "banana" "cherry")

    Elemente lesen

    echo "${fruits[0]}"     # apple
    echo "${fruits[1]}"     # banana

    Listen Sie alle Elemente auf

    echo "${fruits[@]}"

    Ermitteln Sie die Array-Länge

    echo "${#fruits[@]}"

    Neues Element hinzufügen

    fruits+=("date")

    Elemente durchqueren

    for fruit in "${fruits[@]}"; do
        echo "$fruit"
    done

    assoziatives Array

    Definition und Verwendung (erfordert Bash 4+)

    declare -A capital
    capital["Taiwan"]="Taipei"
    capital["Japan"]="Tokyo"

    Zugang und Durchquerung

    echo "${capital["Japan"]}" # Tokio
    
    for Geben Sie „${!capital[@]}“ ein; tun
        echo „Das Kapital von $key ist ${capital[$key]}“
    erledigt

    Dinge zu beachten

    abschließend

    Das Bash-Array ist eine wichtige Struktur zum Speichern mehrerer Daten und eignet sich für die Datenverarbeitung wie Parameterlisten, Verzeichnissätze und Schlüssel-Wert-Paare.



    Bash führt zwei Arrays zusammen

    Grundgrammatik

    combined=("${array1[@]}" "${array2[@]}")

    Dadurch werden alle Elemente aus beiden Arrays in einem neuen Array zusammengeführtcombined

    Vollständiges Beispiel

    array1=("Apfel" "Banane")
    array2=("cherry" "date")
    
    kombiniert=("${array1[@]}" "${array2[@]}")
    
    echo „Kombiniertes Array:“
    für Element in „${combined[@]}“; tun
        echo „$item“
    erledigt

    In das ursprüngliche Array einbinden

    array1+=("${array2[@]}")

    Das wirdarray2Inhalte werden direkt hinzugefügtarray1hinteren.

    Dinge zu beachten



    Bash bestimmt, ob eine Zeichenfolge mit einem bestimmten Wort beginnt

    Zeichenfolgenmustervergleich verwenden (empfohlen)

    str="Hallo Welt"
    
    if [[ "$str" == hallo* ]]; dann
        echo „String beginnt mit Hallo“
    fi

    veranschaulichen:verwenden[[ ]]Unterstützung des Schalenmustervergleichs,*Stellt ein beliebiges Zeichen dar.

    Verwenden Sie reguläre Ausdrücke

    if [[ "$str" =~ ^hello ]]; dann
        echo „String beginnt mit Hallo“
    fi

    veranschaulichen: ^Zeigt den Anfang an,[[ ]]In=~ist ein regulärer Vorgang.

    verwendencaseErzählen

    Fall „$str“ in
      hallo*) echo "String beginnt mit hallo" ;;
      *) echo „beginnt nicht mit hallo“ ;;
    esac

    veranschaulichen: caseEs ist ein gutes Werkzeug zur Verarbeitung von Zeichenfolgenmustern, prägnant und gut lesbar.

    verwendenexpr(Alter Schreibstil)

    if expr "$str" : '^hello' &> /dev/null; dann
        echo „String beginnt mit Hallo“
    fi

    veranschaulichen:verwendenexprReguläre Matching-Funktion, geeignet für ältere Versionen der Shell.

    Dinge zu beachten



    Bash ermittelt, ob eine Datei oder ein Verzeichnis existiert

    Stellen Sie fest, ob es existiert:-e

    -eWird verwendet, um zu überprüfen, ob eine Datei oder ein Verzeichnis vorhanden ist (unabhängig vom Typ).

    DATEI="/etc/passwd"
    
    if [ -e "$FILE" ]; dann
        echo „$FILE existiert“
    sonst
        echo „$FILE existiert nicht“
    fi

    Stellen Sie fest, ob das Verzeichnis nicht existiert:! -d

    -dWird verwendet, um zu überprüfen, ob es sich um ein Verzeichnis handelt.!Es handelt sich um eine negative Operation.

    DIR="/tmp/myfolder"
    
    wenn [ ! -d "$DIR" ]; dann
        echo „$DIR existiert nicht, wird erstellt …“
        mkdir -p „$DIR“
    sonst
        echo „$DIR existiert bereits“
    fi

    Andere häufig verwendete Bedingungsoptionen

    Beispiel: Inspektion und Erstellung kombinieren

    PATH_TO_CHECK="/home/user/config"
    
    if [ -e "$PATH_TO_CHECK" ]; dann
        echo „$PATH_TO_CHECK existiert bereits“
    sonst
        echo „$PATH_TO_CHECK existiert nicht und wird erstellt …“
        mkdir -p "$PATH_TO_CHECK"
    fi

    Anregung



    Listen Sie alle Unterverzeichnisse auf und speichern Sie sie in einem Array

    Beispiel: In Array speichern

    target_dir="/path/to/your/dir"
    subdirs=()
    
    while IFS= read -r -d $'\0' dir; do
        subdirs+=("$dir")
    done < <(find "$target_dir" -mindepth 1 -maxdepth 1 -type d -print0)

    veranschaulichen

    Beispielausgabe

    for dir in "${subdirs[@]}"; do
        echo "$dir"
    done

    Alternative einfache Schreibweise (sofern keine Sonderzeichen vorhanden sind)

    subdirs=( "$target_dir"/*/ )
    

    Diese Schreibweise verwendet Platzhalter, um Unterverzeichnisse abzugleichen, kann jedoch weder Dateien ausschließen noch Leerzeichen und Sonderzeichen verarbeiten.



    Rufen Sie den tatsächlichen Pfad ab, der ~ enthält

    Methode 1: Verwenden Sie eval zum Erweitern

    path="~/myfolder/file.txt"
    realpath "$(eval echo "$path")"
    

    Methode 2: Durch $HOME ersetzen

    path="~/myfolder/file.txt"
    realpath "$(echo "$path" | sed "s|^~|$HOME|")"
    

    Methode 3: Verwenden Sie readlink

    path="~/myfolder/file.txt"
    readlink -f "$(eval echo "$path")"
    

    Empfohlene Verwendung

    realpath "$(eval echo "$path")"
    


    grep

    einfache Suche

    grep „Schlüsselwort“-Dateiname

    Groß-/Kleinschreibung ignorieren

    grep -i „Schlüsselwort“-Dateiname

    Zeilennummer anzeigen

    grep -n „Schlüsselwort“-Dateiname

    rekursive Suche

    grep -r Verzeichnispfad „Schlüsselwort“.

    Nur passenden Text anzeigen

    grep -o „Schlüsselwort“-Dateiname

    Auch Dateinamen anzeigen

    grep -H „Schlüsselwort“-Dateiname

    Zwei Sätze von Schlüsselwörtern erscheinen zusammen (UND)

    grep „Schlüsselwort 1“ Dateiname | grep „Schlüsselwort 2“

    Eines der beiden Schlüsselwörter erscheint (ODER)

    #Methode 1: Regulärer Ausdruck
    grep -E Dateiname „Schlüsselwort 1 | Schlüsselwort 2“.
    
    #Methode 2: Mehrere -e-Parameter
    grep -e "Schlüsselwort 1" -e "Schlüsselwort 2" Dateiname

    Lösen Sie das Problem mit Binärdateiübereinstimmungen

    #Methode 1: Erzwingen Sie, dass die Datei als Text behandelt wird
    grep -a „Schlüsselwort“-Dateiname
    
    #Methode 2: Konvertieren Sie die Dateikodierung in UTF-8 und suchen Sie dann
    iconv -f Originalkodierung -t UTF-8-Dateiname | grep „Schlüsselwort“
    
    # Beispiel (Konvertierung von BIG5 nach UTF-8)
    iconv -f BIG5 -t UTF-8-Dateiname | grep „Schlüsselwort“

    Gängige Kombinationen

    grep -rin Verzeichnispfad „Schlüsselwort“.


    -print0 mit read -d $'\0'

    Gebrauchsanweisung

    Bei der Verarbeitung von Dateinamen oder Pfaden, die Leerzeichen oder Sonderzeichen (wie Leerzeichen, Anführungszeichen, Zeilenumbrüche) enthalten, gilt die traditionellefindVerteilungsliniexargsoderreadEs kann zu Fehleinschätzungen kommen.

    -print0Zulässigfindmit null(\0) Zeichen als Ausgabetrennzeichen, whileread -d $'\0'Kann durch Nullen getrennte Inhalte genau lesen, um eine genaue Trennung der einzelnen Dateien/Pfade sicherzustellen.

    Einfaches Beispiel: Sammeln Sie alle Unterverzeichnisse

    subdirs=()
    while IFS= read -r -d $'\0' dir; do
        subdirs+=("$dir")
    done < <(find . -type d -print0)

    veranschaulichen

    Beispiel 1: Listen Sie die absoluten Pfade aller TXT-Dateien auf

    txt_files=()
    while IFS= read -r -d $'\0' file; do
        txt_files+=("$file")
    done < <(find "$(pwd)" -type f -name "*.txt" -print0)

    Beispiel 2: Dateien zur Verarbeitung an einen Befehl senden (Sicherheit)

    finden . -type f -print0 | while IFS= read -r -d $'\0' file; tun
        echo „Verarbeitung: $file“
        # your_command „$file“
    erledigt

    Beispiel 3: Nur Verzeichnisse verarbeiten, die Leerzeichen enthalten

    finden . -type d -print0 | while IFS= read -r -d $'\0' dir; tun
        if [[ "$dir" == *" "* ]]; dann
            echo „Verzeichnis mit Leerzeichen: $dir“
        fi
    erledigt

    Warum nicht Zeilenumbrüche verwenden?

    Der traditionelle Gebrauch ist wie folgt:

    find . -type f | while read file; do ...

    Wenn der Dateiname jedoch eine neue Zeile enthält, wird dies dazu führenreadFalsches Parsen, selbst mehrere Zeilen werden fälschlicherweise als mehrere Dateien interpretiert.

    abschließend



    Beim Lesen tritt nur ein Verzeichnisproblem auf

    Problemstellung

    In einigen Bash- oder Cygwin-Umgebungen wird die folgende Schreibmethode verwendet:Lesen Sie nur den ersten Artikel

    while IFS= read -r -d $'\0' dir; do
        subdirs+=("$dir")
    done < <(find "$target_dir" -mindepth 1 -maxdepth 1 -type d -print0)

    Dies liegt normalerweise daran, dass „<(find ...)` 在某些系統(如 Cygwin)不是「真正的檔案描述符」,造成 `read` 無法持續讀取。

    Korrektur: Pipeline mit „read -d“ (oder „readarray -d“) verwenden

    Methode 1: Verwenden Sie „find |“. while` Pipeline-Kombination-print0

    subdirs=()
    find "$target_dir" -mindepth 1 -maxdepth 1 -type d -print0 | while IFS= read -r -d $'\0' dir; do
        subdirs+=("$dir")
    done

    **Hinweis**: Wenn Sie möchten, dass „Unterverzeichnisse“ im Hauptprogramm verfügbar sind, ist diese Methode nicht geeignet (da die Subshell „while ... |“ das Array nicht zurückgeben kann).

    Methode 2: Zum Array wechseln und erneut verarbeiten

    mapfile -d '' -t subdirs < <(find "$target_dir" -mindepth 1 -maxdepth 1 -type d -print0)

    mapfile(oderreadarray) kann durch Nullen getrennte Zeichenfolgen korrekt in Arrays einlesen.
    Dies ist die zuverlässigste Möglichkeit, es in der Haupthülle zu behalten.

    Beispielausgabe

    für dir in „${subdirs[@]}“; tun
        echo „Verzeichnis gefunden: $dir“
    erledigt

    Zusammenfassen



    Daten aus Variableninhalten lesen (Lesen verwenden)

    Gehen Sie davon aus, dass die Variable mehrere Textzeilen enthält

    var="line1
    line2
    line3"

    Verwenden Sie while read, um Zeile für Zeile zu lesen

    while IFS= read -r line; tun
        echo „Lesen: $line“
    erledigt <<< „$var“

    Kommentar

    Einzeiliges Lesen

    read -r first_line <<< „$var“
    echo „Erste Zeile: $first_line“

    als Array lesen

    readarray -t lines <<< "$var"
    for line in "${lines[@]}"; do
        echo "$line"
    done


    Suchen Sie das Verzeichnis ausgehend von der Zeichenfolge und sortieren Sie es nach Datum

    Vollständige Anweisungen (sortiert nach Verzeichnisänderungszeit)

    find . -mindepth 1 -maxdepth 1 -type d -name "abc*" -printf "%T@ %p\n" | sort -nr | cut -d' ' -f2-

    veranschaulichen

    Beispielausgabe

    ./abc_latest
    ./abc_old
    ./abc_2020

    Wenn Sie es in einem Bash-Array speichern müssen

    readarray -t abc_dirs << <(
      finden. -min Depth 1 -max Depth 1 -type d -name "abc*" -printf "%T@ %p\n" |
      sort -nr | schneiden -d' ' -f2-
    )
    
    für dir in „${abc_dirs[@]}“; tun
      echo „Gefunden: $dir“
    erledigt

    Notiz



    Bash prüft, ob das Speichergerät beschreibbar ist

    Methode 1: Überprüfen Sie, ob das Verzeichnis über Schreibberechtigungen verfügt

    DIR="/mnt/usb"
    
    if [ -w "$DIR" ]; dann
        echo „$DIR ist beschreibbar“
    sonst
        echo „$DIR ist nicht beschreibbar“
    fi

    -wUm zu prüfen, ob das Verzeichnis „Schreibberechtigung“ hat. Wenn jedoch das Verzeichnis selbst beschreibbar ist, das eigentliche Gerät jedoch schreibgeschützt ist (z. B. mount ist schreibgeschützt), funktioniert diese Methode möglicherweise nicht.

    Methode 2: Versuchen Sie tatsächlich, in die Testdatei zu schreiben

    DIR="/mnt/usb"
    TESTFILE="$DIR/.write_test"
    
    if touch „$TESTFILE“ 2>/dev/null; dann
        echo „$DIR ist beschreibbar“
        rm „$TESTFILE“
    sonst
        echo „$DIR ist nicht beschreibbar“
    fi

    Diese Methode ist die zuverlässigste und kann den Mount-Status erkennen oder ob das physische Gerät tatsächlich beschreibbar ist.

    Methode 3: VerwendenmountAnweisung, um zu prüfen, ob der Mount schreibgeschützt ist

    MNT="/mnt/usb"
    
    wenn mount | grep „$MNT“ | grep -q "(ro,"; dann
        echo „$MNT ist schreibgeschützt gemountet“
    sonst
        echo „$MNT ist ein beschreibbarer Mount“
    fi

    Diese Methode muss prüfen, ob das Gerät schreibgeschützt ist (ro) Methode.

    Anregung



    Anweisungen zur Verwendung der Shell-Umleitung

    1. Standardausgabeumleitung: „>“.

    Verwenden Sie in der Shell „>“, um die Standardausgabe eines Befehls (stdout) in eine Datei oder ein Gerät umzuleiten. Wenn die Datei bereits vorhanden ist, wird der Inhalt überschrieben.

    echo "Hello" > output.txt

    Diese Anweisungszeile wird"Hello"schreibenoutput.txtDatei.

    2. Ausgabeumleitung hinzufügen: „>>“.

    Durch die Verwendung von „>>“ wird die Standardausgabe an das Ende der angegebenen Datei angehängt, ohne den ursprünglichen Inhalt zu überschreiben.

    echo "Hello again" >> output.txt

    Diese Befehlszeile wird"Hello again"anhängenoutput.txtdas Ende von.

    3. Standardfehlerumleitung: „2>“.

    In der Shell wird „2>“ verwendet, um die Standardfehlermeldung (stderr) an einen angegebenen Speicherort umzuleiten. Zum Beispiel:

    ls non_existent_file 2> error.log

    In diese Befehlszeile wird die Fehlermeldung geschriebenerror.logDatei.

    4. Fehlerumleitung hinzufügen: „2>>“.

    Wenn Sie die Fehlermeldungsdatei nicht überschreiben möchten, können Sie die Fehlermeldung mit „2>>“ an das Ende der Datei anhängen.

    ls non_existent_file 2>> error.log

    Mit dieser Befehlszeile wird die Fehlermeldung angehängterror.log

    5. Standardausgabe und Fehler gleichzeitig umleiten: „&>“.

    Verwenden Sie „&>“, um sowohl die Standardausgabe als auch die Standardfehlerausgabe in dieselbe Datei oder dasselbe Gerät umzuleiten.

    command &> all_output.log

    Diese Befehlszeile wirdcommandIn alle Ausgaben (Standardausgabe und Fehlerausgabe) wird geschriebenall_output.log

    6. Standardfehler mit Standardausgabe zusammenführen: „2>&1“.

    „2>&1“ führt Standardfehler mit der Standardausgabe zusammen, um eine einheitliche Verwaltung zu ermöglichen. Zum Beispiel:

    command > output.log 2>&1

    Diese Anweisungszeile schreibt sowohl in die Standardausgabe als auch in die Fehlerausgabeoutput.log

    7. Deaktivieren Sie alle Ausgaben: „>/dev/null 2>&1“.

    Wenn Sie nicht möchten, dass eine Ausgabe angezeigt wird, können Sie die gesamte Ausgabe an weiterleiten/dev/null,wie:

    command >/dev/null 2>&1

    Diese Befehlszeile wirdcommandAlle Ausgaben werden verworfen.



    UTF-8-kodierte Dateien konvertieren und ausgeben

    im EinsatzteeWenn der Befehl die Ausgabe an eine Datei anhängt, können Sie übergebeniconvKonvertieren Sie die Ausgabe in die UTF-8-Kodierung und stellen Sie sicher, dass der Dateiinhalt in UTF-8 gespeichert wird. Nachfolgend finden Sie spezifische Anweisungen und Beispiele.

    Befehlsformat

    Im Folgenden wird die Ausgabe als UTF-8-codiert gespeichertteeAnleitungsformat:

    command | iconv -t utf-8 | tee -a output.txt

    Beispiel

    Das folgende Beispiel zeigt, wie das gehtlsDie Ausgabe des Befehls wird in UTF-8-Kodierung geschriebenoutput.txt

    ls | iconv -t utf-8 | tee -a output.txt

    Nachdem Sie diese Anweisung ausgeführt haben,output.txtDer Inhalt wird in UTF-8-Kodierung gespeichert, um Kodierungsfehler zu vermeiden.



    Windows cmd

    Öffnungsmethode

    Allgemeine Befehle

    Erweiterter Betrieb

    Administratormodus



    Führen Sie den zweiten Befehl nach cmd /k aus

    Führen Sie mehrere Befehle im selben Fenster aus

    Kann verwendet werden&&&oder||Um die Anweisungen fortzusetzen:

    cmd /k „Erster Befehl und zweiter Befehl“

    Rufen Sie andere Batchdateien auf

    Nach der ersten Anweisung hinzufügencall, können Sie mit der Ausführung einer weiteren Batchdatei fortfahren:

    cmd /k „Erster Befehl & zweiter.bat aufrufen“

    Verwenden Sie /c, um nach der Ausführung zu schließen

    Wenn Sie das Fenster nicht offen halten müssen, können Sie es verwenden/c

    cmd /c „Erster Befehl und zweiter Befehl“

    /cschließt das Fenster automatisch, nachdem alle Befehle ausgeführt wurden, und/kDas Fenster bleibt erhalten.



    CMD-Variable

    Was sind CMD-Variablen?

    In der Windows-Eingabeaufforderung (CMD) sind Variablen Namespaces, die zum Speichern von Daten oder Einstellungen verwendet werden. Sie können in der Umgebung gespeichert werden (Umgebungsvariablen) oder in der Batch-Datei definiert und verwendet werden (Regionalvariablen).

    Variablentyp

    So verwenden Sie Variablen

    Variablenwert lesen

    Um den Wert einer Variablen zu ermitteln, müssen Sie normalerweise vor und nach dem Variablennamen Prozentzeichen hinzufügen.%

    setze NAME=CMD-Benutzer
    echo Mein Name ist %NAME%

    Ausgabe:Mein Name ist CMD-Benutzer

    Legen Sie regionale Variablen in Batchdateien fest

    @echo aus
    set MESSAGE=Dies ist eine Batch-Nachricht
    echo%MESSAGE%
    Pause

    Legen Sie eine Variable fest, aber nur, wenn sie nicht vorhanden ist

    Sie können verwendenIF DEFINEDoderIF NOT DEFINEDAnweisung, um zu prüfen, ob die Variable bereits existiert oder definiert (nicht leer) ist.

    @echo aus
    
    rem prüft, ob die Variable MY_DEFAULT_VALUE definiert (nicht leer) ist
    WENN NICHT DEFINIERT MY_DEFAULT_VALUE (
        setze MY_DEFAULT_VALUE=Default_Setting
        Die Echovariable MY_DEFAULT_VALUE ist undefiniert und wurde auf den Standardwert gesetzt.
    ) SONST (
        Die Echovariable MY_DEFAULT_VALUE existiert bereits, der Wert ist: %MY_DEFAULT_VALUE%
    )
    
    rem einmal ausgeführt wird, wird die Variable auf Default_Setting gesetzt
    Wenn rem erneut ausgeführt wird, wird angezeigt, dass es bereits existiert.
    
    set MY_DEFAULT_VALUE=Existing_Setting
    
    Rem-Überprüfung noch einmal
    WENN NICHT DEFINIERT MY_DEFAULT_VALUE (
        setze MY_DEFAULT_VALUE=Another_Default
        Die Echovariable MY_DEFAULT_VALUE ist undefiniert und auf Another_Default gesetzt.
    ) SONST (
        Die Echovariable MY_DEFAULT_VALUE existiert bereits, der Wert ist: %MY_DEFAULT_VALUE%
    )
    
    Pause

    Ein weiterer netter Trick besteht darin, die Standardwertfunktionalität der Variablenerweiterung zu nutzen (diese wird jedoch hauptsächlich für Schleifen und Parameterverarbeitung sowie im Standard verwendet).setDie Logik von „Setzen, wenn nicht gesetzt“ ist nicht direkt auf den Befehl anwendbar. daher,IF NOT DEFINEDDies ist der Standardansatz. )

    Verzögerte Erweiterung der Umgebungsvariablen aktivieren (verzögerte Erweiterung)

    In Schleifen oder bedingten Anweisungen erfolgt die Standarderweiterung der Prozentzeichenvariablen einmal während der Anweisungsanalyse. Um den neuen Wert der Variablen bei jedem Durchlauf der Schleife lesen zu können, müssen Sie die verzögerte Erweiterung aktivieren und das Ausrufezeichen verwenden!auf Referenzvariablen.

    @echo aus
    setlocal aktiviertelayeexpansion
    setCOUNTER=0
    :LOOP
        wenn %COUNTER% LSS 5 (
            setze /A COUNTER+=1
            Echo aktueller Zählerstand: !COUNTER!
            gehe zu LOOP
        )
    endlokal

    Spezielle Variablen/Systemvariablen

    Variable beschreiben
    %DATE% aktuelles Datum.
    %TIME% aktuelle Uhrzeit.
    %CD% Der aktuelle Verzeichnispfad.
    %ERRORLEVEL% Der Endcode des vorherigen Befehls (normalerweise 0 für Erfolg).
    %RANDOM% Eine zufällige Dezimalzahl zwischen 0 und 32767.
    %~dp0 Das Laufwerk und der Pfad, in dem die Batchdatei ausgeführt wird.

    Erweiterte Verwendung von Parametervariablen

    Für Parametervariablen (z. B%1) oder eine Schleifenvariable (z. B%%A), können Sie Modifikatoren verwenden, um verschiedene Teile des Pfads zu extrahieren:

    Echo vollständiger Pfad: %~1
    Echo-Laufwerk: %~d1
    Echopfad: %~p1
    Name der Echodatei: %~n1
    Echo-Dateierweiterung: %~x1

    Dies ist nützlich, wenn Sie mit Archivpfaden arbeiten.



    Filtern Sie Schlüsselwörter in CMD

    Verwenden Sie den Suchbefehl

    Beispiel

    dir | „txt“ finden :: Nur Dateien anzeigen, die „txt“ enthalten
    ipconfig | find „IPv4“ :: Nur Zeilen anzeigen, die IPv4 enthalten
    Aufgabenliste | find „chrome“ :: Ausführbare Programme herausfiltern, die Chrome enthalten

    Häufig verwendete Parameter

    Suche nach mehreren Schlüsselwörtern

    type log.txt | find "Error" | find "2025"
    type log.txt | findstr /I "error warning fail"

    Fortgeschritten: Verwenden Sie findstr

    dir | findstr /R ".*\.txt$" :: Verwenden Sie reguläre Ausdrücke, um TXT-Dateien zu finden
    Geben Sie log.txt | ein findstr /I „Timeout-Fehler fehlgeschlagen“


    CMD führt beim Start automatisch die Einstellungsmethode aus

    Konzeptnotiz

    Methode 1: Verwenden Sie AutoRun, um Werte einzugeben

    HKEY_CURRENT_USER\Software\Microsoft\Command Processor
    HKEY_LOCAL_MACHINE\Software\Microsoft\Command Processor
    
    AutoRun = "C:\Users\YourName\cmd_startup.bat"

    Methode 2: CMD-Verknüpfung ändern

    %SystemRoot%\System32\cmd.exe /k "C:\Users\YourName\cmd_startup.bat"

    Methode 3: Verwenden Sie die Anmeldung, um die Batchdatei zu starten

    %AppData%\Microsoft\Windows\Start Menu\Programs\Startup

    Korrespondenzanweisungen

    Linux bash Windows CMD entsprechende Methode
    ~/.bash_profile oder ~/.bashrc Anmeldeformular AutoRun oder CMD /k startet die Batchdatei
    Benutzerdefinierte Anweisungen automatisch ausführen In der Batchdatei können benutzerdefinierte Umgebungsvariablen und Pfadeinstellungen platziert werden


    Legen Sie die Batchdatei von CMD AutoRun automatisch fest

    Funktionsbeschreibung

    Beispielinhalt einer Batchdatei

    @echo aus
    setlocal
    
    :: Legen Sie den Batch-Dateipfad fest, der von AutoRun ausgeführt werden soll
    setze „AUTORUN_PATH=C:\Users\%USERNAME%\cmd_startup.bat“
    setze „REG_PATH=HKCU\Software\Microsoft\Command Processor“
    
    echo Überprüfen Sie die CMD-AutoRun-Einstellung ...
    
    :: Prüfen Sie, ob der Login-Code vorhanden ist
    reg-Abfrage „%REG_PATH%“ >nul 2>&1
    wenn Fehlerstufe 1 (
        echo [Informationen] Der Befehlsprozessorcode kann nicht gefunden werden, es wird erstellt...
        reg add „%REG_PATH%“ /f >nul
    )
    
    :: Überprüfen Sie, ob AutoRun eingestellt ist
    reg query „%REG_PATH%“ /v AutoRun >nul 2>&1
    wenn Fehlerstufe 1 (
        echo [Information] AutoRun nicht gefunden, neuer Wert wird erstellt ...
        reg add „%REG_PATH%“ /v AutoRun /d „%AUTORUN_PATH%“ /f >nul
        echo [Fertig] AutoRun wurde eingestellt auf: %AUTORUN_PATH%
    ) sonst (
        echo [OK] AutoRun existiert bereits und wurde nicht geändert.
    )
    
    endlokal
    Pause

    veranschaulichen



    Bestimmen Sie, auf welchem ​​Terminal die Batchdatei ausgeführt wird

    Beispiel-Batchdatei

    @echo aus
    
    :: PowerShell erkennen
    falls definiert PSModulePath (
        echo wird derzeit in PowerShell ausgeführt
        gehe zu :eof
    )
    
    :: Cygwin erkennen
    falls definiert CYGWIN (
        echo wird derzeit in Cygwin ausgeführt
        gehe zu :eof
    )
    falls definiert SHELL (
        echo wird derzeit in Cygwin ausgeführt (SHELL=%SHELL%)
        gehe zu :eof
    )
    
    ::Standard ist CMD
    echo wird derzeit in CMD ausgeführt

    Urteilsgrundlage



    PowerShell

    Öffnungsmethode

    Allgemeine Befehle

    Erweiterter Betrieb

    Administratormodus



    Listen Sie alle Variablen in PowerShell auf

    Befehlsmethode

    Beispiel

    # Alle Variablen auflisten
    Get-Variable
    
    # Nur Variablennamen anzeigen
    Get-Variable | Objektnamen auswählen
    
    # Zeigt den Wert einer bestimmten Variablen an
    Get-Variable PATH | Format-Liste *
    
    #Variable Treibermethode verwenden
    Get-ChildItem-Variable:

    veranschaulichen



    C- und C++-Sprachen

    Hohe Effizienz

    statisches Typsystem

    Ressourcenkontrolle

    Grammatische Flexibilität

    Breites Anwendungsspektrum

    Plattformübergreifend



    C/C++-Präprozessoranweisungen

    Überblick

    Präprozessoranweisungen sind Befehle, die von einem Programmmodul namens „Präprozessor“ ausgeführt werden, bevor der C- oder C++-Programmcode offiziell vom Compiler verarbeitet (kompiliert) wird. Vor diesen Anweisungen steht ein Nummernzeichen (#) und ohne vorangestelltem Semikolon (;) Am Ende.

    Die Rolle des Präprozessors besteht darin, Textersetzung, Dateieinbindung, bedingte Kompilierung und andere Vorgänge durchzuführen, um die endgültige „Übersetzungseinheit“ zur Verwendung durch den Compiler zu generieren.

    Hauptbefehlskategorien und Beispiele

    1. Dateieinbindung

    Wird verwendet, um den Inhalt anderer Dateien in die aktuelle Datei einzufügen.

    #include <iostream> // Die Standard-E/A-Bibliothek einbinden
    #include "my_utility.h" // Benutzerdefinierte Header-Datei einschließen

    2. Makrodefinition und -substitution

    Literales Ersetzungsmakro, das zum Definieren symbolischer Konstanten oder Codefragmente verwendet wird.

    #define MAX_SIZE 100 //Definiere eine symbolische Konstante
    #define SUM(a, b) ((a) + (b)) // Definiere ein Makro mit Parametern
    
    int main() {
        int size = MAX_SIZE; // Nach der Vorverarbeitung wird es zu int size = 100;
        int total = SUM(5, 3); // Nach der Vorverarbeitung wird es zu int total = ((5) + (3));
        0 zurückgeben;
    }

    3. Bedingte Kompilierung

    Ermöglicht Ihnen die Entscheidung, ob ein bestimmter Codeblock basierend auf dem Wert eines Präprozessormakros kompiliert werden soll.

    #define DEBUG_MODE 1
    
    #if DEBUG_MODE
        std::cout << „Debug-Modus aktiviert“ << std::endl;
    #sonst
        std::cout << „Produktionsmodus läuft“ << std::endl;
    #endif
    
    #ifndef MY_HEADER_H
    #defineMY_HEADER_H
        // ... Inhalt der Header-Datei (Beispiel „Include Guard“)
    #endif

    4. Fehler und Warnung

    #ifndef VERSION_DEFINED
    #error „Versionsnummernmakro VERSION_DEFINED muss definiert werden!“
    #endif

    5. Sonstige Richtlinien



    #pragma once

    Definition und Funktion

    #pragma onceIst eine der C- und C++-SprachenPräprozessor-Direktive. Seine Hauptfunktion besteht darin, sicherzustellen, dass die Header-Datei, die diese Direktive enthält, vom Compiler nur während eines einzigen Kompilierungsprozesses verarbeitet wird.einmal

    Der Zweck dieser Anweisung besteht darin, das Problem des wiederholten Einschließens von Header-Dateien zu lösen und zu verhindern, dass derselbe Code (z. B. Klassendefinitionen, Funktionsprototypen oder Konstantendeklarationen) aufgrund mehrerer Quellcodedateien oder mehrstufiger Einbindungsbeziehungen von Header-Dateien vom Compiler mehrmals gesehen wird, was zu Problemen führtNeudefinitionKompilierungsfehler.

    Vergleich mit Include Guard

    Im C/C++-Standard traditionell durch die VerwendungWache einbeziehenUm den Zweck zu erreichen, eine wiederholte Einbeziehung zu verhindern.#pragma onceBietet eine sauberere Alternative.

    Guard einbeziehen (Standardmethode)

    Dies ist der standardmäßige und portable Ansatz, bei dem Anweisungen zur bedingten Kompilierung verwendet werden:

    #ifndef MY_HEADER_H
    #defineMY_HEADER_H
    
    // Inhalt der Header-Datei
    
    #endif // MY_HEADER_H

    Es basiert auf einem eindeutigen Makronamen (z. B.MY_HEADER_H), um zu steuern, ob Inhalte enthalten sind.

    #pragma einmal (nicht standardmäßige Methode)

    Verwenden Sie eine einzeilige Direktive:

    #pragma einmal
    
    // Inhalt der Header-Datei

    Der Compiler prüft automatisch, ob er diese Datei in der aktuellen Kompilierungssitzung bereits verarbeitet hat, und überspringt in diesem Fall den verbleibenden Inhalt der Datei.

    Vor- und Nachteile

    Vorteile von #pragma Once:

    Nachteile von #pragma Once:

    abschließend

    In modernen Entwicklungsumgebungen, insbesondere bei Verwendung von Visual Studio oder Mainstream-Compilern,#pragma onceAufgrund seiner Einfachheit und Bequemlichkeit verhindert es das wiederholte Einbinden von Header-Dateien.Häufig und empfehlenswertPraktiken.



    #pragma warning

    Definition und Verwendung

    #pragma warningsind Präprozessoranweisungen in den Sprachen C und C++, die in bestimmten Codeblöcken verwendet werden.Unterdrücken Sie selektiv den Schweregrad von Compiler-Warnungen, stellen Sie sie wieder her oder ändern Sie sie

    Der Hauptzweck dieser Anweisung besteht darin, eine feinere Kontrolle als Einstellungen auf Projektebene bereitzustellen. Verwenden Sie diesen Befehl beispielsweise, wenn Sie eine ältere Version einer Bibliothek einbinden müssen, die viele Warnungen generiert, die Warnungen aber nicht global deaktivieren möchten.

    Hauptoperationssyntax (MSVC-Format)

    Obwohl#pragma warningDie spezifische Implementierung kann zwischen verschiedenen Compilern leicht variieren (insbesondere MSVC wird am häufigsten verwendet), ihre Kernaktionen sind jedoch in die folgenden Typen unterteilt:

    1. Warnung deaktivieren (Disable)

    Ab diesem Zeitpunkt ignoriert der Compiler den angegebenen Warncode.

    #pragma warning(disable: 4996) // C4996 deaktivieren (zum Beispiel: Warnung vor der Verwendung unsicherer Funktionen)
    // Code enthalten oder schreiben, der C4996 generiert

    2. Wiederherstellungswarnung (Standard)

    Stellt die angegebene Warnung auf das vom Projekt oder der Befehlszeile festgelegte Standardverhalten wieder her.

    #pragma warning(default: 4996) //C4996 auf den Standardzustand zurücksetzen

    3. Status speichern und wiederherstellen (Push and Pop)

    Dies ist der sicherste und am meisten empfohlene Modus. Es ermöglicht die Änderung der Warneinstellungen während der Verarbeitung eines bestimmten Codeblocks und stellt dann sicher, dass der ursprüngliche Warnstatus unmittelbar nach Beendigung des Blocks wiederhergestellt wird, um Nebenwirkungen zu vermeiden.

    #pragma warning( push ) // 1. Speichern Sie die aktuellen Warneinstellungen
    #pragma warning(disable: 4996 4244) // 2. Deaktivieren Sie mehrere spezifische Warnungen
    // Enthält Header-Dateien von Drittanbietern oder Legacy-Code
    #pragma warning( pop ) // 3. Auf die ursprünglichen Einstellungen zurücksetzen
    // Nachfolgender Code verwendet die wiederhergestellten Einstellungen

    4. Warnstufe erhöhen (Fehler)

    Heraufstufen eines bestimmten Warncodes zu einem Kompilierungsfehler. Wenn die Warnung auftritt, schlägt die Kompilierung fehl.

    #pragma warning( error : 4005 ) // Warnung 4005 als Fehler behandeln

    Dinge zu beachten



    C++-Standard-Namespace

    Überblick

    In der C++-Programmierungstd::Bezieht sich auf den Standard-Namespace. Es handelt sich um einen Container, der alle Standardentitäten im C++-Sprachkern und seiner Standardbibliothek (Standardbibliothek) enthält, einschließlich Funktionen, Klassen, Vorlagen, Makros und Objekte.

    verwendenstd::Der Hauptzweck besteht darin, zu vermeidenNamenskollisionen. Wenn eine Standardfunktion (z.B.coutodervector) werden nicht in einem separaten Namensraum platziert. Wenn der Benutzer eine Entität mit demselben Namen definiert, weiß der Compiler nicht, welche Entität verwendet werden soll.

    Der Hauptinhalt von std::

    Die meisten Funktionen der C++-Standardbibliothek befinden sich instd::innerhalb des Namensraums. Zu den Hauptkategorien und Funktionen gehören:

    1. Eingabe-/Ausgabeströme (I/O-Ströme)

    2. Standardcontainer (Container)

    Sammlungskategorien, die zum Speichern von Daten verwendet werden:

    3. Algorithmen

    Eine Reihe allgemeiner Funktionen für Container- und Bereichsoperationen:

    4. Andere Kerntools (Dienstprogramme)

    Mit std::

    zugreifenstd::Es gibt zwei Hauptmethoden für Entitäten in einem Namespace:

    1. Vollständig qualifizierte Namen

    Schreiben Sie es jedes Mal deutlich, wenn Sie es verwendenstd::Präfix. Dies ist der sicherste und empfohlene Ansatz, insbesondere bei Header-Dateien, um eine Verschmutzung des globalen Namespace zu vermeiden.

    
    int main() {
        std::cout << "Hello World" << std::endl;
        std::vector<int> numbers;
        return 0;
    }
    

    2. Deklarationen verwenden (Direktiven verwenden)

    verwendenusing namespace std;Das Ganzestd::Der Inhalt des Namespace wird in den aktuellen Bereich eingeführt und der Name kann direkt ohne verwendet werdenstd::Präfix.

    #include <iostream>
    Verwenden des Namensraums std; // std::-Namespace einführen
    
    int main() {
        cout << „Hallo Welt“ << endl; // Kein std::-Präfix erforderlich
        Vektor<int> Zahlen;
        0 zurückgeben;
    }

    Obwohlusing namespace std;Praktisch, sollte aber in großen Projekten oder Header-Dateien vermieden werden, da es das Risiko von Namenskonflikten erhöht.



    std::string

    1. Deklaration und Anfangswert

    In C++,std::stringIst eine Kategorie (Klasse). Wenn Sie astd::stringWenn einer Variablen kein Anfangswert zugewiesen wird, ruft sie den Standardkonstruktor auf.

    #include <string>
    #include <iostream>
    
    void initialization_example() {
        std::string s; // deklariert, aber kein Wert angegeben
        
        std::cout << "Länge: " << s.length() << std::endl; // Ausgabe: 0
        std::cout << "Inhalt: '" << s << "'" << std::endl; // Ausgabe: ''
    }

    2. So prüfen Sie, ob es leer ist (Empty)

    Um zu überprüfen, ob eine Zeichenfolge keine Zeichen enthält, empfiehlt sich die Verwendungempty()Memberfunktionen, die besser sind als die Überprüfunglength() == 0In einigen Containern semantischer und effizienter.

    void check_empty(std::string s) {
        if (s.empty()) {
            std::cout << „Dies ist eine leere Zeichenfolge.“ << std::endl;
        }
    }

    3. Wie überprüfe ich, ob es Null ist?

    Dies ist ein häufiges Missverständnis:Das std::string-Objekt selbst ist niemals null.

    In C++ können nur „Zeiger“ seinnullptr. Wenn Sie sich auf die Überprüfung beziehen, ob einer Zeichenfolge kein Wert zugewiesen wurde, prüfen Sie normalerweise, ob dies der Fall istempty(). Wenn Sie es mit String-Zeigern im C-Stil zu tun haben (char*), müssen Sie nach Null suchen.

    Typ Methode prüfen Bemerkung
    std::string s; s.empty() Überprüfen Sie, ob die Inhaltslänge 0 beträgt
    std::string* ptr; ptr == nullptr Prüfen Sie, ob der „Indikator“ selbst auf eine Lücke hinweist
    char* c_str; c_str == nullptr Überprüfen Sie, ob der Zeichenfolgenzeiger im C-Stil leer ist

    4. Methode zum Löschen der Zeichenfolge

    Wenn Sie eine vorhandene Zeichenfolge in ihren ursprünglichen leeren Zustand zurückversetzen möchten, können Sie die folgende Methode verwenden:

    void clear_example() {
        std::string s = "Hallo";
        
        s.clear(); // Methode 1: Am häufigsten verwendet
        s = ""; // Methode 2: Neu zuweisen
        s = std::string(); // Methode 3: Ein Standardobjekt zuweisen
    }


    float zu std::string

    1. Verwenden Sie std::to_string (die einfachste Methode)

    Dies ist die einfachste in C++11 eingeführte Methode, bei der ein numerischer Wert in eine Zeichenfolge konvertiert wird. Standardmäßig werden 6 Dezimalstellen beibehalten.

    #include <string>
    #include <iostream>
    
    void simple_convert() {
        Float-Wert = 3,14159f;
        std::string s = std::to_string(val);
        
        std::cout << s << std::endl; // Ausgabebeispiel: „3.141590“
    }

    2. Verwenden Sie std::stringstream (benutzerdefinierte Präzision)

    Wenn Sie die Anzahl der Dezimalstellen oder ein bestimmtes Format steuern müssen,stringstreamEs ist die flexibelste Option. es verbindet<iomanip>Bibliothek zur präzisen Steuerung der Ausgabe.

    #include <sstream>
    #include <iomanip>
    
    void precision_convert() {
        Float-Wert = 3,1415926f;
        std::stringstream ss;
        
        // Festkomma-Zählmethode festlegen (fest) und 2 Dezimalstellen beibehalten
        ss << std::fixed << std::setprecision(2) << val;
        
        std::string s = ss.str();
        std::cout << s << std::endl; // Ausgabe: „3.14“
    }

    3. Verwenden Sie std::format (C++20-effiziente Methode)

    In C++20 können Sie Formatzeichenfolgen verwenden, um die Typkonvertierung und Präzisionskontrolle gleichzeitig mit der prägnantesten Syntax durchzuführen.

    #include <format>
    
    void modern_format() {
        Float-Wert = 123,456f;
        
        // {:.2f} stellt den Float-Typ dar und behält zwei Dezimalstellen bei
        std::string s = std::format("{:.2f}", val);
        
        std::cout << s << std::endl; // Ausgabe: „123,46“ (wird automatisch gerundet)
    }

    4. Verwandte Verarbeitungsnutzung: Entfernen Sie zusätzliche Nullen am Ende

    std::to_stringOft gibt es zusätzliche Nullen wie „3.140000“. Sie können kombinierenfind_last_not_ofUnderaseum die Saite zu bereinigen.

    std::string remove_trailing_zeros(float val) {
        std::string s = std::to_string(val);
        
        // Nachgestellte „0“ entfernen, bis ein Zeichen ungleich Null gefunden wird
        s.erase(s.find_last_not_of('0') + 1, std::string::npos);
        
        // Wenn das letzte Zeichen ein Dezimalpunkt ist, entfernen Sie ihn ebenfalls
        if (s.back() == '.') {
            s.pop_back();
        }
        return s;
    }

    Vergleich der Konvertierungsmethoden

    Verfahren Merkmale Vorgeschlagene Szenarien
    std::to_string Die Syntax ist am kürzesten und die Leistung ist akzeptabel Schnelles Debuggen, wenn keine Anforderungen an die Anzahl der Dezimalstellen bestehen
    std::stringstream Hochgradig anpassbar (keine Polsterung, Breite, Tragfähigkeit) Wenn das Ausgabeformat streng kontrolliert werden muss
    std::format Typsicherheit, Leistung und moderne Syntax Bevorzugte Lösung in einer C++20-Umgebung
    sprintf (C-Stil) Extrem schnell, aber weniger sicher Pflege von altem Code mit extremem Streben nach Leistung


    std::string-Trennzeichen-Analyse

    1. Verwenden Sie die Schleifenanalyse std::string::find

    Dies ist der Standardansatz in C++, der nicht auf externen Bibliotheken basiert. durchfindFinden Sie die Position des Trennzeichens und verwenden Sie essubstrTeilzeichenfolge abrufen.

    #include <iostream>
    #include <vector>
    #include <string>
    
    void split_by_ three_chars() {
        std::string text = "Apfel---Banane---Kirsche---Datum";
        std::string delimiter = "---";
        std::vector<std::string> Token;
        
        size_t pos = 0;
        size_t last_pos = 0;
    
        //Schleife, um Trennzeichen zu finden
        while ((pos = text.find(delimiter, last_pos)) != std::string::npos) {
            tokens.push_back(text.substr(last_pos, pos - last_pos));
            last_pos = pos + delimiter.length();
        }
        
        //Das letzte Fragment einfügen
        tokens.push_back(text.substr(last_pos));
    
        //Ergebnis ausgeben
        for (const auto& t : tokens) std::cout << „[“ << t << "]" << std::endl;
    }

    2. Verwenden Sie std::string_view (C++17-Leistungsoptimierung).

    Wenn Ihre Zeichenfolge sehr groß ist, verwenden Siestd::string_viewDadurch kann vermieden werden, dass während des Aufteilungsprozesses eine große Anzahl von Zeichenfolgenkopien generiert wird, wodurch die Leistung erheblich verbessert wird.

    
    #include <string_view>
    #include <vector>
    
    std::vector<std::string_view> split_sv(std::string_view str, std::string_view del) {
        std::vector<std::string_view> output;
        size_t first = 0;
    
        while (first < str.size()) {
            const auto second = str.find(del, first);
            if (second == std::string_view::npos) {
                output.emplace_back(str.substr(first));
                break;
            }
            output.emplace_back(str.substr(first, second - first));
            first = second + del.size();
        }
        return output;
    }
    

    3. Verwenden Sie reguläre Regex-Ausdrücke

    Wenn Sie möchten, dass Ihr Code prägnanter aussieht oder sich die Trennzeichen ändern, können Sie Folgendes verwendenstd::regex. Beachten Sie jedoch, dass die Ausführungsleistung regulärer Ausdrücke normalerweise besser ist als die manueller Ausführungfindlangsam.

    #include <regex>
    
    void regex_split() {
        std::string text = "Eins###Zwei###Drei";
        std::regex ws_re("###"); // 3-stelliges Trennzeichen definieren
        
        std::copy(std::sregex_token_iterator(text.begin(), text.end(), ws_re, -1),
                  std::sregex_token_iterator(),
                  std::ostream_iterator<std::string>(std::cout, "\n"));
    }

    Vergleich analytischer Methoden

    Verfahren Vorteil Mangel
    std::find + substr Höchste Kompatibilität (C++98+) und stabile Leistung. Der Code ist langwierig und erfordert eine manuelle Verarbeitung des letzten Fragments.
    string_view Am effektivsten, wird keine zusätzliche Speicherkopie erzeugt. Erfordert C++17-Unterstützung und es muss auf den ursprünglichen String-Lebenszyklus geachtet werden.
    std::regex Die Syntax ist die prägnanteste und erweiterbarste. Die Ausführungsgeschwindigkeit ist am langsamsten und die Kompilierungszeit länger.


    Überprüfen Sie, ob std::vector leer ist

    Überblick

    In C++ zur Überprüfungstd::vectorWenn der Container keine Elemente enthält (d. h. die Größe Null hat), ist die Verwendung seiner Mitgliedsfunktionen die üblichste und empfohlene Methodeempty(). Das liegt daranempty()Funktionen sind in der Regel besser als direkte Prüfungensize()Ist gleich Null effizienter, insbesondere in einigen Containerimplementierungen.

    Methode prüfen

    1. Verwenden Sie die Funktion empty() (empfohlen)

    Dies ist die bevorzugte Methode, um zu überprüfen, ob ein Vektor leer ist. Es gibt einen booleschen Wert zurück: Wenn der Vektor keine Elemente hat, wird er zurückgegebentrue; Ansonsten zurückfalse

    #include <vector>
    #include <iostream>
    #include <string>
    
    void check_empty(const std::vector<std::string>& vec)
    {
        if (vec.empty()) {
            std::cout << „Vektor ist leer (empty() == true).“ << std::endl;
        } sonst {
            std::cout << "Vektor ist nicht leer (empty() == false). Anzahl der Elemente: " << vec.size() << std::endl;
        }
    }
    
    int main()
    {
        std::vector<std::string> empty_vec;
        std::vector<std::string> non_empty_vec = {"Apfel", "Banane"};
    
        check_empty(empty_vec);
        check_empty(non_empty_vec);
    
        0 zurückgeben;
    }

    2. Überprüfen Sie die Funktion size()

    Dies ist zwar gültig, aber nicht die idiomatischste oder möglicherweise effizienteste Methode zur Überprüfung des Leerstatus. Es prüft direkt, ob die Anzahl der Elemente im Vektor Null ist.

    void check_size(const std::vector<int>& vec)
    {
        if (vec.size() == 0) {
            std::cout << „Vektor ist leer (size() == 0).“ << std::endl;
        } sonst {
            std::cout << „Vektor ist nicht leer (size() != 0).“ << std::endl;
        }
    }

    Effizienzüberlegungen

    fürstd::vectorBezüglichempty()Undsize() == 0Die Zeitkomplexität beträgt $O(1)$, da der Vektor seine Größe als Mitgliedsvariable speichert. Für einige andere C++-Standardcontainer (z. B.std::listoderstd::forward_list), ist die Standardempfehlung immer die Verwendungempty(), da es im Allgemeinen die gebräuchlichste und schnellste Redewendung in der C++-Standard-Containerbibliothek zur Überprüfung auf leeren Status ist.



    C++ analysiert String in String-Vektor

    Überblick

    In C++ ein Zeichen, das ein Leerzeichen oder Tabulatorzeichen enthält (\t) getrennte Zeichenfolge wird in einzelne Wörter oder Token analysiert und in gespeichertstd::vector<std::string>, die häufigste Methode ist die Verwendung von **std::stringstream**. Kategorie „Datei-Streaming“.std::stringstreamWie ein In-Memory-Stream verwendet er standardmäßig Leerzeichen (einschließlich Leerzeichen, Tabulatoren und Zeilenumbrüche) als Trennzeichen für Lesevorgänge.

    Codebeispiel

    Folgendes wird verwendetstd::stringstreamBeispiel für C++-Code, der diese Aufgabe erfüllt:

    #include <iostream>
    #include <sstream> // Stringstream einschließen
    #include <string>
    #include <vector>
    
    Verwenden des Namensraums std;
    
    /**
     * Trennen Sie die Eingabezeichenfolge durch Leerzeichen (Leerzeichen oder Tabulator) und speichern Sie sie im Vektor.
     * @param input_str Die zu analysierende Zeichenfolge.
     * @return Ein Vektor, der alle getrennten Wörter enthält.
     */
    Vektor<string> split_string_by_whitespace(const string& input_str)
    {
        Vektor<string> Token;
        
        // 1. Erstellen Sie ein Stringstream-Objekt und initialisieren Sie es mit der Eingabezeichenfolge
        stringstream ss(input_str);
        
        String-Token;
        
        // 2. Schleifenlesung
        // Der Stream-Extraktionsoperator (>>) liest automatisch das nächste Token unter Verwendung von Leerzeichen (Leerzeichen, Tab usw.) als Trennzeichen.
        // Der Operator gibt „true“ zurück, wenn ein Token erfolgreich gelesen wurde, andernfalls (das Ende der Zeichenfolge ist erreicht) gibt er „false“ zurück.
        while (ss >> token)
        {
            tokens.push_back(token);
        }
        
        Rückgabemarken;
    }
    
    int main()
    {
        //Die Eingabezeichenfolge enthält mehrere Leerzeichen und Tabulatorzeichen (\t)
        string test_string = „Hallo \tWorld, das ist ein Teststring“;
        
        cout << "Originalzeichenfolge: " << test_string << endl;
        
        Vektor<string> result = split_string_by_whitespace(test_string);
        
        cout << „--- separate Ergebnisse ---“ << endl;
        
        for (size_t i = 0; i < result.size(); ++i)
        {
            cout << „Token“ << i + 1 << ": [" << Ergebnis[i] << "]" << endl;
        }
        
        0 zurückgeben;
    }

    Erklärung des Schlüsselmechanismus



    Mehrdimensionales C++-Array, initialisiert auf 0

    Initialisiert mit std::array

    In C++ können Sie verwendenstd::arrayInitialisieren Sie ein mehrdimensionales Array auf 0:

    #include <iostream>
    #include <array>
    Verwenden des Namensraums std;
    
    int main() {
        array<array<int, 4>, 3> arr = {0}; // Alle Elemente auf 0 initialisieren
    
        for (int i = 0; i < 3; i++) {
            for (int j = 0; j < 4; j++) {
                cout << arr[i][j] << " ";
            }
            cout << endl;
        }
        0 zurückgeben;
    }

    Dinge zu beachten



    C++-Standard-Array-Schleifenmethode

    Überblick

    In C++ ist eine Schleife die grundlegende Operation zum Durchlaufen aller Elemente in einem Container oder Array.std::vector(dynamisch dimensionierter Container) undstd::array(Container mit fester Größe) sind Container in der C++-Standardbibliothek (STL), deren Elemente auf verschiedene standardmäßige und sichere Weise iteriert werden können.

    1. Bereichsbasierte for-Schleife

    Dies ist die modernste, sicherste und prägnanteste Traversierungsmethode, die in C++11 eingeführt wurde. Es funktioniert mit allen Standardcontainern (einschließlichstd::vectorUndstd::array)。

    Anwendbarkeit:

    #include <iostream>
    #include <vector>
    #include <array>
    
    void range_based_loop_example()
    {
        std::vector<int> vec = {10, 20, 30};
        std::array<int, 4> arr = {1, 2, 3, 4};
        
        // Auto& verwenden durch Referenz zu durchlaufen, was effizient ist und die Änderung von Elementen ermöglicht
        std::cout << „--- Vektor (veränderbar) ---“ << std::endl;
        for (auto& element : vec) {
            Element += 1; // Element ändern
            std::cout << Element << " ";
        }
        std::cout << std::endl;
        
        // const auto& verwenden Durchlaufen mit konstanter Referenz, was sicher ist und keine Änderung von Elementen zulässt
        std::cout << „--- Array (schreibgeschützt) ---“ << std::endl;
        for (const auto& element : arr) {
            std::cout << Element << " ";
        }
        std::cout << std::endl;
    }

    2. Indexbasierte for-Schleife

    Dies ist eine traditionelle und universelle Methode. Geeignet für Situationen, in denen Sie auf Elementindizes zugreifen müssen (zum Beispiel: Sie müssen zwei Container oder Arrays gleichzeitig betreiben oder bei einem bestimmten Index enden).

    Anwendbarkeit:

    #include <iostream>
    #include <vector>
    #include <array>
    
    void index_loop_example()
    {
        std::vector<std::string> Namen = {"Alice", "Bob", "Charlie"};
        std::array<double, 3> Preise = {10,5, 20,99, 5,0};
        
        // Verwenden Sie size_t oder auto mit size(), um sicherzustellen, dass der Indextyp korrekt und die Grenzen sicher sind
        for (size_t i = 0; i < name.size(); ++i) {
            // Operator[] verwenden, um auf Elemente zuzugreifen
            std::cout << "Name: " << Namen[i] << ", Preis: " << Preise[i] << std::endl;
        }
    }

    HINWEIS: Verwenden[]C++ führt keine Grenzprüfung durch, wenn Operatoren auf Elemente zugreifen. Wenn eine Grenzüberprüfung erforderlich ist, verwenden Sieat()Funktion (es wird ausgelöst, wenn es außerhalb der Grenzen liegtstd::out_of_rangeabnormal).

    3. Iteratorschleife

    Dies ist die flexibelste Traversal-Methode in C++ und funktioniert mit allen Standardcontainern. Iteratoren sind für die Interaktion mit STL-Algorithmen (C++ Standard Library) erforderlich.

    Anwendbarkeit:

    #include <iostream>
    #include <vector>
    
    void iterator_loop_example()
    {
        std::vector<double> Werte = {100,0, 50,0, 10,0};
        
        // Vereinfachen Sie den Iteratortyp mit auto und verwenden Sie begin() und end(), um den Bereich abzurufen
        for (auto it = value.begin();
             it != Values.end();
             ++es)
        {
            *it /= 10,0; // *es dereferenziert den Iterator und greift auf Elemente zu
            std::cout << *es << " ";
        }
        std::cout << std::endl;
        
        // Verwenden Sie cbegin() und cend(), um sicherzustellen, dass der Iterator für die schreibgeschützte Durchquerung konstant ist
        for (auto cit = Values.cbegin(); cit != Values.cend(); ++cit)
        {
            // Versuche *cit = 5; führt zu einem Kompilierungsfehler
            std::cout << *cit << " ";
        }
        std::cout << std::endl;
    }

    Zusammenfassung und Empfehlungen

    Schleifenmethode Anwendbare Behälter Vorteil Anwendbarer Zeitpunkt
    Reichweitenbasiert std::vector, std::array, alle Standardcontainer Die sauberste, sicherste und moderne C++-Sprache. Es ist kein Index erforderlich, nur jedes Element muss durchlaufen werden.
    Indexbasiert std::vector, std::array Auf Indizes kann zugegriffen werden und sie weisen eine hohe Vielseitigkeit auf. Wenn Sie den Index eines Elements kennen oder bearbeiten müssen.
    Iterator Alle Standardcontainer Äußerst flexibel und einsetzbar mit STL-Algorithmen wie zstd::find) passt perfekt. Wenn Sie STL-Algorithmen verwenden oder komplexe Vorgänge an Containern ausführen müssen.


    Methode zum Kopieren des Inhalts eines mehrdimensionalen std::array

    Problemsituation

    std::array<std::array<std::array<float, 2>, 2>, 2> twoLines;
    std::array<std::array<std::array<float, 2>, 2>, 2> twoLinesCopy;
    

    Lösung 1: Direkt angeben (= Operator)

    std::arrayUnterstützt das vollständige Kopieren von flachen zu tiefen Ebenen, sodass es direkt verwendet werden kann=

    twoLinesCopy = twoLines;
    

    Lösung 2: Verwenden Sie std::copy

    std::copy(twoLines.begin(), twoLines.end(), twoLinesCopy.begin());
    

    Lösung 3: Verwenden Sie std::memcpy (geeignet für POD-Typ, hier gilt float)

    std::memcpy(&twoLinesCopy, &twoLines, sizeof(twoLines));
    

    Anregung



    Speicherzugriffsfehler des C++-Capture-Indikators

    Überblick

    In C++ passiert dies, wenn Sie auf einen ungültigen oder außerhalb der Grenzen liegenden Speicherort zugreifen, wenn Sie Zeiger manipulieren oder Indizes verwenden, um auf Arrays/Speicher zuzugreifen.Undefiniertes Verhalten. Dieses Verhalten manifestiert sich normalerweise als ProgrammAbsturz, wie etwa ein Segmentierungsfehler oder ein Zugriffsverletzungsfehler.

    C++-Standardtry-catchDer Mechanismus wird hauptsächlich zum Abfangen von C++-Ausnahmen (Exceptions) verwendet, die explizit im Programmcode ausgelöst werden, kann jedoch vom Betriebssystem ausgegebene Hardware- oder Speicherzugriffsfehler nicht direkt abfangen.

    Warum kann Try-Catch keine Speicherzugriffsfehler abfangen?

    Wenn ein C++-Programm versucht, auf ungültigen Speicher zuzugreifen, zum Beispiel:

    1. Zugang außerhalb der Grenzen:Greifen Sie nach dem Ende des Arrays auf den Speicher zu.
    2. Dereferenzieren eines Nullzeigers:Es wurde versucht, an der Adresse zu lesen oder zu schreibennullptrder Erinnerung.
    3. Kostenlose Nutzung:Zugriff bestandendeleteoderfreeFreier Speicher.

    Diese Vorgänge lösen den Schutzmechanismus des zugrunde liegenden Betriebssystems aus (z. B. Zugriffsverletzung unter Windows oder SIGSEGV-Signal unter Unix/Linux) und das Programm wird vom Betriebssystem beendet. Bei diesen Fehlern handelt es sich nicht um Ausnahmeobjekte auf C++-Sprachebene (z. Bstd::exception), also der Standardtry-catchEs gibt keine Möglichkeit, sie einzufangen.

    Fehlerbeispiel (Standard-Try-Catch funktioniert nicht)

    #include <iostream>
    #include <vector>
    
    Verwenden des Namensraums std;
    
    void crash_function()
    {
        // Beispiel für einen Array-Out-of-Bounds-Zugriff
        Vektor<int> vec = {10, 20};
        cout << „Versuch, auf den Index außerhalb des zulässigen Bereichs zuzugreifen …“ << endl;
        
        // Dies ist ein undefiniertes Verhalten und führt wahrscheinlich zu einem Absturz aufgrund einer Zugriffsverletzung
        int value = vec[100]; // Fehler: Zugriff auf ungültigen Index
        cout << "Wert: " << Wert << endl;
    }
    
    int main()
    {
        Versuchen Sie es
        {
            crash_function();
            //Das Programm stürzt bei vec[100] oben ab und wird hier nicht ausgeführt.
            // Und der Catch-Block wird nicht ausgeführt.
        }
        Catch (const Ausnahme& e)
        {
            // Fehler auf Betriebssystemebene können hier nicht erfasst werden
            cerr << „C++-Ausnahme abgefangen: „ << e.what() << endl;
        }
        fangen(...)
        {
            // Speicherzugriffsfehler können immer noch nicht erkannt werden
            cerr << „Unbekannte Ausnahme abgefangen“ << endl;
        }
    
        0 zurückgeben;
    }

    Wie gehe ich mit solchen Fehlern um?

    1. Sichere C++-Mechanismen verwenden (bevorzugt)

    Der beste Ansatz besteht darin, das Auftreten solcher Fehler während der Entwurfsphase Ihres Codes zu verhindern, anstatt zu versuchen, sie abzufangen:

    void safe_function()
    {
        Vektor<int> vec = {10, 20};
        Versuchen Sie es
        {
            int value = vec.at(100); // std::out_of_range-Ausnahme auslösen
            cout << "Wert: " << Wert << endl;
        }
        Catch (const std::out_of_range& e)
        {
            // C++-Ausnahme erfolgreich abgefangen
            cerr << „Sichere Erfassung:“ << e.what() << endl;
        }
    }

    2. Verwenden Sie die plattformspezifische strukturierte Ausnahmebehandlung (SEH)

    In einer Windows-Umgebung können Sie die erweiterte strukturierte Ausnahmebehandlung (Structured Exception Handling, SEH) von Microsoft verwenden, um Fehler auf Betriebssystemebene, einschließlich Zugriffsverletzungen, abzufangen. Dies erfolgt in der Regel mit__tryUnd__exceptSchlüsselwörter.

    Hinweis: SEH ist kein Standard und wird nicht für die Verwendung in portablem C++-Code empfohlen. In C++/CLI-Projekten können Sie .NET verwendentry/catchFangen Sie einige SEH-Ausnahmen ab, dies erfordert jedoch bestimmte Compilereinstellungen (z. B./EHa)。



    C++ fängt einen Fehler beim Zugriff auf den Array-Indexspeicher ab

    Überblick

    Wenn Sie in C++ ein Roharray (Array im C-Stil) oder einen Zeiger für Indizierungsvorgänge verwenden, kommt es zu einem Fehler, wenn auf einen Speicherort zugegriffen wird, der außerhalb des Bereichs des Arrays liegt oder ungültig ist.Undefiniertes Verhalten. Dieses Verhalten führt häufig dazu, dass Programme auf Betriebssystemebene ausgeführt werdenAbsturz, wie z. B. Zugriffsverletzung oder Segmentierungsfehler.

    Die wichtigsten Punkte sind:C++-Standardtry-catchDer Mechanismus dient dazu, C++-Ausnahmen (Exceptions) abzufangen, die explizit im Programmcode ausgelöst werden. Vom Betriebssystem ausgegebene Hardware- oder Speicherschutzfehler können nicht erkannt werden.

    Warum funktioniert das Standard-Try-Catch nicht?

    Wenn ein C++-Programm versucht, auf ungültigen Speicher zuzugreifen (z. B. auf ein statisches Array).arr[100], aber das Array hat nur 10 Elemente), was gegen die Speicherschutzregeln des Betriebssystems verstößt. Das Betriebssystem greift ein und sendet ein Signal oder eine Ausnahme, um das Programm zu beenden und so zu verhindern, dass es das System oder andere Programme beschädigt. Diese Fehler entsprechen nicht der C++-Sprachebenestd::exceptionObjekt und kann daher vom Standard nicht verwendet werdentry-catchBlockerfassung.

    Fehlerdemonstration (Standard-Try-Catch kann Abstürze nicht abfangen)

    #include <iostream>
    #include <stdexclusive> // Standardausnahmen einschließen
    
    Verwenden des Namensraums std;
    
    void crash_function()
    {
        // Primitives Array im C-Stil
        int raw_array[5] = {1, 2, 3, 4, 5};
        cout << „Versuch, auf den Index außerhalb des zulässigen Bereichs zuzugreifen …“ << endl;
        
        // Array-Zugriff außerhalb der Grenzen: Dies ist ein typisches undefiniertes Verhalten
        // Wenn auf einen Speicher zugegriffen wird, auf den das Programm nicht zugreifen darf, wird sofort eine Zugriffsverletzung ausgelöst, die zum Absturz des Programms führt.
        int value = raw_array[100]; // Fehler: Zugriff auf ungültigen Index
        cout << "Wert (falls erreichbar): " << Wert << endl;
    }
    
    int main()
    {
        Versuchen Sie es
        {
            crash_function();
            // Das Programm wird bei raw_array[100] beendet und hier nicht ausgeführt.
        }
        Catch (const Ausnahme& e)
        {
            // Speicherzugriffsfehler auf Betriebssystemebene können hier nicht erfasst werden
            cerr << „C++-Ausnahme abgefangen: „ << e.what() << endl;
        }
    
        0 zurückgeben;
    }

    Richtige Handhabung und Präventionsmethoden (bevorzugt)

    Die beste Vorgehensweise besteht darin, Zugriffe außerhalb der Grenzen vollständig zu vermeiden oder die von C++ bereitgestellten sicheren Container und Methoden zu verwenden, die bei Auftreten eines Fehlers abfangbare C++-Ausnahmen auslösen:

    1. Verwenden Sie std::vector::at()

    fürstd::vectorBehälter, Verwendungat()Memberfunktion statt Original[]Operator. Wenn der Zugriff außerhalb der Grenzen liegt,at()wird werfen **std::out_of_range**Ausnahme, dies ist eine Standard-C++-Ausnahme und kann seintry-catchSicher aufgefangen und entsorgt.

    #include <vector>
    // ... (andere enthalten)
    
    void safe_vector_access()
    {
        std::vector<int> vec = {10, 20};
        Versuchen Sie es
        {
            // Verwenden Sie at() zur Überprüfung der Grenzen
            int value = vec.at(100);
            std::cout << "Wert: " << Wert << std::endl;
        }
        Catch (const std::out_of_range& e)
        {
            // C++-Ausnahme erfolgreich abgefangen
            std::cerr << „Sicher gefangene Out-of-bounds-Ausnahme:“ << e.what() << std::endl;
        }
    }

    2. Vermeiden Sie die Verwendung von Roharrays und verwenden Sie stattdessen std::array

    Eingeführt mit C++11std::arrayErsetzt Arrays im C-Stil. Obwohlstd::arrayvon[]Der Operator wird nicht überprüft, aber es istat()Die Funktion wird auch werfenstd::out_of_rangeabnormal.

    #include <array>
    // ...
    
    void safe_array_access()
    {
        std::array<int, 5> arr = {1, 2, 3, 4, 5};
        Versuchen Sie es
        {
            int value = arr.at(5); // Zugriff außerhalb der Grenzen, Ausnahme auslösen
        }
        Catch (const std::out_of_range& e)
        {
            std::cerr << „std::array Out-of-Bounds-Erfassung:“ << e.what() << std::endl;
        }
    }

    Plattformspezifische strukturierte Ausnahmebehandlung (erweitert/nicht standardmäßig)

    Auf bestimmten Plattformen wie Windows können Sie **Structured Exception Handling (SEH)** verwenden, um vom Betriebssystem ausgegebene Hardwareausnahmen (z. B. Zugriffsverletzungen) abzufangen. Dies erfordert normalerweise die Verwendung einer Microsoft-Erweiterung__tryUnd__exceptSchlüsselwörter. Diese Methode entspricht nicht dem Plattformstandard, beeinträchtigt die Code-Portabilität und wird im Allgemeinen nicht als routinemäßiger Fehlerbehandlungsmechanismus empfohlen.



    C++/CLI-Listenzugriff außerhalb des zulässigen Bereichs

    1. Was passiert, wenn ein Index den zulässigen Bereich verlässt?

    in C++/CLISystem::Collections::Generic::List<T>, wenn Sie versuchen, auf einen Index zuzugreifen, der nicht existiert (z. B.sizeist 1, aber Zugriffindex1), ProgrammGewohnheitBei einem Standardwert (z. B. 0 oder null) wird sofort eine Ausnahme ausgelöst.


    2. Sichere Zugangspraktiken

    Bevor Sie einen Indexzugriff durchführen, sollten Sie dies immer überprüfenCountAttribut oder Verwendungtry-catchBlöcke erfassen potenzielle Fehler.

    //Methode A: Vorinspektion (am meisten empfohlen, beste Leistung)
    if (nums->Count > 1) {
        int value = nums[1];
        // Verarbeitungslogik
    } sonst {
        // Behandeln Sie die Situation mit unzureichendem Index
    }
    
    //Methode B: Ausnahmefang
    versuche es mit {
        int value = nums[1];
    } Catch (System::ArgumentOutOfRangeException^ ex) {
        System::Diagnostics::Debug::WriteLine("Index außerhalb des gültigen Bereichs!");
    }

    3. Leistung in verschiedenen Situationen

    Kontext Ergebnis Bemerkung
    Index existiert (e.g., Count=5, index=1) Geben Sie den richtigen Wert zurück normaler Betrieb.
    Index existiert nicht (e.g., Count=1, index=1) löst eine ArgumentOutOfRangeException aus Das Programm unterbricht die Ausführung.
    Natives C++-Array/std::vector [ ] Undefiniertes Verhalten Möglicherweise erhalten Sie verstümmelten Code oder einen Absturz, es werden jedoch keine .NET-Ausnahmen aktiv ausgelöst.

    4. Zusammenfassung der vorbeugenden Maßnahmen



    Maximale und minimale C++-Standardwerte

    1. C++-Standardbibliotheksfunktionen: std::min und std::max

    In C++ sind die am häufigsten verwendeten Tools in definiert<algorithm>Instd::minUndstd::max. Sie unterstützen grundlegende Typen, Objekte und sogar Initialisierungslisten.

    #include <Algorithmus>
    #include <iostream>
    #include <vector>
    
    void basic_usage() {
        int a = 10, b = 20;
    
        // 1. Vergleiche zwei Zahlen
        int small = std::min(a, b);
        int large = std::max(a, b);
    
        // 2. Initialisierungslisten vergleichen (C++11)
        int low = std::min({5, 1, 9, 3}); // 1 zurückgeben
    
        // 3. std::minmax (C++11) – Maximal- und Minimalwerte gleichzeitig abrufen
        auto result = std::minmax({10, 20, 30, 40});
        std::cout << "Min: " << result.first << ", Max: " << result.second;
    }

    2. Numerische Grenzwerte: FLT_MAX und std::numeric_limits

    Wenn Sie eine „minimale“ Variable initialisieren müssen, setzen Sie sie normalerweise auf die größte positive Zahl, die der Typ ausdrücken kann, um sicherzustellen, dass sie beim ersten Vergleich aktualisiert wird.

    Grenzwerte im C-Stil (von <cfloat> und <climits>)

    Einschränkungen im C++-Stil (die Verwendung von <limits> wird empfohlen)

    std::numeric_limitsBietet eine konsistente und auf Vorlagen basierende Möglichkeit, numerische Eigenschaften abzurufen, was beim Schreiben von generischem Code sehr nützlich ist.

    #include <limits>
    
    void limits_example() {
        // Holen Sie sich den Maximalwert
        float max_f = std::numeric_limits<float>::max();
        int max_i = std::numeric_limits<int>::max();
    
        // Holen Sie sich die „minimale positive Zahl“ (Hinweis: Bei Gleitkommazahlen gibt min() die minimale positive Zahl anstelle der maximalen negativen Zahl zurück)
        float min_positive_f = std::numeric_limits<float>::min();
    
        // Holen Sie sich den „niedrigsten Wert“ (die real kleinste negative Zahl)
        float lowest_f = std::numeric_limits<float>::lowest();
    }

    3. Die Maximal- und Minimalwerte in der Sammlung: std::min_element

    Wenn Sie es zu tun habenstd::vectoroder Array, das Sie verwenden müssenstd::min_elementoderstd::max_element, was sie zurückgeben, istIterator

    #include <vector>
    #include <Algorithmus>
    
    voidcollection_example() {
        std::vector<float> Punkte = {88,5f, 92,0f, 79,5f, 100,0f};
    
        // Holen Sie sich den Iterator des Maximalwerts
        auto it = std::max_element(scores.begin(), scores.end());
    
        if (it != scores.end()) {
            std::cout << „Höchste Punktzahl:“ << *Es;
        }
    }

    4. Hauptunterschiede und Fallstricke

    Name verwenden Dinge zu beachten
    FLT_MAX Minimalwertsuche initialisieren definiert in<cfloat>ist ein Legacy-Makro von C.
    std::min Vergleichen Sie zwei Zahlen oder Listen Wenn die Parametertypen inkonsistent sind (z. B. int und long), muss die Vorlage explizit angegeben werden:std::min<long>(a, b)
    lowest() Ermitteln Sie die kleinste negative Zahl Bei Gleitkommazahlen giltmin()ist die kleinste positive Zahl nahe 0,lowest()ist der maximale negative Wert.
    min_element Suchcontainer Was zurückgegeben wird, ist ein Iterator, und Sie müssen prüfen, ob der Container leer ist, bevor Sie ihn verwenden.


    C++ std erhält pi

    Überblick

    Obwohl die konstante Definition von $\pi$ in der C++-Standardmathematikbibliothek erst in C++20 offiziell standardisiert wurde, gibt es mehrere häufig verwendete Methoden, um in verschiedenen C++-Versionen und Compilerumgebungen Näherungswerte von pi zu erhalten.

    Um die Portabilität und Genauigkeit des Codes sicherzustellen, ist die Verwendung von am empfehlenswertestenstd::numbers::pi

    1. Verwenden Sie C++20-Standardkonstanten (empfohlen)

    Ab C++20 ist die Standardbibliothek<numbers>Präzise und typsichere mathematische Konstanten werden in der Header-Datei bereitgestellt.

    Header-Datei:

    Anwendung:

    #include <iostream>
    #include <numbers> // eingeführt in C++20
    
    void use_cpp20_pi()
    {
        // std::numbers::pi_v<T> ist eine Vorlagenvariable, die einen genauen Wert basierend auf Typ T bereitstellt
        // std::numbers::pi (ohne <T>) ist äquivalent zu std::numbers::pi_v<double>
        
        double pi_double = std::numbers::pi;
        float pi_float = std::numbers::pi_v<float>;
        long double pi_long_double = std::numbers::pi_v<long double>;
    
        std::cout.precision(16); // Ausgabegenauigkeit festlegen
        std::cout << "C++20 (doppelt): " << pi_double << std::endl;
        std::cout << "C++20 (float): " << pi_float << std::endl;
    }

    2. Verwenden Sie Makros der traditionellen C-Sprache (C++17 und früher)

    Vor C++20 verließen sich viele Entwickler auf die C-Mathe-Bibliothek (<cmath>oder<math.h>) stellt ein nicht standardmäßiges Makro bereit. Obwohl diese Makros auf den meisten modernen Systemen vorhanden sind, sind sie nicht Teil des C++-Standards und es kann nicht garantiert werden, dass sie in allen Umgebungen funktionieren.

    Header-Datei:

    Anwendung:

    #include <iostream>
    #include <cmath> // Traditionelle C-Mathematikbibliothek
    
    void use_c_macro_pi()
    {
        // M_PI ist das gebräuchlichste PI-Makro, normalerweise als Doppeltyp definiert.
        // Hinweis: Um dieses Makro zu aktivieren, muss auf einigen Systemen möglicherweise das Makro _USE_MATH_DEFINES definiert werden.
        
        #ifdef M_PI
            double pi_value = M_PI;
            std::cout.precision(16);
            std::cout << "C-Makro (M_PI): " << pi_value << std::endl;
        #sonst
            std::cout << „Das M_PI-Makro ist undefiniert. Möglicherweise müssen Sie _USE_MATH_DEFINES definieren.“ << std::endl;
        #endif
    }

    3. Berechnen oder definieren Sie selbst

    Wenn Sie keine C++20- oder C-Makros verwenden können, können Sie $\pi$ selbst als Konstante definieren oder eine mathematische Funktion zur Berechnung verwenden (z. B. $\arccos(-1)$).

    Anwendung:

    #include <iostream>
    #include <cmath>
    
    void define_or_calculate_pi()
    {
        // Durch mathematische Operationen definieren:
        const double PI_CUSTOM_CALC = std::acos(-1.0);
        
        // Direkt als Konstante definieren:
        const double PI_CUSTOM_DEFINE = 3.14159265358979323846;
    
        std::cout.precision(16);
        std::cout << „Benutzerdefiniert berechnen:“ << PI_CUSTOM_CALC << std::endl;
        std::cout << „Benutzerdefiniert:“ << PI_CUSTOM_DEFINE << std::endl;
    }

    Empfohlene Zusammenfassung



    Berechnen Sie die Standardabweichung einer Liste

    Beispielprogramm

    #include <cmath>
    #include <iostream>
    Verwenden des Namespace-Systems;
    unter Verwendung des Namensraums System::Collections::Generic;
    
    int main()
    {
        //Testdaten erstellen
        Dictionary<int, List<float>^>^ data = gcnew Dictionary<int, List<float>^>();
        data->Add(1, gcnew List<float>({ 1.2f, 2.3f, 3.4f }));
        data->Add(2, gcnew List<float>({ 4.5f, 5.5f, 6.5f, 7.5f }));
        data->Add(3, gcnew List<float>()); // Testen Sie die leere Liste
    
        // Berechnen Sie die Standardabweichung jedes Schlüssels
        für jeden (KeyValuePair<int, List<float>^> Eintrag in Daten)
        {
            int key = enter.Key;
            List<float>^ Values ​​= Entry.Value;
    
            if (Werte == nullptr || Werte->Anzahl == 0)
            {
                Console::WriteLine("Schlüssel {0}: Keine Daten", key);
                weitermachen;
            }
    
            // Berechnen Sie den Durchschnitt
            Doppelsumme = 0,0;
            für jeden (Float v in Werten)
            {
                Summe += v;
            }
            doppelter Mittelwert = Summe / Werte->Anzahl;
    
            // Berechnen Sie die Anzahl der Mutationen (Anzahl der mütterlichen Mutationen)
            doppelte Varianz = 0,0;
            für jeden (Float v in Werten)
            {
                double diff = v – Mittelwert;
                Varianz += diff * diff;
            }
            Varianz /= Werte->Anzahl; // Wenn Sie die Beispielvariation wünschen, ändern Sie sie zu (values->Count - 1)
    
            // Standardabweichung
            double stddev = Math::Sqrt(variance);
    
            Console::WriteLine("Key {0}: Standardabweichung = {1:F4}", key, stddev);
        }
    
        0 zurückgeben;
    }

    veranschaulichen

    Ausgabebeispiel

    Schlüssel 1: Standardabweichung = 0,8981
    Schlüssel 2: Standardabweichung = 1,1180
    Schlüssel 3: Keine Informationen


    std::sort

    1. Grundlegende Verwendung

    std::sortIst der am häufigsten verwendete Sortieralgorithmus in der C++ Standard Template Library (STL). es liegt<algorithm>In der Header-Datei werden standardmäßig Elemente innerhalb des Bereichs angezeigtAufsteigendsortieren.

    #include <Algorithmus>
    #include <vector>
    #include <iostream>
    
    void basic_sort() {
        std::vector<int> Zahlen = {5, 2, 9, 1, 5, 6};
        
        // Sortierbereich: vom Start-Iterator bis zum End-Iterator
        std::sort(nums.begin(), nums.end());
        
        // Ergebnis: 1, 2, 5, 5, 6, 9
    }

    2. Benutzerdefinierte Sortierkriterien (absteigende Potenz oder spezifische Bedingungen)

    Sie können die Sortierlogik ändern, indem Sie den dritten Parameter (Vergleichsfunktion oder Lambda-Ausdruck) übergeben.

    // 1. Vordefiniertes std::greater zur Potenzierung verwenden
    std::sort(nums.begin(), nums.end(), std::greater<int>());
    
    // 2. Verwenden Sie Lambda-Ausdrücke, um die Logik anzupassen
    std::sort(nums.begin(), nums.end(), [](int a, int b) {
        Rückkehr a > b; // Wenn true zurückgegeben wird, wird a vor b gereiht
    });

    3. Struktur- oder Kategoriensortierung

    Für benutzerdefinierte Typen muss eine Vergleichslogik bereitgestellt werden, andernfalls meldet der Compiler einen Fehler, da er nicht weiß, wie Größen verglichen werden sollen.

    Struktur Student {
        std::string name;
        int-Punktzahl;
    };
    
    void sort_students() {
        std::vector<Student> studenten = {{"Alice", 90}, {"Bob", 85}, {"Charlie", 95}};
        
        // Nach Punktzahl von hoch nach niedrig sortieren
        std::sort(students.begin(), Students.end(), [](const Student& a, const Student& b) {
            return a.score > b.score;
        });
    }

    4. Grundprinzip: Introspektive Sortierung (Introsort)

    std::sortKein einzelner Sortieralgorithmus, sondern ein Hybridalgorithmus, der die Vorteile jedes Algorithmus kombiniert und das Worst-Case-Szenario vermeidet. Seine Funktionslogik ist wie folgt:


    Zusammenfassung der Leistung und Funktionen

    Merkmal veranschaulichen
    durchschnittliche Zeitkomplexität $O(n \log n)$
    Schlimmste Zeitkomplexität $O(n \log n)$ (Profitieren Sie vom Introsort-Mechanismus)
    Raumkomplexität $O(\log n)$ (rekursives Aufrufstapeln)
    Stabilität instabil(Die relativen Positionen gleicher Elemente können sich ändern). Wenn Sie eine stabile Sortierung benötigen, verwenden Sie bittestd::stable_sort


    Beurteilung relativer Positionen von Punkten und Geradengleichungen

    1. Mathematische Grundlagen: Punktwerte ersetzen

    Wenn die Gleichung einer Geraden $ax + by + c = 0$ und eines Punktes $P(x_0, y_0)$ gegeben ist, lässt sich die Beziehung zwischen dem Punkt und der Geraden am schnellsten durch Berechnen ermittelnDistanzkoeffizient $d$

    $$d = a \cdot x_0 + b \cdot y_0 + c$$

    Anhand des Vorzeichens von $d$ können wir erkennen, auf welcher Seite der Linie sich der Punkt befindet. Aber das sollte man beachtenDie Definition von „oben“ oder „rechts“ wird durch die Vorzeichen von $a$ und $b$ beeinflusst


    2. Der Beurteilungspunkt liegt über der Linie (y ist kleiner)

    In den meisten Computergrafik-Koordinatensystemen verläuft die y-Achse positiv nach unten (je kleiner das y, desto weiter oben auf dem Bildschirm). Um festzustellen, ob der Punkt $P$ über der Linie liegt, vergleichen wir $y_0$ des Punktes mit $y_{Linie}$, wenn der Punkt mit $x_0$ auf der Linie übereinstimmt.

    // Geradengleichung: ax + by + c = 0 => y = (-ax - c) / b
    bool isAbove(std::array<float, 3> line, float x0, float y0) {
        float a = line[0];
        float b = Zeile[1];
        float c = Zeile[2];
    
        // Wenn b 0 ist, stellt es eine vertikale Linie dar und die obere und untere Linie können nicht definiert werden
        if (std::abs(b) < 1e-6) return false;
    
        float y_on_line = (-a * x0 - c) / b;
        
        // Das kleinere y repräsentiert die Spitze
        Rückgabe y0 < y_on_line;
    }

    3. Der Beurteilungspunkt liegt rechts von der Linie (x ist größer).

    Auf die gleiche Weise vergleichen wir $x_0$ an einem Punkt mit $x_{Linie}$ am gleichen $y_0$ auf der Linie.

    // Geradengleichung: ax + by + c = 0 => x = (-by - c) / a
    bool isRight(std::array<float, 3> line, float x0, float y0) {
        float a = line[0];
        float b = Zeile[1];
        float c = Zeile[2];
    
        // Wenn a 0 ist, stellt es eine horizontale Linie dar und links und rechts können nicht definiert werden
        if (std::abs(a) < 1e-6) return false;
    
        float x_on_line = (-b * y0 - c) / a;
    
        // Das größere x repräsentiert die rechte Seite
        return x0 > x_on_line;
    }

    4. Schnellbeurteilungstabelle (Standardisierung vorausgesetzt)

    Wenn Sie $b sicherstellen können< 0$ (透過將整個方程式乘上 -1),那麼 $ax + by + c >0$ bedeutet direkt, dass der Punkt über der Linie liegt. Das Folgende ist die allgemeine Logik:

    Ziel Urteilslogik Einschränkungen
    Oben (y kleiner) $y_0 < \frac{-ax_0 - c}{b}$ $b \neq 0$ (nicht vertikale Linie)
    Rechts (x ist größer) $x_0 > \frac{-by_0 - c}{a}$ $a \neq 0$ (nicht horizontale Linie)

    Überlegungen zur Implementierung



    Beurteilung der Direktionalität einer Geraden

    1. Beurteilungslogik: Vergleich von Steigung und Koeffizient

    Angesichts der Gleichung einer geraden Linie $ax + by + c = 0$ lässt sich am intuitivsten feststellen, ob sie in Richtung einer „horizontalen Linie“ oder einer „geraden Linie“ tendiert, indem man sich den Winkel zwischen ihr und der Koordinatenachse ansieht. von45 Gradist die Trennlinie, was dem Vergleich der Größen von $|a|$ und $|b|$ entspricht.


    2. Implementierung des Programmcodes

    verwendenstd::absVergleichenline[0]($a$) undline[1]Der absolute Wert von ($b$).

    #include <iostream>
    #include <array>
    #include <cmath>
    
    Enum-Klasse LineOrientation {
        Horizontal, // horizontale Linie (< 45 Grad)
        Vertikal, // gerade Linie (> 45 Grad)
        Diagonale // Genau 45 Grad
    };
    
    LineOrientation checkOrientation(std::array<float, 3> line) {
        float a = std::abs(line[0]);
        float b = std::abs(line[1]);
    
        if (a < b) {
            return LineOrientation::Horizontal;
        } else if (a > b) {
            return LineOrientation::Vertical;
        } sonst {
            return LineOrientation::Diagonal;
        }
    }

    3. Warum reicht es aus, |a| zu vergleichen? und |b|?

    Aus der Steigungsformel $m = -\frac{a}{b}$:


    4. Tabelle der Beurteilungskriterien

    Zustand Einstufung Besonderheit
    |a| < |b| Horizontal Der Winkel zur X-Achse ist klein und eignet sich zur Beurteilung von „Punkt über/unter der Linie“.
    |a| > |b| Vertikal Der Winkel zur Y-Achse ist klein und eignet sich zur Beurteilung des „Punkts links/rechts der Linie“.
    a = 0 absolute horizontale Linie Genau parallel zur X-Achse.
    b = 0 absolute vertikale Linie Genau parallel zur Y-Achse.

    Praktische Vorschläge

    Bei der Beurteilung der Punkt-zu-Linie-Position wird empfohlen, zunächst diese Prüfung durchzuführen:



    C++-Vorlage

    1. Was ist eine Vorlage?

    In C++ ist Vorlage ein generisches Programmiertool, das es uns ermöglicht, Funktionen oder Kategorien zu schreiben, ohne bestimmte Datentypen anzugeben, wodurch der Code wiederverwendbar wird. Vorlagen helfen dabei, verschiedene Datentypen in einem einzigen Code zu verarbeiten und doppelte Funktions- oder Klassendefinitionen zu vermeiden.

    2. Funktionsvorlage

    Mit Funktionsvorlagen können wir Funktionen schreiben, die verschiedene Typen verarbeiten können. Die Syntax der Funktionsvorlage lautet wie folgt:

    template <typename T>
    T add(T a, T b) {
        return a + b;
    }

    In diesem Beispiel,addDie Funktion kann jeden Typ verarbeiten, der Additionsoperationen unterstützt, zintfloatoderdouble

    Wenn Sie es verwenden, können Sie es folgendermaßen aufrufen:

    int result = add(3, 4); // Int-Typ verwenden
    double result2 = add(3.5, 2.7); // Doppeltyp verwenden

    3. Klassenvorlage

    Mit Kategorievorlagen können wir Kategorien erstellen, die auf mehrere Typen angewendet werden können. Die Syntax einer Kategorievorlage lautet wie folgt:

    template <typename T>
    class MyClass {
    private:
        T data;
    public:
        MyClass(T data) : data(data) {}
        T getData() { return data; }
    };

    In diesem BeispielMyClassKategorien können beliebige Datentypen verwendendata

    Sie können es so verwenden:

    MyClass<int> obj1(5); // int-Typ
    MyClass<double> obj2(3.14); // Doppeltyp

    4. Mehrere Vorlagenparameter

    Vorlagen können mehrere Parameter akzeptieren, zum Beispiel:

    template <typename T, typename U>
    class Pair {
    private:
        T first;
        U second;
    public:
        Pair(T first, U second) : first(first), second(second) {}
        T getFirst() { return first; }
        U getSecond() { return second; }
    };

    Eine solche Vorlagenklasse kann zwei verschiedene Arten von Daten speichern:

    Pair<int, double> pair1(1, 3.14);

    5. Vorlagenspezialisierung

    Durch die Vorlagenspezialisierung können wir Vorlagen bestimmter Typen gezielt definieren. Zum Beispiel:

    Vorlage <>
    Klasse MyClass<int> {
    öffentlich:
        MyClass(int data) { /* Spezialisiertes Verhalten */ }
    };

    Dieser Code ist spezialisiertMyClassRechtsintDas Verhalten eines Typs, das ihn von anderen Typen unterscheidet.

    6. Nicht-Typ-Vorlagenparameter

    Vorlagen können auch Nicht-Typ-Parameter akzeptieren, beispielsweise konstante Werte:

    template <typename T, int Size>
    class Array {
    private:
        T data[Size];
    public:
        int getSize() const { return Size; }
    };

    Hier,SizeIst ein nicht typisierter Parameter, der die Größe des Arrays angibt.

    Anwendungsbeispiel:

    Array<int, 10> arr; // Erstelle ein Array vom Typ int mit einer Größe von 10

    7. Fazit

    C++-Vorlagen sind leistungsstark, machen den Code vielseitiger und reduzieren Duplikate. Wenn Sie verstehen, wie Sie Technologien wie Funktionsvorlagen, Kategorievorlagen und Vorlagenspezialisierung verwenden, können Sie die Flexibilität und Leistung der Programmierung erheblich steigern.



    Querverweis auf die C++-Klasse

    1. Problemhintergrund

    In C++, wenn zwei Klassen voneinander abhängig sind und gleichzeitig direkt in ihren jeweiligen Klassen auf die Mitglieder der jeweils anderen Klasse verweisen müssen.hin der Datei#includeDie Definition der anderen Partei führt zu einem Zirkelverweisproblem, das dazu führt, dass die Kompilierung fehlschlägt. Die Lösung besteht darin, „Forward-Deklaration“ zu verwenden, um Zirkelverweise zu vermeiden.

    2. Lösungsschritte

    3. Codebeispiele

    ClassA.h

    // ClassA.h
    #ifndef CLASSA_H
    #define CLASSA_H
    
    // Forward-Deklaration ClassB
    Klasse KlasseB;
    
    Klasse ClassA {
    öffentlich:
        ClassA();
        void setB(ClassB* b); // Den Zeiger auf ClassB setzen
        void showBData(); // ClassB-Daten anzeigen
    
    privat:
        KlasseB* b; // Zeiger auf ClassB
    };
    
    #endif

    ClassB.h

    // ClassB.h
    #ifndef CLASSB_H
    #define CLASSB_H
    
    // Forward-Deklaration ClassA
    Klasse KlasseA;
    
    Klasse KlasseB {
    öffentlich:
        ClassB(int data);
        int getData(); // Daten abrufen
        void setA(ClassA* a); // Den Zeiger auf ClassA setzen
        void showAInfo(); // ClassA-Informationen anzeigen
    
    privat:
        int-Daten;
        KlasseA* a; // Zeiger auf ClassA
    };
    
    #endif

    ClassA.cpp

    
    #include "ClassA.h"
    #include "ClassB.h"
    #include <iostream>
    
    ClassA::ClassA() : b(nullptr) {}
    
    void ClassA::setB(ClassB* b) {
        this->b = b;
    }
    
    void ClassA::showBData() {
        if (b != nullptr) {
            std::cout << "ClassB data: " << b->getData() << std::endl;
        }
    }
            

    ClassB.cpp

    
    #include "ClassB.h"
    #include "ClassA.h"
    #include <iostream>
    
    ClassB::ClassB(int data) : data(data), a(nullptr) {}
    
    int ClassB::getData() {
        return data;
    }
    
    void ClassB::setA(ClassA* a) {
        this->a = a;
    }
    
    void ClassB::showAInfo() {
        if (a != nullptr) {
            a->showBData();
        }
    }
            

    4. Implementierungsanweisungen



    C++ Friend

    In C++,friendSchlüsselwörter können für Funktionen oder Klassen verwendet werden, um anderen Funktionen oder Klassen den Zugriff auf private und geschützte Mitglieder der Klasse zu ermöglichen. Ein solches Design ermöglicht den Betrieb externer Funktionen oder Klassen, ohne das Kapselungsprinzip zu verletzen.

    1. Freundefunktion

    Eine Friend-Funktion ist eine externe Funktion, die Zugriff auf die privaten und geschützten Mitglieder einer anderen Klasse gewährt. Wenn es innerhalb einer Kategorie deklariert wird, enden Sie mitfriendÄndern Sie einfach die Schlüsselwörter.

    Beispiele sind wie folgt:

    #include <iostream>
    Verwenden des Namensraums std;
    
    Klasse Box {
    privat:
        doppelte Breite;
    
    öffentlich:
        Box(double w) : width(w) {}
    
        //Freundfunktion deklarieren
        Freund void showWidth(Box &b);
    };
    
    //Freund-Funktionsdefinition, kann auf private Mitglieder der Box-Klasse zugreifen
    void showWidth(Box &b) {
        cout << "Boxbreite: " << b.width << endl;
    }
    
    int main() {
        Kastenkasten(10,5);
        showWidth(box); // Auf die Breite des privaten Mitglieds zugreifen
        0 zurückgeben;
    }

    In diesem Beispiel,showWidthObwohl es sich bei der Funktion um eine gewöhnliche Funktion außerhalb der Box-Kategorie handelt, kann sie dennoch auf die privaten Mitglieder der Box-Kategorie zugreifen, da sie als Friend-Funktion deklariert ist.width

    2. Kategorie „Freunde“.

    Die Friend-Klasse ermöglicht einer Klasse den Zugriff auf alle Mitglieder einer anderen Klasse. Eine solche Einrichtung ist nützlich, wenn Kategorien eng zusammenarbeiten müssen, sollte jedoch mit Vorsicht verwendet werden, um zu vermeiden, dass zu viele interne Details preisgegeben werden.

    Beispiele sind wie folgt:

    #include <iostream>
    Verwenden des Namensraums std;
    
    Klassenplatz; // Forward-Deklaration
    
    Klasse Rechteck {
    privat:
        doppelte Breite, Höhe;
    
    öffentlich:
        Rechteck(doppelt w, doppelt h) : Breite(b), Höhe(h) {}
    
        // Deklariere die Square-Kategorie als Freund
        Freund-Klasse-Quadrat;
    };
    
    Klasse Quadrat {
    öffentlich:
        double areaOfRectangle(Rectangle &rect) {
            return rect.width * rect.height;
        }
    };
    
    int main() {
        Rechteck rect(5.0, 3.0);
        Quadratisches Quadrat;
        cout << "Fläche des Rechtecks: " << quadrat.areaOfRectangle(rect) << endl;
        0 zurückgeben;
    }

    In diesem Beispiel wird die Square-Klasse als Freundklasse der Rechteck-Klasse deklariert, sodass die Mitgliedsfunktionen in der Square-Klasse direkt auf die privaten Mitglieder der Rechteck-Klasse zugreifen können.widthUndheight

    3. Anwendungsszenarien der Freundesfunktion und der Freundeskategorie

    Seien Sie vorsichtig, wenn Sie Friend-Funktionen und Friend-Klassen in C++ verwenden. Übermäßiger Gebrauch zerstört die Kapselung der Klasse. Daher wird das Schlüsselwort Friend normalerweise nur beim Entwerfen von Klassen oder Funktionen verwendet, die eine enge Zusammenarbeit erfordern.



    C++ liest die Datei Zeile für Zeile

    Überblick

    In C++ ist die Verwendung der Datei-Streaming-Klasse aus der Standardbibliothek die standardmäßigste und empfohlene Methode zum zeilenweisen Lesen einer Textdateistd::ifstreamZusammenarbeitenstd::getlineFunktion.

    std::ifstreamVerantwortlich für das Öffnen und Verwalten des Datei-Streamings undstd::getlineist dafür verantwortlich, eine ganze Textzeile aus dem Stream zu lesen (bis ein Zeilenumbruchzeichen gefunden wird).\n) und speichern Sie es darinstd::stringim Objekt.

    Codebeispiel

    Das Folgende ist ein vollständiges C++-Beispiel, das zeigt, wie eine Datei mit dem Namen Zeile für Zeile gelesen wirdexample.txtDateiinhalte.

    #include <iostream>
    #include <fstream> // Datei-Streaming-Bibliothek einschließen
    #include <string> // String-Kategorie einschließen
    
    Verwenden des Namensraums std;
    
    void read_file_line_by_line(const string& filename)
    {
        // 1. std::ifstream-Objekt erstellen
        //Versuchen Sie, die angegebene Datei zu öffnen.
        ifstream input_file(filename);
        
        // 2. Überprüfen Sie, ob die Datei erfolgreich geöffnet wurde
        if (!input_file.is_open())
        {
            cerr << „Fehler: Datei konnte nicht geöffnet werden“ << Dateiname << endl;
            zurückkehren;
        }
        
        Schnurlinie;
        int Zeilennummer = 1;
        
        // 3. Verwenden Sie die Funktion std::getline, um Zeile für Zeile zu lesen
        // Die Schleifenbedingung (getline(stream, string)) gibt jedes Mal „true“ zurück, wenn der Lesevorgang erfolgreich ist.
        // Wenn das Ende der Datei (EOF) erreicht ist oder ein Fehler auftritt, wird „false“ zurückgegeben und die Schleife endet.
        while (getline(input_file, line))
        {
            cout << „Zeile“ << Zeilennummer << ": " << Zeile << endl;
            Zeilennummer++;
        }
        
        // 4. Datei-Streaming schließen
        // Wenn das input_file-Objekt seinen Gültigkeitsbereich überschreitet, schließt der Destruktor die Datei automatisch.
        // Ein expliziter Aufruf von close() ist aber auch akzeptabel.
        input_file.close();
        
        cout << „Dateilesen abgeschlossen.“ << endl;
    }
    
    int main()
    {
        read_file_line_by_line("example.txt");
        0 zurückgeben;
    }

    Schlüsselkonzepte



    C++ Datei Zeile für Zeile schreiben und Felder ausrichten

    Überblick

    In C++ ist das Konvertieren einer Datenstruktur (z. B. fromstd::vector<std::string>Um die Datei Zeile für Zeile zu schreiben (Tokens einlesen) und sicherzustellen, dass jede Spalte (Token) eine feste Breitenausrichtung in der Zeile beibehält, müssen Sie ** verwendenstd::ofstream** Verwenden Sie **I/O-Stream-Manipulatoren**, um das Ausgabeformat zu steuern.

    Die wichtigsten Tools zur Formatkontrolle sind:

    Codebeispiel

    Im Folgenden finden Sie ein C++-Beispiel für die Konvertierung einer zweidimensionalen Datenstruktur mit mehreren Feldern (unter Verwendung vonstd::vector<std::vector<std::string>>Simulieren) und schreiben Sie die Datei. Stellen Sie dabei sicher, dass jedes Tokenfeld eine feste Breite von 15 Zeichen hat und linksbündig ist.

    #include <iostream>
    #include <fstream> // Dateiausgabestream einschließen
    #include <string>
    #include <vector>
    #include <iomanip> // I/O-Stream-Manipulator einbinden (setw, links/rechts)
    
    Verwenden des Namensraums std;
    
    // Simuliere eine zweidimensionale Datenstruktur, jede Zeile enthält mehrere Felder (Token)
    using TableData = vector<vector<string>>;
    
    void write_aligned_data(const string& filename, const TableData& data, int columns_width)
    {
        // 1. std::ofstream-Objekt erstellen und die Datei öffnen
        ofstream-Ausgabedatei(Dateiname);
        
        // 2. Überprüfen Sie, ob die Datei erfolgreich geöffnet wurde
        if (!output_file.is_open())
        {
            cerr << „Fehler: Datei konnte nicht geöffnet werden“ << Dateiname << „zum Schreiben.“ << endl;
            zurückkehren;
        }
    
        //Globale Ausrichtung festlegen: linksbündig (L-bündig)
        Ausgabedatei << links;
        
        // 3. Daten Zeile für Zeile schreiben
        for (const auto& row : data)
        {
            // 4. Token für Token schreiben und die Breite festlegen
            for (const auto& token : row)
            {
                // setw(width) wirkt sich nur auf das nächste Ausgabeelement aus, das unmittelbar darauf folgt
                Ausgabedatei << setw(column_width) << Token;
            }
            
            // 5. Fügen Sie nach dem Ende der Zeile ein Newline-Zeichen ein, um eine neue Zeile zu beginnen
            Ausgabedatei << "\N";
        }
        
        // 6. Datei-Streaming schließen
        Ausgabedatei.close();
        
        cout << „Daten wurden erfolgreich in die Datei geschrieben: „ << Dateiname << endl;
    }
    
    int main()
    {
        //Beispieldaten: enthält vier Zeilen, jede Zeile hat drei Felder
        TableData-Daten = {
            {"Name", "Artikel", "Preis"},
            {"Alice", "Buch", "19,99"},
            {"BobJohnson", "PenSet", "4.50"},
            {"Charlie", "Notebook", "800.75"}
        };
        
        const int COLUMN_WIDTH = 15; // Definieren Sie die Breite jeder Spalte
        
        write_aligned_data("output_aligned.txt", data, COLUMN_WIDTH);
        
        0 zurückgeben;
    }

    Analyse von Schlüsseltechnologien



    vcpkg C++-Paketmanager

    1. Laden Sie den vcpkg-Quellcode herunter

    vcpkg wird nicht über die Installationsdatei installiert, sondern kopiert den Quellcode direkt von GitHub nach lokal. Es wird empfohlen, es im Stammverzeichnis der Festplatte zu platzieren (z. BC:\vcpkg), um Pfade zu vermeiden, die zu lang sind oder Leerzeichen enthalten. Bitte öffnen Sie das Terminal (CMD oder PowerShell) und führen Sie Folgendes aus:

    git clone https://github.com/microsoft/vcpkg.git
    cd vcpkg

    2. Führen Sie die Erstkompilierung durch (Bootstrap).

    Nach dem Herunterladen müssen Sie das Skript ausführen, um die ausführbare Datei von vcpkg zu kompilieren, die generiert wirdvcpkg.exe

    3. Integration in die Entwicklungsumgebung

    Dieser Schritt ermöglicht es Entwicklungstools (wie Visual Studio), die von vcpkg installierten Pakete automatisch zu erkennen:

    Gemeinsame Befehlsvergleichstabelle

    Anweisung veranschaulichen Beispiel
    search Suchen Sie nach verfügbaren Paketen vcpkg search libuv
    install Installieren Sie die angegebenen Pakete vcpkg install libuv:x64-windows
    list Installierte Pakete auflisten vcpkg list
    update Suchen Sie nach Aktualisierungen der Paketversion vcpkg update

    Umgebungsvariablen festlegen (empfohlen)

    Um die Verwendung von vcpkg in jedem Pfad zu erleichtern, wird empfohlen, den vcpkg-Ordnerpfad zum System hinzuzufügenPATHin Umgebungsvariablen. Wenn Sie das 64-Bit-Paket standardmäßig installieren möchten, können Sie außerdem eine Umgebungsvariable hinzufügenVCPKG_DEFAULT_TRIPLETund setzen Sie den Wert aufx64-windows

    Dinge zu beachten

    Stellen Sie vor der Verwendung von vcpkg unter Windows sicher, dass es installiert istVisual Studio 2015 oder neuer, und überprüfen Sie die Arbeitslast „Desktop-Entwicklung mit C++“ (einschließlich englischem Sprachpaket), da es sonst beim Kompilieren des Pakets zu Fehlern kommen kann.



    Entwicklung von Peripheriesteuerungsprogrammen

    Definition

    Peripheriesteuerungsprogramme sind Anwendungen zur Kommunikation und zum Betrieb externer Hardwaregeräte (z. B. Drucker, Scanner, Motoren, SPS, Sensoren usw.), die an den Computer oder Host angeschlossen sind.

    Gemeinsame Kommunikationsschnittstellen

    Gemeinsame Entwicklungssprachen und Umgebungen

    SpracheAnwendbare SituationenBemerkung
    PythonSchnelle Entwicklung, TestautomatisierungGilt für Seriell, USB HID
    C/C++Entwicklung eingebetteter Steuerungen und TreiberZugriff auf Low-Level-Speicher und Hardware
    C#Windows-Benutzeroberfläche + SteuergerätGeeignet für COM-Port und USB-Kommunikation
    JavaPlattformübergreifende SteuerungWird bei Low-End-Geräten seltener verwendet

    Beispiel 1: Verwendung von Python zur Steuerung der seriellen Schnittstelle

    Seriennummer importieren
    
    ser = serial.Serial('COM3', 9600, timeout=1)
    ser.write(b'ON\n') # Steuerbefehle senden
    Antwort = ser.readline()
    print("Geräteantwort:", Response.decode())
    ser.close()

    Beispiel 2: C# steuert das COM-Port-Gerät

    SerialPort-Port = neuer SerialPort("COM4", 9600);
    port.Open();
    port.WriteLine("MOVE 100");
    String-Antwort = port.ReadLine();
    Console.WriteLine("Response: " + Antwort);
    port.Close();

    Beispiel 3: USB-HID-Gerät steuern

    Beispiel 4: Peripheriegeräte zur TCP-Kommunikationssteuerung

    Socket importieren
    
    s = socket.socket()
    s.connect(('192.168.1.100', 5000))
    s.sendall(b'START\n')
    data = s.recv(1024)
    print("Antwort:", data.decode())
    s.close()

    Anwendungsfälle

    Dinge zu beachten

    abschließend

    Die Entwicklung von Peripheriesteuerungsprogrammen erfordert die Auswahl der geeigneten Sprache und Funktionsbibliothek basierend auf der Schnittstelle und dem Protokoll des Geräts sowie die Kombination von seriellen, USB-, Netzwerk- und anderen Kommunikationsmethoden, die in verschiedenen Bereichen der Automatisierung und industriellen Steuerung weit verbreitet sind.



    Entwicklung eines Barcode-Reader-Programms

    Gemeinsame Plattformunterstützung

    Gängige Barcodetypen

    Gängige Entwicklungskits und Tools

    Beispiel für eine Android-Entwicklung (mit ZXing)

    // build.gradle
    Implementierung 'com.journeyapps:zxing-android-embedded:4.3.0'
    
    //Java-Aufruf-Scan-Bildschirm
    IntentIntegrator integrator = new IntentIntegrator(this);
    integrator.setPrompt("Bitte scannen Sie den Barcode");
    integrator.setBeepEnabled(true);
    integrator.setOrientationLocked(false);
    integrator.initiateScan();
    //onActivityResult empfängt das Ergebnis
    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        IntentResult result = IntentIntegrator.parseActivityResult(requestCode, resultCode, data);
        if(result != null) {
            if(result.getContents() != null) {
                String barcode = result.getContents();
                Log.d("Barcode-Inhalt", Barcode);
            }
        }
    }

    Beispiele für Webentwicklung (mit QuaggaJS)

    <script src="https://unpkg.com/[email protected]/dist/quagga.min.js"></script>
    
    <script>
    Quagga.init({
        inputStream: {
            Name: „Live“,
            Typ: „LiveStream“,
            Ziel: document.querySelector('#scanner')
        },
        Decoder: {
            Leser: ["code_128_reader", "ean_reader", "upc_reader"]
        }
    }, function(err) {
        if (!err) {
            Quagga.start();
        }
    });
    
    Quagga.onDetected(function(result) {
        console.log("Barcode-Inhalt: ", result.codeResult.code);
    });
    </script>

    Plattform- und Suite-Vergleich

    PlattformEmpfohlenes SetIst es kostenlos?
    AndroidZXing / ML KitJa
    WebQuaggaJS / jsQRJa
    WindowsDynamsoft / ZXing.NETDynamsoft für kommerzielle Nutzung
    PythonZBar / pyzbarJa

    abschließend

    Um Barcode Reader zu entwickeln, können Sie je nach Plattform das entsprechende Open-Source-Paket auswählen. ZXing ist die am weitesten verbreitete Option. QuaggaJS ist für das Web verfügbar. Wenn Sie Unterstützung auf kommerzieller Ebene benötigen, können Sie das Dynamsoft Barcode SDK in Betracht ziehen.



    Barcode mit Steuerzeichen

    Grundprinzipien

    Barcode-Lesegeräte sind im Wesentlichen Geräte, die Tastatureingaben simulieren. Wenn ein Barcode gescannt wird, „gibt“ er den Inhalt des Barcodes in einen Zeichenstrom aus, genau wie eine Tastatureingabe.

    Daher der BarcodeKann Steuercode (Control Code) enthalten,AberErfordert Barcode-Lesegerät und Barcode-FormatunterstützungEinfach gut.

    Gängige Steuercodetypen in Barcodes

    Bedingung 1: Das Barcodeformat muss Steuercodes unterstützen

    Das folgende Format kann beispielsweise Steuercodes kodieren:

    Bedingung 2: Das Barcode-Kodierungstool muss das Einbetten von Steuercodes unterstützen

    Einige Barcode-Generatoren ermöglichen die Einbettung von Sonderzeichen, wie zum Beispiel:

    Bedingung 3: Der Barcodescanner muss Ausgabesteuercodes unterstützen

    Die meisten professionellen Barcodedrucker (z. B. Zebra, Honeywell) sind werkseitig voreingestelltSteuercodeausgabe deaktivieren, muss über die vom Scanner bereitgestellten „Einstellungen Barcode“ aktiviert werden:

    Bedingung 4: Das Betriebssystem und die Anwendung müssen es korrekt empfangen

    Zum Beispiel in einer Windows-Anwendung:

    Beispiel: Codieren von Strg-C-Barcode-Inhalten

    Codierung von ASCII 3 mit Code128:

    Eingabe:\x03Hallo Welt

    Nachdem der Barcode gescannt wurde, wird Strg+C ausgelöst und „Hello World“ ausgegeben.

    abschließend



    Android-Entwicklung

    Android-Entwicklungsplattform

    Einführung in die Plattform

    Android ist ein von Google entwickeltes Open-Source-Betriebssystem für Mobilgeräte, das häufig in Smartphones, Tablets und anderen intelligenten Geräten verwendet wird. Entwickler können die umfangreiche API und die Tools nutzen, um eine Vielzahl von Anwendungen zu erstellen.

    Entwicklungstools

  • Android Studio: Eine offiziell von Google bereitgestellte integrierte Entwicklungsumgebung (IDE), die Codebearbeitung, Simulatortests und Debugging-Funktionen unterstützt.
  • Kotlin und Java: Die wichtigsten Programmiersprachen für die Android-Entwicklung, unter denen Kotlin die offiziell empfohlene Sprache ist.
  • Android SDK: Bietet Emulatoren, API-Bibliotheken und Toolsets zur Unterstützung der Anwendungsentwicklung und des Testens.
  • Gradle: Tool zur Verwaltung von Abhängigkeiten und Gebäudeautomation.

    Anwendungslebenszyklus

  • Start (onCreate): Die Anwendung startet und initialisiert Ressourcen.
  • Ausführen (onStart): Der Bildschirm wird dem Benutzer angezeigt.
  • Aktivität (onResume): Die Anwendung wechselt in einen interaktiven Zustand.
  • Pause (onPause): Die Anwendung ist teilweise ausgeblendet oder verliert den Fokus.
  • Stopp (onStop): vollständig verborgen und kann vom System recycelt werden.
  • Zerstören (onDestroy): Die Anwendung wird geschlossen und alle Ressourcen werden freigegeben.

    Vorteile

  • Offenheit: Unterstützt individuelle Anpassung und umfassende Gerätekompatibilität.
  • Marktgröße: Google Play bietet globale Möglichkeiten zur App-Veröffentlichung.
  • Leistungsstarke Tools: Umfangreiche Entwicklungstools und Dateiressourcen tragen zur Verbesserung der Entwicklungseffizienz bei.

    Lernressourcen

  • Offizielle Dokumentation: Android Developers bietet detaillierte Dokumentation und Beispiele.
  • Entwickler-Community: Plattformen wie Stack Overflow und Reddit bieten technischen Support.
  • Online-Kurse: Sie können verwandte Kurse von Udemy, Coursera oder YouTube auswählen.

    Abschluss

    Die Android-Entwicklungsplattform hat aufgrund ihrer Flexibilität und leistungsstarken Funktionen viele Entwickler angezogen und ist damit eine der ersten Wahlen für die Entwicklung mobiler Anwendungen.

    Chromebook mit Android Studio

    Installationsschritte

    1. einschaltenEinstellungen → Entwickler → Linux-Entwicklungsumgebung (Crostini), weisen Sie mindestens 20 GB Speicherplatz und 8 GB Arbeitsspeicher zu.
    2. Update-Kit:
      sudo apt update && sudo apt upgrade -y
      sudo apt install -y wget curl unzip zip git ca-certificates
    3. JDK installieren (Version 17 empfohlen):
      sudo apt install -y openjdk-17-jdk
    4. Laden Sie Android Studio herunter und installieren Sie es:
      sudo dpkg -i ~/Downloads/android-studio-*.deb || sudo apt -f install -y
      android-studio
      oder dekomprimieren.tar.gz
      tar -xzf ~/Downloads/android-studio-*.tar.gz -C ~
      ~/android-studio/bin/studio.sh
    5. Folgen Sie dem Installationsassistenten, um die SDK- und Tool-Einstellungen abzuschließen.

    Testen Sie mit einem physischen Gerät

    1. Auf ChromeOS:Einstellungen → Entwickler → Linux → USB-Gerät, aktivieren Sie das Kontrollkästchen, um das Telefon mit Linux zu teilen.
    2. Schalten Sie das Telefon einEntwickleroptionen → USB-Debugging, was RSA-Fingerprinting ermöglicht, wenn eine Verbindung besteht.
    3. Gerät zur Bestätigung der Linux-Umgebung:
      sudo apt install -y android-sdk-platform-tools
      adb kill-server
      adb start-server
      adb devices

    Empfehlungen zu Leistung und Emulator

    Alternativen



    Chromebook verwendet VS Code + Android SDK

    Installieren Sie VS-Code

    1. Schalten Sie ChromeOS einEinstellungen → Entwickler → Linux-Entwicklungsumgebung (Crostini)
    2. Laden Sie die VS Code Linux-Version (.deb-Datei) herunter und installieren Sie sie im Linux-Container:
      sudo dpkg -i ~/Downloads/code_*.deb || sudo apt -f install -y
    3. Starten Sie VS Code und installieren Sie häufig verwendete Erweiterungen (z. BKotlinFlutterJava Extension Pack)。

    Installieren Sie das Android SDK und die Tools

    1. Installieren Sie die erforderlichen Pakete:
      sudo apt update && sudo apt install -y openjdk-17-jdk unzip git
    2. Laden Sie die Android SDK-Befehlszeilentools herunter:
      wget https://dl.google.com/android/repository/commandlinetools-linux-11076708_latest.zip
      unzip commandlinetools-linux-*_latest.zip -d ~/android-sdk
    3. Umgebungsvariablen festlegen (können hinzugefügt werden).~/.bashrcoder~/.zshrc):
      export ANDROID_SDK_ROOT=$HOME/android-sdk
      export PATH=$ANDROID_SDK_ROOT/cmdline-tools/bin:$ANDROID_SDK_ROOT/platform-tools:$PATH
    4. Verwenden Sie sdkmanager, um Plattformtools und erforderliche Pakete zu installieren:
      sdkmanager "platform-tools" "platforms;android-34" "build-tools;34.0.0"

    Stellen Sie eine Verbindung zum physischen Mobiltelefontest her

    1. Auf ChromeOS:Einstellungen → Entwickler → Linux → USB-Gerät, überprüfen Sie die Telefonfreigabe.
    2. Schalten Sie das Telefon einEntwickleroptionen → USB-Debugging
    3. Linux-Container-Bestätigungsgerät:
      adb devices
      SehendeviceDer Test kann nun bereitgestellt werden.

    Entwickeln Sie in VS-Code

    Passend zur Situation



    Beispiel für eine Android-App

    Neues Projekt erstellen

    Erstellen Sie ein neues Projekt in Android Studio, wählen Sie die Vorlage „Leere Aktivität“ aus und legen Sie den Projektnamen und andere grundlegende Informationen fest.

    Schreibschnittstelle (activity_main.xml)

    existierenres/layout/activity_main.xmlEine einfache, in der Datei gestaltete Benutzeroberfläche, die beispielsweise eine Schaltfläche und einen Textanzeigebereich enthält:

    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
                android:layout_width="match_parent"
                android:layout_height="match_parent"
                android:orientation="vertikal"
                android:gravity="center">
            
                <Schaltfläche
                    android:id="@+id/button"
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:text="Klick mich" />
            
                <TextView
                    android:id="@+id/textView"
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:text="Hallo Welt!"
                    android:layout_marginTop="20dp" />
            
            </LinearLayout>

    Programmlogik schreiben (MainActivity.java)

    existierenMainActivity.javaLegen Sie das Klickereignis der Schaltfläche fest, um den Inhalt des Textanzeigebereichs zu ändern:

    Paket com.example.simpleapp;
    
            android.os.Bundle importieren;
            import android.view.View;
            import android.widget.Button;
            import android.widget.TextView;
            import androidx.appcompat.app.AppCompatActivity;
    
            Die öffentliche Klasse MainActivity erweitert AppCompatActivity {
                @Override
                protected void onCreate(Bundle savingInstanceState) {
                    super.onCreate(savedInstanceState);
                    setContentView(R.layout.activity_main);
    
                    Button button = findViewById(R.id.button);
                    TextView textView = findViewById(R.id.textView);
    
                    button.setOnClickListener(new View.OnClickListener() {
                        @Override
                        public void onClick(View v) {
                            textView.setText("Sie haben auf die Schaltfläche geklickt!");
                        }
                    });
                }
            }

    Anwendung ausführen

    Klicken Sie in Android Studio auf die Schaltfläche „Ausführen“, um Ihre App auf dem Emulator oder einem angeschlossenen physischen Gerät zu testen. Nach dem Klicken auf die Schaltfläche ändert sich der Text in „Sie haben auf die Schaltfläche geklickt!“.



    Android ruft den aktuellen GPS-Standort ab

    Berechtigungseinstellungen

    existierenAndroidManifest.xmlFügen Sie die folgenden Berechtigungen hinzu:

    <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
    <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />

    Berechtigungen prüfen und anfordern (Android 6.0 und höher)

    if (ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION)
        != PackageManager.PERMISSION_GRANTED) {
        ActivityCompat.requestPermissions(this,
            new String[]{Manifest.permission.ACCESS_FINE_LOCATION}, 1);
    }

    Holen Sie sich LocationManager

    LocationManager locationManager = (LocationManager) getSystemService(Context.LOCATION_SERVICE);

    Aktuellen Standort abrufen

    LocationListener locationListener = new LocationListener() {
        @Override
        public void onLocationChanged(@NonNull Location location) {
            double width = location.getLatitude();
            double longitude = location.getLongitude();
            Log.d("GPS", "Breitengrad: " + Breitengrad + ", Längengrad: " + Längengrad);
        }
    };
    
    if (ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION)
        == PackageManager.PERMISSION_GRANTED) {
        locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER,
            1000, // Millisekundenintervall
            1, // Mindestabstand (Meter)
            locationListener);
    }

    Verwenden Sie FusedLocationProviderClient (empfohlen)

    FusedLocationProviderClient fusedLocationClient = LocationServices.getFusedLocationProviderClient(this);
    
    if (ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION)
        == PackageManager.PERMISSION_GRANTED) {
        fusedLocationClient.getLastLocation()
            .addOnSuccessListener(this, location -> {
                if (location != null) {
                    double lat = location.getLatitude();
                    double lng = location.getLongitude();
                    Log.d("GPS", "Lat: " + lat + ", Lng: " + lng);
                }
            });
    }


    Sound Control Android-App

    Grundlegende Konzepte

    Um eine Sprachassistentenfunktion wie Siri oder Hey Google zu implementieren, müssen Sie die folgenden Komponenten kombinieren:

    Fügen Sie die erforderlichen Berechtigungen hinzu

    <uses-permission android:name="android.permission.RECORD_AUDIO"/>
    <uses-permission android:name="android.permission.INTERNET"/>

    Initialisierung der Spracherkennung

    SpeechRecognizercognizer = SpeechRecognizer.createSpeechRecognizer(this);
    Absicht intent = new Intent(RecognizerIntent.ACTION_RECOGNIZE_SPEECH);
    intent.putExtra(RecognizerIntent.EXTRA_LANGUAGE_MODEL,
                    RecognizerIntent.LANGUAGE_MODEL_FREE_FORM);
    intent.putExtra(RecognizerIntent.EXTRA_LANGUAGE, Locale.getDefault());
    
    cognizer.setRecognitionListener(new RecognitionListener() {
        @Override
        public void onResults(Bundle results) {
            ArrayList<String> match = results.getStringArrayList(SpeechRecognizer.RESULTS_RECOGNITION);
            if (matches != null && !matches.isEmpty()) {
                String command = matches.get(0).toLowerCase();
                if (command.contains("Kamera öffnen")) {
                    // Operationen ausführen
                }
            }
        }
        //Andere notwendige Überschreibmethoden werden weggelassen
    });
    
    Recognizer.startListening(intent);

    Sprachsynthese (Antwort an den Benutzer)

    TextToSpeech tts = new TextToSpeech(this, status -> {
        if (status == TextToSpeech.SUCCESS) {
            tts.setLanguage(Locale.TAIWAN);
            tts.speak("Hallo, ich bin hier.", TextToSpeech.QUEUE_FLUSH, null, null);
        }
    });

    Permanente Hintergrundüberwachung (optional)

    Wenn Sie den Hintergrund beibehalten und per Stimme aktivieren möchten, müssen Sie Folgendes verwenden:

    Dinge zu beachten



    Permanente Hintergrundüberwachung

    Zweck

    Das Ziel der permanenten Hintergrundüberwachung besteht darin, dass die App Sprachweckwörter (z. B. „Hey Assistant“) erkennt und entsprechende Funktionen aktiviert, auch wenn der Bildschirm nicht geöffnet ist.

    Herausforderung

    Lösungsarchitektur

    1. verwendenInteressentendienste(Foreground Service) bleibt betriebsbereit.
    2. Sprachweckung übernimmtPorcupineWarten Sie, bis die Hotword Engine offline ist.
    3. Nachdem Sie erfolgreich aufgewacht sind, beginnen SieSpeechRecognizerErkennen Sie vollständige Sprachbefehle.

    Schritt 1: Einrichtung eines potenziellen Dienstes

    Öffentliche Klasse VoiceService erweitert Service {
        @Override
        public int onStartCommand(Intent intent, int flags, int startId) {
            Benachrichtigungsbenachrichtigung = neuer NotificationCompat.Builder(this, „voice_channel“)
                .setContentTitle("Sprachassistent ist in Betrieb")
                .setSmallIcon(R.drawable.ic_mic)
                .build();
            startForeground(1, Benachrichtigung);
    
            //Hotword-Erkennung initialisieren
            startHotwordDetection();
            return START_STICKY;
        }
    
        @Override
        public IBinder onBind(Intent intent) {
            null zurückgeben;
        }
    }

    Schritt 2: Benachrichtigungskanal erstellen (Android 8+)

    NotificationChannel channel = new NotificationChannel("voice_channel",
        "Voice Assistant", NotificationManager.IMPORTANCE_LOW);
    NotificationManager manager = getSystemService(NotificationManager.class);
    manager.createNotificationChannel(channel);

    Schritt 3: Verwenden Sie Porcupine zur Stimmaktivierung

    Porcupine bietet ein Android SDK, das benutzerdefinierte Schlüsselwörter erkennt und vollständig offline funktioniert.

    PorcupineManager porcupineManager = new PorcupineManager.Builder()
        .setAccessKey("Ihr Schlüssel")
        .setKeywordPath("hey_assistant.ppn")
        .setSensitivity(0.7f)
        .build((keywordIndex) -> {
            //Rufen Sie SpeechRecognizer zur Spracherkennung auf, wenn Sie aufgewacht sind
            startSpeechRecognition();
        });
    
    porcupineManager.start();

    Schritt 4: Starten Sie den Dienst

    Intent serviceIntent = new Intent(this, VoiceService.class);
    ContextCompat.startForegroundService(this, serviceIntent);

    Dinge zu beachten



    Optimierung von Hey Google Voice Assistant

    Benutzerseitige Optimierungsvorschläge

    Entwicklerseitige Optimierungsmethoden

    Optimierung der Auslösebedingungen für die Sprachaktivierung

    Beachten Sie die Einschränkungen



    Entwicklung von Apple-Produktprogrammen

    Entwicklungstools

    Einstellungen der Entwicklungsumgebung

    1. Laden Sie die neueste Version herunter und installieren Sie sieXcode

    2. Öffnen Sie Xcode und gehen Sie zuPreferences > AccountsMelden Sie sich mit Ihrer Apple-ID an, um Entwicklerfunktionen zu aktivieren.

    3. Installation über XcodeCommand Line Toolsum Swift-Befehlszeilentools zu verwenden.

    Entwicklungsplattform

    Projekt erstellen

    1. Öffnen Sie Xcode und wählen Sie „Neues Xcode-Projekt erstellen“.

    2. Wählen Sie eine passende Bewerbungsvorlage aus, z.B.App (iOS/macOS)。

    3. Legen Sie den Projektnamen, die Bundle-ID und die Sprache (Swift oder Objective-C) fest.

    4. Wählen Sie ein UI-Framework (SwiftUI oder UIKit).

    Simulation und Test

    Anwendungsveröffentlichung

    1. RegistrierenApple Developer Program(Jahresgebühr 99 USD erforderlich).

    2. Über Xcode einstellenApp Store Connectund reichen Sie die App ein.

    3. Folgen Sie ApplesApp Store Review GuidelinesStellen Sie sicher, dass Ihre App den Auflistungsspezifikationen entspricht.



    iOS-Entwicklung

    Entwicklungstools

    Die iOS-Entwicklung verwendet hauptsächlichXcode, die offizielle integrierte Entwicklungsumgebung (IDE) von Apple.

    Entwicklungsprozess

    1. Entwerfen Sie Anwendungsarchitektur und -schnittstelle
    2. Schreiben Sie Code, um Funktionen zu implementieren
    3. Testen Sie mit einem Simulator oder einer realen Maschine
    4. Führen Sie eine Fehlerbehebung und Leistungsoptimierung durch
    5. Über den App Store einreichen und veröffentlichen

    Grundlegendes Wissen

    Das Erlernen der iOS-Entwicklung erfordert die Beherrschung der folgenden Grundlagen:

    Ressourcen entwickeln

    Hier sind einige hilfreiche Lern- und Entwicklungsressourcen:



    Xcode

    Merkmale

    Xcode ist eine von Apple bereitgestellte integrierte Entwicklungsumgebung (IDE) für die Entwicklung von macOS-, iOS-, watchOS- und tvOS-Anwendungen.

    Hauptkomponenten

    1. Code Editor:Bietet Syntaxhervorhebung, Codevervollständigung und Fehlermeldungen
    2. Interface Builder:Unterstützt eine intuitive Drag-and-Drop-Designoberfläche
    3. Simulator:Wird zum Testen und Simulieren von Anwendungen verwendet, die auf verschiedenen Geräten ausgeführt werden
    4. Debugging-Tools:Unterstützt Haltepunkte, Speichererkennung und Leistungsanalyse

    Installation und Updates

    Sie können die neueste Version von Xcode aus dem Mac App Store oder der offiziellen Entwickler-Website von Apple herunterladen.

    Tipps

    Praktische Tipps zur Verbesserung der Entwicklungseffizienz:

    Ressource

    Verwandte Lern- und Referenzressourcen:



    Swift

    Sprachmerkmale

    Swift ist Apples moderne Programmiersprache für die Entwicklung von iOS-, macOS-, watchOS- und tvOS-Apps.

    Grammatikgrundlagen

    Kernkonzepte

    1. Verwenden Sie Protocol, um Schnittstellen und Protokolle zu implementieren
    2. Erweitern Sie die Kategoriefunktionalität mithilfe der Erweiterung
    3. Die Unterstützung von Generics verbessert die Wiederverwendbarkeit von Code
    4. Verwenden Sie Abschlüsse, um Funktionen höherer Ordnung zu implementieren
    5. Unterstützt benutzerdefinierte Operatoren und Tupel

    Anwendungsszenarien

    Swift ist nicht nur für das Apple-Ökosystem gedacht, es kann auch für serverseitige Entwicklung und plattformübergreifende Tools verwendet werden.

    Ressource

    Verwandte Lern- und Referenzressourcen:



    Objective-C

    Merkmale

    Objective-C ist eine C-basierte objektorientierte Programmiersprache, die ursprünglich von der NeXT Corporation entwickelt und später von Apple häufig für die Entwicklung von macOS- und iOS-Anwendungen verwendet wird.

    grammatikalische Struktur

    Die Syntax von Objective-C kombiniert die Funktionen von C und Smalltalk und verwendet das @-Symbol, um Spracherweiterungen anzuzeigen.

    Kernkonzepte

    1. Objektorientierte Programmierung, einschließlich Klassen und Vererbung
    2. Protokolle werden zum Definieren von Methodensammlungen verwendet
    3. Kategorien werden verwendet, um die Kategoriefunktionalität zu erweitern
    4. Blocksyntax für Schließungen und Rückrufe

    Entwicklungstools

    Die Objective-C-Entwicklung erfolgt hauptsächlich mit Apples Xcode.

    Ressource

    Hier sind einige Ressourcen zum Lernen und Nachschlagen:



    GNews

    Was ist GNews?

    GNews ist eine von Google entwickelte Plattform zur Nachrichtenaggregation, die Nutzer dabei unterstützen soll, die neuesten globalen Nachrichten zu erhalten. Es integriert Inhalte aus verschiedenen Nachrichtenquellen und nutzt die Technologie der künstlichen Intelligenz, um Empfehlungen für Nachrichten zu personalisieren, die für Benutzer von Interesse sind.

    Hauptfunktionen von GNews

    Wie verwende ich GNews?

    Benutzer können diese Plattform nutzen, indem sie die Website von GNews besuchen oder die App herunterladen. Auf der Plattform können Benutzer interessante Themen auswählen, bestimmten Nachrichtenquellen folgen und Newsfeeds an ihre Bedürfnisse anpassen.

    Vorteile von GNews

    abschließend

    GNews ist ein leistungsstarkes Nachrichtenaggregationstool, das mithilfe künstlicher Intelligenz den Benutzern ein personalisiertes Nachrichtenerlebnis bietet. Da sich Nachrichteninformationen schnell ändern, hilft GNews den Benutzern, schnell über weltweite Trends auf dem Laufenden zu bleiben und die Informationen zu erhalten, die sie benötigen.



    Automatisierte Prozesstools

    Werkzeugname Hauptmerkmale Anwendbare Szenarien Preis
    n8n Ein automatisiertes Open-Source-Workflow-Tool, das ein hochgradig anpassbares Prozessdesign bietet und selbst erstellte Knoten unterstützt. Geeignet für interne Prozessautomatisierung, große Automatisierungssysteme, API-Integration usw. Kostenlos und Open Source, kostenpflichtige Cloud-Version verfügbar.
    Make Bietet visuelle Workflow-Konstruktion, unterstützt die Integration mehrerer Anwendungen und Dienste von Drittanbietern und legt Wert auf Einfachheit und Benutzerfreundlichkeit. Geeignet für die Workflow-Automatisierung kleiner und mittlerer Unternehmen und die schnelle Integration verschiedener Dienste. Es ist ein kostenloser Plan verfügbar und ein kostenpflichtiger Plan bietet erweiterte Funktionen, die auf die Bedürfnisse der Benutzer abgestimmt sind.
    Zapier Unterstützt die Integration mit den meisten Anwendungen, ist einfach und benutzerfreundlich und kann Auslöser und automatisierte Arbeitsabläufe erstellen. Geeignet für die Automatisierung in verschiedenen Geschäftsbereichen, insbesondere in kleinen Unternehmen und Startups. Es ist ein kostenloser Plan verfügbar, und ein kostenpflichtiger Plan bietet mehr Funktionen und läuft je nach Benutzerbedarf.


    KI-Entwicklungsprogramm

    Bolt

    Bolt ist ein schnelles, leichtes KI-Entwicklungsframework, das sich darauf konzentriert, Entwicklern einfache und effiziente Tools zum Erstellen von Anwendungen bereitzustellen. Zu den Funktionen gehören:

    Cursor

    Cursor ist ein Editor-Tool, das speziell für die KI-Programmentwicklung entwickelt wurde und intelligente Hilfsfunktionen zum Schreiben von Code und zum Debuggen bietet. Zu den Funktionen gehören:

    v0

    v0 ist eine auf visueller Entwicklung basierende KI-Plattform, die es Benutzern ermöglicht, Modelle und Anwendungen über eine Drag-and-Drop-Schnittstelle zu erstellen. Zu den Funktionen gehören:

    Codeium

    Codeium ist ein Programmeditor in Kombination mit intelligenter KI-Unterstützung, der sich auf die Verbesserung der Effizienz und Genauigkeit der Programmentwicklung konzentriert. Zu den Funktionen gehören:



    Software-Engineering

    Definition

    Software Engineering ist eine Ingenieursdisziplin, die Software systematisch und geplant entwickelt, betreibt und wartet. Ziel ist der Aufbau qualitativ hochwertiger, wartbarer, zuverlässiger und anspruchsvoller Softwaresysteme.

    Kernziele

    Softwareentwicklungslebenszyklus (SDLC)

    1. Bedarfsanalyse:Sammeln und analysieren Sie Benutzeranforderungen und erstellen Sie Anforderungsspezifikationen
    2. Systemdesign:Entwerfen Sie Systemarchitekturen, Module, Datenbanken und Schnittstellen
    3. Durchführung:Schreiben Sie Code basierend auf dem Design
    4. prüfen:Führen Sie Unit-Tests, Integrationstests, Systemtests und Abnahmetests durch
    5. Bereitstellung und Start:Stellen Sie das System in der Produktionsumgebung bereit
    6. Wartung und Updates:Beheben Sie Fehler, aktualisieren Sie Funktionen und optimieren Sie die Leistung

    Gemeinsame Entwicklungsmethoden

    Gängige Werkzeuge und Techniken

    Qualitätsmerkmale

    Rollenverteilung



    Agile Entwicklung

    Kernwert

    Hauptprinzipien

    1. Erfüllen Sie Kundenbedürfnisse mit höchster Priorität und schaffen Sie Mehrwert durch frühzeitige und konsistente Lieferung.
    2. Begrüßen Sie veränderte Anforderungen und nutzen Sie diese, um auch in späten Entwicklungsstadien Wettbewerbsvorteile für Kunden zu schaffen.
    3. Regelmäßige Lieferung funktionsfähiger Software, oft mit Vorlaufzeiten von Wochen oder Monaten.
    4. Entwicklungs- und Geschäftsteams sollten jeden Tag zusammenarbeiten, um Kommunikation und Verständnis zu fördern.
    5. Konzentrieren Sie sich auf motivierte Personen, bieten Sie Unterstützung und vertrauen Sie ihnen, dass sie ihre Arbeit erledigen.
    6. Persönliche Kommunikation ist die effektivste Art der Kommunikation.
    7. Das wichtigste Maß für den Fortschritt ist funktionierende Software.
    8. Fördern Sie ein nachhaltiges Entwicklungstempo, und alle Teilnehmer sollten in der Lage sein, ein stabiles Tempo aufrechtzuerhalten.
    9. Streben Sie nach technischer Exzellenz und einfacher Gestaltung und verbessern Sie Flexibilität und Qualität.
    10. Halten Sie es einfach und konzentrieren Sie sich darauf, die notwendige Arbeit zu erledigen.
    11. Selbstorganisierende Teams produzieren optimale Designs und Architekturen.
    12. Reflektieren Sie regelmäßig und passen Sie Ihr Verhalten an, um die Wirksamkeit zu verbessern.

    Häufig verwendete Frameworks

    Anwendbare Szenarien



    Dokumentvorlage für Softwareentwicklungsanforderungen

    Projektname

    Bitte geben Sie den offiziellen Namen dieses Projekts ein.

    Versionsdatensatz

    Projekthintergrund und Ziele

    Erläutern Sie den Grund für dieses Projekt, Hintergrundthemen und zu lösende Kernthemen und definieren Sie klare Projektziele.

    Systemübersicht

    Skizzieren Sie die Systemfunktionen und die Gesamtarchitektur, die mit dem Systemarchitekturdiagramm gepaart werden können.

    Funktionale Anforderungen

    nichtfunktionale Anforderungen

    Benutzerrollen und Berechtigungen

    Bildschirm- und Schnittstellenanforderungen

    Sie können Hauptbildschirmskizzen oder Wireframes anhängen, um die Elemente und interaktiven Prozesse jedes Bildschirms zu beschreiben.

    Datenanforderungen

    Listen Sie die Hauptstruktur, Felder, Korrelationen usw. der Datentabelle auf.

    Integration und Interdependenz

    Listen Sie externe Systeme, APIs oder andere Softwarekomponenten auf, die integriert werden müssen.

    Zeitleiste und Meilensteine

    Risiken und Einschränkungen

    Listen Sie potenzielle Risiken und Einschränkungen auf (z. B. Budget, Arbeitskräfte, Technologie usw.).

    Anhang

    Links zu verwandten Dokumenten, Referenzmaterialien, Begriffsdefinitionen usw.



    Designmuster

    Definition

    Design Patterns sind eine Reihe bewährter Software-Designlösungen, die hauptsächlich in der objektorientierten Programmierung verwendet werden, um wiederkehrende Designprobleme in bestimmten Situationen zu lösen.

    Drei Hauptkategorien

    Gemeinsame Einrichtungsmuster

    Gemeinsame Strukturmuster

    Gemeinsame Verhaltensmuster

    Vorteile von Designmustern

    Nutzungsvorschläge



    Versionskontrolle

    Definition

    Versionskontrolle ist ein System, das den Dateiänderungsverlauf verwaltet. Es wird häufig in der Softwareentwicklung eingesetzt und ermöglicht die gleichzeitige Zusammenarbeit mehrerer Entwickler und die vollständige Aufzeichnung jeder Änderung.

    Hauptfunktionen

    Typ des Versionskontrollsystems

    Gängige Werkzeuge

    Grundlegende Git-Anweisungen

    Verzweigungsstrategie

    Nutzen



    Git

    Einführung

    Git ist ein dezentrales Versionskontrollsystem, das 2005 von Linus Torvalds (dem Vater von Linux) zur Verfolgung von Codeänderungen, kollaborativer Entwicklung und Versionsverwaltung entwickelt wurde. Es ist heute das am weitesten verbreitete Tool zur Versionskontrolle und wird in der persönlichen Entwicklung, in Teamprojekten und in Open-Source-Communitys eingesetzt.

    Kernkonzepte

    Installieren Sie Git

    1. Gehe zuOffizielle Git-WebsiteLaden Sie die entsprechende Version herunter.
    2. Öffnen Sie nach der Installation die Eingabeaufforderung (CMD) oder PowerShell.
    3. eingebengit --versionum zu bestätigen, dass die Installation erfolgreich war.

    Grundeinstellungen

    Wenn Sie Git zum ersten Mal verwenden, müssen Sie Entwicklerinformationen festlegen:

    git config --global user.name „Ihr Name“
    git config --global user.email „Ihre [email protected]

    grundlegende Anweisungen

    git init # Lokales Repository initialisieren
    Git-Klon-URL # Kopieren Sie das Remote-Repository
    git add . # Änderungen zum Staging-Bereich hinzufügen
    git commit -m "description" # Erstelle einen Commit
    git status # Aktuellen Status anzeigen
    git log # Commit-Datensätze anzeigen
    git branch # Zweigliste anzeigen
    Git-Checkout-Zweigname # Zweige wechseln
    git merge branch name # Den angegebenen Zweig zusammenführen
    git push # Push-Änderungen an das entfernte Ende
    git pull # Aktualisierungen vom entfernten Ende abrufen

    Gemeinsamer Arbeitsablauf

    1. Erstellen oder kopieren Sie ein Repository (git initodergit clone
    2. Dateien bearbeiten oder hinzufügen
    3. Fügen Sie die Änderungen zum Staging-Bereich hinzu (git add
    4. Änderungen übernehmen (git commit
    5. Mit der Gegenstelle synchronisieren (git push / git pull

    Integrieren Sie mit Visual Studio

    Vorteil

    Gemeinsame Remote-Dienste



    Git-Reset-Synchronisierungs-Remote

    Kernbefehl: Git Reset

    Wenn Sie alle lokalen Änderungen, die nicht festgeschrieben (Uncommitted) und festgeschrieben, aber noch nicht gepusht (Local Commits) wurden, vollständig verwerfen und den Zweig so zurücksetzen möchten, dass er vollständig mit dem Remote-Ende übereinstimmt, führen Sie bitte die folgenden Schritte aus.

    1. Holen Sie sich den aktuellen Status der Gegenstelle

    Stellen Sie zunächst sicher, dass Ihr lokaler Index mit dem neuesten Fortschritt auf der Remote-Seite aktualisiert wird:

    git fetch --all

    2. Erzwingen Sie das Zurücksetzen auf den Remote-Zweig

    verwenden--hardDer Parameter verweist den aktuellen Zweig auf den entsprechenden Remote-Zweig (vorausgesetzt, Ihr Zweig ist der Hauptzweig):

    git reset --hard origin/main

    Nicht verfolgte Dateien verarbeiten (Untracked Files)

    git reset --hardEs werden nur Dateien verarbeitet, die bereits von Git verfolgt wurden. Wenn Sie Dateien oder Ordner lokal neu erstellt, diese aber noch nicht mit Git hinzugefügt haben, bleiben sie erhalten. Um sie alle zu löschen, verwenden SiecleanAnweisung:

    Löschen Sie nicht verfolgte Dateien

    # Führen Sie zunächst den Test aus, um zu sehen, welche Dateien gelöscht werden
    git clean -n
    
    # Dateien (-f) und Verzeichnisse (-d) offiziell löschen
    git clean -fd

    Vergleichstabelle für häufige Szenarien

    Ziel Geltende Richtlinien
    Verwerfen Sie alle lokalen Änderungen git reset --hard origin/<branch_name>
    Verwerfen Sie nur einzelne Dateiänderungen git checkout HEAD -- <file_path>
    Aktuelle Änderungen vorübergehend speichern (kann später wiederhergestellt werden) git stash
    Entfernen Sie sämtliche Unordnung außerhalb von Gitignore git clean -fdx

    Dinge zu beachten



    Vergleich von Git-Konfliktdateien

    Wenn ein Git-Merge-Zweig in Konflikt gerät, wird die Datei als „Nicht zusammengeführt“ markiert. Zu diesem Zeitpunkt fügt Git eine Konfliktmarkierung in die Datei ein und wir müssen Vergleichsbefehle verwenden, um das Problem zu lokalisieren und manuell zu beheben.


    1. Suchen Sie die Liste der in Konflikt stehenden Dateien

    Bevor Sie den Konflikt lösen, ermitteln Sie zunächst, welche Dateien im Konflikt stehen:

    git status

    In Konflikt stehende Dateien werden in aufgelistetUnmerged pathsunter Abschnitt.


    2. Vergleichen Sie widersprüchliche Inhalte

    Wenn die Datei widersprüchliche Tags enthält, können Sie die Unterschiede mit den folgenden Methoden anzeigen:


    3. Interpretieren Sie Konfliktmarker

    Git ändert die Konfliktdatei direkt. Das Format ist wie folgt:

    <<<<<<< HEAD (oder Ihr Filialname)
    Dies ist der Inhalt Ihres aktuellen Zweigs (unserer)
    =======
    Dies ist der Inhalt des Zweigs der anderen Partei (deren)
    >>>>>>> Filialname

    4. Verwenden Sie grafische Tools zum Vergleich (empfohlen)

    Bei komplexen Konflikten ist die Textoberfläche schwer lesbar. Es wird empfohlen, ein spezielles Merge-Tool aufzurufen:

    git mergetool

    Das wird so etwas wie startenMeld, P4Merge oder VS CodeVergleichen Sie mit anderen Tools drei Versionen nebeneinander: Basisversion (Base), lokale Version (Local) und Remote-Version (Remote).


    5. Maßnahmen nach der Lösung

    Nachdem Sie die Dateien manuell bearbeitet und entschieden haben, welcher Code beibehalten werden soll, müssen Sie die folgenden Schritte ausführen, um die Zusammenführung abzuschließen:

    1. Aus Datei entfernen<<<<, ====, >>>>markieren.
    2. git add <file>(Fügen Sie die aufgelöste Datei zum temporären Speicherbereich hinzu.)
    3. git commit(Merge-Commit abschließen).


    GitHub

    GitHub ist eine cloudbasierte Versionskontroll- und Kollaborationsplattform, die hauptsächlich für die Softwareentwicklung verwendet wird. es nutztGitImplementieren Sie eine Versionskontrolle, die es Entwicklern ermöglicht, den Quellcode eines Projekts zu verwalten, Änderungen zu verfolgen und mit anderen zusammenzuarbeiten.

    Hauptfunktionen

    Vorteile der Verwendung von GitHub

    Anwendbare Objekte

    GitHub eignet sich für alle Arten von Entwicklern, egal ob Einzelentwickler, Open-Source-Communitys oder Unternehmensteams. Es kann die Versionskontroll- und Zusammenarbeitsanforderungen kleiner Projekte bis hin zu großen Softwareprojekten erfüllen.

  • GitHub

    GitHub verwendetgit pull --rebase

    git pull --rebaseEs ruft die neuesten Änderungen aus dem Remote-Zweig ab und wendet die lokalen Änderungen erneut auf den neuesten Remote-Commit an, anstatt die herkömmliche Zusammenführung zu verwenden.

    Verwendung

    git pull --rebase

    Arbeitsablauf

    1. Erhalten Sie die neuesten Änderungen aus der Remote-Zweigstelle.
    2. Lokale Commits vorübergehend entfernen.
    3. Wenden Sie Remote-Commits auf den lokalen Zweig an.
    4. Wenden Sie lokale Commits erneut an, um den Verlauf linear zu halten.

    Warum verwenden--rebase

    Anwendungsbeispiele

    Angenommen, Sie übernehmen einige Änderungen lokal und es gibt neue Festschreibungen auf der Remote-Seite, verwenden Siegit pull --rebasetreffen:

    Konflikte lösen

    Wenn beim Wiedergeben eines lokalen Commits ein Konflikt auftritt, fordert Git zur manuellen Konfliktlösung auf:

    1. Konflikte lösen und nutzengit addBühnenaufgelöste Dateien.
    2. verwendengit rebase --continueSpielen Sie den Commit weiter ab.
    3. Wenn Sie den Vorgang abbrechen möchten, verwenden Siegit rebase --abortZurück zum Status Quo.

    Zusammenfassen

    git pull --rebaseEs ist ein wichtiges Tool, um den Git-Übermittlungsverlauf sauber zu halten. Es eignet sich besonders für die Zusammenarbeit mehrerer Personen. Dadurch können redundante Zusammenführungsübermittlungen vermieden und der Übermittlungsdatensatz der Codebasis linear gehalten werden.



    GitHub-Benutzerzugriff

    Damit andere Entwickler an Ihrem Projekt teilnehmen können, müssen Sie sie über die Einstellungsseite des Repositorys als Mitarbeiter hinzufügen. Das Folgende ist der Vorgang:


    Arbeitsschritte

    1. Betreten Sie das Repository: Öffnen Sie die Homepage des Projekts, das Sie auf GitHub autorisieren möchten.
    2. Einstellungen öffnen: Klicken Sie oben rechts in der Menüleiste aufSettings(Zahnradsymbol).
    3. Zugriff verwalten: Klicken Sie in der linken Seitenleiste aufAccessunter KategorieCollaborators
    4. Authentifizierung: Möglicherweise werden Sie aufgefordert, Ihr GitHub-Passwort erneut einzugeben oder eine zweistufige Verifizierung durchzuführen, um Ihre Identität zu bestätigen.
    5. Neues Mitglied hinzufügen:KlickenAdd peopleTaste.
    6. Nach Benutzern suchen: Geben Sie den Namen des anderen Teilnehmers in das Popup-Fenster einGitHub-Kontonamevollständiger NameoderE-Mail
    7. Einladung senden: Nachdem Sie den richtigen Benutzer ausgewählt haben, klicken Sie aufFügen Sie [Name] zu diesem Repository hinzu

    Berechtigungsstufen

    Für persönliche Konto-Repositorys verfügen Eingeladene normalerweise standardmäßig über Lese- und Schreibberechtigungen; Handelt es sich um ein Organisationskonto, können detailliertere Einstellungen vorgenommen werden:

    Berechtigungsstufe veranschaulichen
    Read Kann nur Code lesen und kopieren, geeignet für reine Zuschauer.
    Triage Kann Issues und Pull Requests verwalten, aber keinen Code schreiben.
    Write Code kann direkt in das Repository gepusht werden.
    Maintain Neben dem Schreiben können Sie auch einige Einstellungen des Repositorys verwalten.
    Admin Sie haben die volle Kontrolle, einschließlich des Löschens von Repositorys und der Verwaltung anderer Mitarbeiter.

    Dinge zu beachten



    Löschen Sie ein GitHub-Repository

    Löschen eines GitHub-Repositorys über die Weboberfläche

    Dies ist die gebräuchlichste und intuitivste Methode zum Löschen. Bitte beachten Sie, dass ein einmal gelöschtes Repository nur dann wiederhergestellt werden kann, wenn Sie über ein Backup verfügen.

    1. Gehen Sie zu GitHub und gehen Sie zu der Datei, die Sie löschen möchtenHauptseite des Repositorys
    2. Klicken Sie oben rechts auf die Registerkarte „Paging“.Settings(aufstellen).
    3. Scrollen Sie auf der Seite nach unten und finden Sie die rot markierte SeiteDanger Zone(Gefahrenbereich).
    4. KlickenDelete this repositoryTaste.
    5. Es erscheint ein Bestätigungsfenster, in dem Sie aufgefordert werden, den vollständigen Namen des Repositorys einzugeben (normalerweise im FormatBenutzername/Repository-Name)。
    6. Klicken Sie auf die Schaltfläche unten, um den Löschvorgang zu bestätigen.
    ---

    Mit der GitHub-CLI löschen

    Wenn Sie das Befehlszeilentool (gh) von GitHub installiert haben, können Sie es schnell über das Terminal löschen:

    gh repo delete <Benutzername>/<Repository-Name> --bestätigen

    Beachten:--confirmDer Parameter überspringt den Bestätigungsschritt direkt. Bitte verwenden Sie ihn mit Vorsicht.

    ---

    Lokalen Repository-Ordner löschen

    Nachdem das Remote-Repository auf GitHub gelöscht wurde, ist der lokale Ordner auf Ihrem Computer weiterhin vorhanden. Um den Ordner vollständig zu entfernen, löschen Sie ihn manuell:

    Linux / macOS / ChromeOS

    rm -rf <Ordnername>

    Windows (CMD)

    rd /s /q <Ordnername>
    ---

    Verhaltenscheckliste löschen

    Betriebsmodus Einflussbereich Ist es wiederherstellbar?
    Entfernung der Webschnittstelle Löschen Sie nur Daten auf dem GitHub-Remoteserver. Nein (es sei denn, Sie wenden sich an den Support oder Fork)
    rm -rf-Befehl Löschen Sie nur lokale Dateien auf Ihrem Computer. Nein (es sei denn, es gibt einen Papierkorb)
    Löschen Sie den .git-Ordner Behalten Sie die Datei, verschieben Sie sie jedoch zurück in den normalen Ordner (wodurch die Versionskontrollfunktion verloren geht). Ja (re-git init)

    Dinge zu beachten



    Visual Studio verwendet Git

    Überblick

    Visual Studio verfügt über eine integrierte Git-Integrationsfunktion, Sie müssen jedoch weiterhin die ausführbare Git-Datei im System installieren, um Versionskontrollvorgänge (wie Commit, Push, Pull, Merge usw.) auszuführen.

    Schritt 1: Bestätigen Sie, ob Git installiert ist

    1. Öffnen Sie die Eingabeaufforderung (CMD) oder PowerShell.
    2. Geben Sie den folgenden Befehl ein:
      git --version
    3. Wenn es so etwas anzeigt wiegit version 2.x.x, bedeutet, dass es installiert wurde; Wenn „Unrecognized git command“ angezeigt wird, müssen Sie Git installieren.

    Schritt 2: Laden Sie Git herunter und installieren Sie es

    1. Gehe zuOffizielle Git-Downloadseite
    2. Wählen Sie die entsprechende Betriebssystemversion (Windows, macOS oder Linux).
    3. Führen Sie nach dem Herunterladen das Installationsprogramm aus. Es wird empfohlen, die Standardeinstellungen zu verwenden und vollständig auf „Weiter“ zu klicken.
    4. Nachdem die Installation abgeschlossen ist, starten Sie Visual Studio neu.

    Schritt 3: Git-Benutzerinformationen einrichten

    Aktivieren Sie die Eingabeaufforderung und legen Sie Ihren Benutzernamen und Ihre E-Mail-Adresse fest:

    git config --global user.name „Ihr Name“
    git config --global user.email „Ihre [email protected]

    Diese Informationen werden jedem Commit angehängt und zur Identifizierung des Entwicklers verwendet.

    Schritt 4: Aktivieren Sie Git in Visual Studio

    1. Starten Sie Visual Studio.
    2. Klicken Sie auf das Menü obenAnsicht → Team Explorer
    3. wählenVerbinden → Repository klonenum das Remote-Repository zu kopieren.
    4. Oder klicken Sie in ein bestehendes ProjektGit → Git-Repository erstellen, wodurch das Projekt Teil der Versionskontrolle wird.

    Schritt 5: Überprüfen Sie den Integrationsstatus

    Ergänzung: Verwenden Sie die integrierte Git-Installation von Visual Studio

    Wenn Sie Visual Studio 2022 oder neuer verwenden, können Sie dies während des Installationsvorgangs überprüfen「Git for Windows」Optionen. Auf diese Weise installiert und integriert Visual Studio Git automatisch und ohne manuelle Konfiguration.

    Wirkung nach Fertigstellung

    Sobald die Einstellungen abgeschlossen sind, können Sie die folgenden Vorgänge direkt in Visual Studio ausführen:



    Azure DevOps

    Einführung in die Plattform

    Azure DevOps ist eine von Microsoft bereitgestellte integrierte Entwicklungs- und Kollaborationsplattform, die den gesamten DevOps-Prozess von der Codeverwaltung über die Erstellung und automatisierten Tests bis hin zur Bereitstellung unterstützt. Es eignet sich für eine Vielzahl von Programmiersprachen und Frameworks und kann für persönliche Projekte oder die Teamentwicklung großer Unternehmen verwendet werden.

    Hauptbestandteile der Dienstleistung

    Hauptmerkmale

    Häufige Verwendungen

    Verwendung

    1. Gehe zuOffizielle Azure DevOps-Website
    2. Melden Sie sich an oder registrieren Sie sich für ein Microsoft-Konto.
    3. Erstellen Sie neue Organisationen und Projekte.
    4. Richten Sie Module wie Repos, Pipelines und Boards ein, um den Entwicklungs- und Bereitstellungsprozess zu starten.

    Vorteil

    Anwendbare Szenarien



    Azure DevOps-Zugriffsebenen

    Schrittanweisungen

    1. EinloggenAzure DevOps
    2. Klicken Sie auf die untere linke EckeOrganisationseinstellungen
    3. Wählen Sie aus dem Menü auf der linken Seite ausBenutzer
    4. Das System listet alle Benutzer in der Organisation und deren entsprechende Benutzer aufZugriffsebene

    Allgemeine Zugriffsebenentypen

    Erweiterter Betrieb

    Hinweis

    Wenn bei der Verwendung von Azure DevOps Pipelines, Repos oder Boards Probleme mit Berechtigungseinschränkungen auftreten, überprüfen Sie bitte zunächst, ob Ihre Zugriffsebene aktiviert istBasicoder höher.



    Plattformübergreifendes CMake-Build-System

    CMake-Definition

    CMake ist ein plattformübergreifendes Open-Source-„Meta-Build-System“. Es kompiliert den Programmcode nicht direkt selbst, sondern generiert automatisch Projektdateien, die für das aktuelle Betriebssystem und die Entwicklungsumgebung geeignet sind, indem es die Konfigurationsdatei (CMakeLists.txt) liest. Unter Windows wird beispielsweise eine Visual Studio-Lösung generiert, während unter Linux eine Makefile- oder Ninja-Konfigurationsdatei generiert wird.

    Installieren Sie CMake

    So installieren Sie CMake auf verschiedenen Betriebssystemen:

    Kernfunktionen

    CMake wurde entwickelt, um die Verwaltung komplexer Softwareprojekte zu vereinfachen. Es unterstützt mehrstufige Verzeichnisstrukturen, verwaltet Abhängigkeiten zwischen Bibliotheken und sucht automatisch nach installierten Bibliotheken auf dem System. Darüber hinaus bietet es auch Test- (CTest) und Verpackungsfunktionen (CPack) und deckt den gesamten Lebenszyklus von der Entwicklung bis zur Veröffentlichung ab.

    Mainstream-Bauprozess

    Schritt Befehlsbeispiel veranschaulichen
    1. Konfigurieren cmake -S . -B build Lesen Sie Einstellungen und erkennen Sie die Systemumgebung.
    2. Generieren (automatisch ausgeführt) Erstellen Sie eine Makefile- oder VS-Projektdatei.
    3. Bauen cmake --build build Rufen Sie den Compiler auf, um die eigentliche Kompilierung durchzuführen.
    4. Installieren cmake --install build Verschieben Sie die generierte ausführbare Datei in den angegebenen Pfad.

    x64- und ARM64-Unterstützung

    CMake verfügt über hervorragende architekturübergreifende Unterstützungsfunktionen. In einer Windows-Umgebung können Entwickler die Zielarchitektur über Parameter wie „using“ angeben-A x64oder-A ARM64. Für moderne Apple Silicon unterstützt CMake die Generierung universeller Binärdateien, sodass Programme sowohl auf Intel- als auch auf Apple-Prozessoren der M-Serie ausgeführt werden können.

    Warum CMake wählen?

    Herkömmliche Makefiles sind schwer zu warten und nicht plattformübergreifend einsetzbar. Mit CMake können Entwickler einfach eine Reihe von Konfigurationsdateien schreiben, und Entwickler auf der ganzen Welt können Projekte problemlos in ihrer bevorzugten IDE (z. B. VS Code, CLion, Xcode) öffnen und kompilieren. Aus diesem Grund verwenden die meisten Mainstream-Open-Source-C++-Projekte derzeit CMake als Standardtool.



    Programmbereitstellung

    Definition

    Bei der Anwendungsbereitstellung handelt es sich um den Prozess, bei dem eine entwickelte Anwendung von einer Entwicklungsumgebung in eine Test- oder Produktionsumgebung verschoben wird, damit Benutzer sie tatsächlich verwenden können. Es stellt sicher, dass das System in verschiedenen Umgebungen stabil und reproduzierbar funktionieren kann.

    Bereitstellungsprozess

    1. Bauen:Kompilieren und verpacken Sie Quellcode in ausführbare Dateien oder Bilddateien.
    2. Prüfen:Überprüfen Sie Funktionalität, Leistung und Kompatibilität.
    3. Einsetzen:Stellen Sie Anwendungen und Konfigurationsdateien auf dem Server bereit.
    4. Monitor:Überwachen Sie kontinuierlich den Betriebsstatus, zeichnen Sie Protokolle und Leistungsindikatoren auf.

    Gängige Bereitstellungsmethoden

    Gemeinsame Bereitstellungsarchitektur

    Automatisierte Bereitstellungstools

    Bereitstellungsbeispiel

    # Stellen Sie das Beispiel mit GitHub Actions bereit
    Name: Web-App bereitstellen
    am:
      drücken:
        Zweige: [ "main" ]
    Jobs:
      bereitstellen:
        läuft weiter: ubuntu-latest
        Schritte:
          - verwendet: actions/checkout@v4
          - Name: Docker-Image erstellen
            Führen Sie Folgendes aus: docker build -t myapp .
          - Name: Auf dem Server bereitstellen
            Ausführen: Docker run -d -p 80:80 myapp

    Überlegungen zur Bereitstellung

    Bereitstellungsstrategie

    Best Practices



    Containerisierungstechnologie

    Definition

    Docker (Containertechnologie) ist eine Open-Source-Plattform zur Automatisierung der Bereitstellung, Skalierung und Verwaltung von Anwendungen. Es verwendet „Container“, um Anwendungen und ihre Abhängigkeiten zusammenzupacken und so eine konsistente Ausführung in verschiedenen Umgebungen sicherzustellen.

    Kernkonzepte

    Vorteile von Docker

    grundlegende Anweisungen

    Dockerfile-Beispiel

    # Verwenden Sie eine Python-Bilddatei
    VON Python:3.10
    
    # Arbeitsverzeichnis festlegen
    WORKDIR/app
    
    # Programmdateien kopieren
    KOPIEREN ./app
    
    #Abhängigkeitspakete installieren
    FÜHREN Sie pip install -r require.txt aus
    
    #Geben Sie die Anweisungen an, die beim Start des Containers ausgeführt werden sollen
    CMD ["python", "app.py"]

    Docker Compose

    Docker Compose ist ein Tool, das mehrere Containeranwendungen definieren kann. Verwendendocker-compose.ymlDateien definieren jeden Dienst.

    version: '3'
    services:
      web:
        build: .
        ports:
          - "8000:8000"
      db:
        image: mysql:8
        environment:
          MYSQL_ROOT_PASSWORD: example
    

    Anwendungsszenarien

    Verwandte Technologien



    Modulabhängigkeitsanalyse

    Die Modulabhängigkeitsanalyse ist eine Technik der Softwareentwicklung, mit der externe Dateien (z. B. DLLs, Bibliotheken, Frameworks) identifiziert und verfolgt werden, von denen eine Anwendung bei der Ausführung abhängt. Dies ist entscheidend, um sicherzustellen, dass die Software in verschiedenen Umgebungen korrekt funktioniert.


    Kernanalysedimensionen


    Hauptzweck der Analyse

    Zweck Ausführliche Beschreibung
    Fehlerbehebung Finden Sie Programmabstürze, die durch fehlende DLL oder Versionskonflikte verursacht wurden.
    Sicherheitsaudit Identifiziert, ob ein Programm nicht autorisierte Komponenten von Drittanbietern lädt oder Sicherheitslücken aufweist.
    Leistungsoptimierung Bewerten Sie die Auswirkungen zu vieler abhängiger Module auf die Startzeit und die Speichernutzung und entfernen Sie unnötige Verweise.
    Beurteilung der Transplantierbarkeit Bestimmen Sie, ob die Software auf einem Computer ausgeführt werden kann, auf dem keine bestimmte Entwicklungsumgebung installiert ist, z. B. die .NET-Laufzeit- oder VC++-Bibliotheken.

    Gängige Analysetools



    Dependency Walker

    Dependency Walker (allgemein bekannt als Depends.exe) ist ein kostenloses Tool zur Analyse der Dateistruktur von Windows-Anwendungen (wie .exe, .dll, .sys usw.). Es wird hauptsächlich zum Scannen aller 32-Bit- oder 64-Bit-Windows-Module und zum Erstellen einer hierarchischen Baumstruktur aller zugehörigen abhängigen Module verwendet.


    Kernfunktionen


    Gängige Anwendungsszenarien

  • DLL-Höllenerkennung
  • Szene beschreiben
    Fehlerbehebung bei Systemfehlern Beheben Sie Systemfehler wie 0xc000007b (Parallelkonfigurationsfehler) oder das angegebene Modul wurde nicht gefunden.
    Softwarebereitstellung Entwickler überprüfen, ob das Installationsprogramm alle erforderlichen Ausführungsbibliotheken enthält (z. B. VC++ Redistributable).
    Überprüfen Sie, ob im Systempfad verschiedene Versionen der DLL mit demselben Namen vorhanden sind, die zu einem abnormalen Verhalten des Programms führen.

    Nutzungsbeschränkungen und Alternativen

    Da Dependency Walker seit vielen Jahren nicht mehr aktualisiert wurde, unterstützt es einige Funktionen des modernen Windows 10/11 nur unzureichend (z. B. API-Sets oder Lazy-Loaded-DLLs) und es werden häufig falsche rote Warnungen angezeigt. In diesem Fall werden die folgenden Open-Source-Alternativtools empfohlen:



    Dependencies

    Dependencies ist ein modernes Open-Source-Tool zur Abhängigkeitsanalyse, das den seit vielen Jahren eingestellten Dependency Walker (Depends.exe) ersetzen soll. Es ist vollständig für die Systemarchitektur von Windows 10 und Windows 11 optimiert und kann Modulzuordnungen in modernen Softwareumgebungen genau analysieren.


    Warum Abhängigkeiten wählen?


    Funktionsvergleichstabelle

    Merkmal Dependency Walker (alte Version) Abhängigkeiten (moderne Version)
    Unterstützung für Windows 10/11 Schlecht (häufige Fehlalarme) Hervorragend (native Unterstützung)
    Verarbeitung von API-Sets Nicht erkannt (wird in Rot als fehlend angezeigt) Korrekt der Entitäts-DLL zugeordnet
    Entwicklungsstand Updates gestoppt (2006) Unter laufender Wartung (GitHub)
    Kerntechnologie C++ / MFC C# / WPF (einige Low-Level-C++)

    Allgemeine Shortcut-Funktionen


    Besorgen und installieren

    Dependencies ist eine umweltfreundliche, installationsfreie Software, die normalerweise von GitHub heruntergeladen werden kannlucasg/DependenciesDas Repository lädt die kompilierte Release-Version herunter. Wenn Sie es verwenden, ziehen Sie einfach die .exe- oder .dll-Datei, die Sie analysieren möchten, in das Fenster, um die Analyse zu starten.



    Unterschiede in der Ausführungsphasenerkennungsfunktion

    Die beiden Tools haben unterschiedliche Designphilosophien: Dependency Walker (Depends.exe) enthält einen dynamischen Analysator (Profiler), während moderne Dependencies sich auf statische Analyse und API-Sets-Analyse konzentrieren.


    Warum führen Abhängigkeiten das Programm nicht aus?


    So verwenden Sie Dependency Walker zur Bewegungserkennung (Profiling)

    Wenn Sie den „Executor“ verwenden müssen, um DLL-Fehler zu beheben, die nur beim Ausführen auftreten (z. B. Fehler beim verzögerten Laden oder Probleme bei der Pfadsuche), können Sie weiterhin die Profilfunktion von Dependency Walker verwenden:

    1. Starten Sie Dependency Walker und laden Sie Ihre EXE-Datei.
    2. Drücken Sie auf der TastaturF7Oder klicken Sie auf das MenüProfile -> Start Profiling
    3. Legen Sie Parameter (z. B. Arbeitsverzeichnis, Befehlszeilenparameter) im Popup-Dialogfeld fest und klicken Sie dannOK
    4. Schauen Sie sich das Protokollfenster unten an: Wenn das Programm ausgeführt wird und abstürzt, zeigt das Protokoll unten in roter Schrift an, bei welcher DLL beim Laden der Fehler aufgetreten ist.

    Vergleich der Vor- und Nachteile der Bewegungserkennung

    Vorteil Mangel
    FähigDynamic Loading(LoadLibrary)-Fehler. Bei der Ausführung unter Win10/11 werden die Protokolle mit einer großen Anzahl falscher API-MS-WIN-Fehlermeldungen gefüllt.
    Kann den tatsächlich geladenen DLL-Dateipfad bestätigen (bezogen auf die Suchpfadreihenfolge). Wenn das Programm aufgrund zu vieler Abhängigkeiten überhaupt nicht startet, kann Profiler möglicherweise keine nützlichen Informationen erfassen.

    Erweiterte Debugging-Vorschläge

    Wenn Sie im Profiler von Dependency Walker zu viele falsche Fehler haben und den Sinn nicht erkennen können, wird empfohlen, stattdessen die folgende Kombination zu verwenden:



    KI-Tools für die Programmentwicklung


    GitHub Copilot

    Es wurde von GitHub in Zusammenarbeit mit OpenAI entwickelt und ist derzeit der weltweit am häufigsten verwendete KI-Codierungsassistent. Es kann direkt eingebettet werdenVisual Studio CodeJetBrainsIn anderen gängigen Entwicklungsumgebungen analysiert es Kommentare und Kontext, um sofort Codezeilen oder ganze Funktionen vorzuschlagen.


    Cursor

    Dies ist eine unabhängige Software, die auf der VS-Code-Architektur basiert.AI-Code-Editor. Im Gegensatz zu einem einfachen Plug-in integriert Cursor die KI tief in die unterste Ebene des Editors. Es versteht die Struktur (den Kontext) des gesamten Projekts und ermöglicht Entwicklern, direkt mit der gesamten Bibliothek zu kommunizieren, um globale Refactorings oder Fehlerbehebungen durchzuführen.


    Claude 3.5 Sonnet

    Obwohl Claude eine Allzweck-KI ist, ist sie es3.5 Sonnet-ModellIn Bezug auf Programmlogik, Architekturdesign und Debugging-Funktionen gilt es als eine der besten Optionen. übereinstimmenArtifactsMit dieser Funktion können Entwickler direkt eine Vorschau des generierten Webseiten-Frontend-Bildschirms oder interaktiver Komponenten im Dialogfeld anzeigen.


    Tabnine

    Tabnine legt großen Wert daraufPrivatsphäre und Sicherheit, geeignet für Unternehmen mit hohen Anforderungen an die Vertraulichkeit des Quellcodes. Es unterstützt die vollständig lokalisierte Bereitstellung (Selbsthosting), stellt sicher, dass der Code nicht zu Schulungszwecken in die Cloud hochgeladen wird, und bietet genaue Funktionen zur automatischen Vervollständigung.


    Amazon Q (ehemals CodeWhisperer)

    Entwicklungsassistent bereitgestellt von Amazon Web Services (AWS). Zusätzlich zur grundlegenden Codegenerierung wird es insbesondere um erweitertAWS-Cloud-DiensteDie Integration kann Entwicklern helfen, schnell Infrastruktur als Code (IaC) zu schreiben oder Sicherheitsscans und Updates durchzuführen.


    Replit Agent

    In die Online-Entwicklungsumgebung Replit integrierter KI-Agent. Es zeichnet sich aus durchAutomatisierte BereitstellungBeim Erstellen einer Umgebung müssen Benutzer nur die Funktionen der Anwendung beschreiben, und der Agent kann automatisch Dateien erstellen, abhängige Pakete installieren, Code schreiben und den Online-Vorgang abschließen.


    v0.dev

    Präsentiert von VercelKI für die Frontend-Entwicklung. Benutzer beschreiben Schnittstellenanforderungen in natürlicher Sprache, und v0 generiert direkt Front-End-Komponentencode basierend auf React, Tailwind CSS und Shadcn UI, wodurch die Zeit für UI-Stereotypen erheblich verkürzt wird.



    Agentenbasierter KI-Programmierassistent

    Agentische KI-Codierungsassistenten. Die Merkmale dieser Art von Tool sind die Fähigkeit, direkt auf das Terminal zuzugreifen, Dateien zu lesen und zu schreiben, Tests auszuführen und Aufgaben unabhängig zu planen.


    1. Terminal- und CLI-Tools

    Diese Art von Tool kommt Claude Code am nächsten und wird direkt in Ihrem Terminal ausgeführt, sodass es für Entwickler geeignet ist, die mit Befehlszeilenvorgängen vertraut sind.


    2. IDE- und Editor-Tools

    Solche Tools integrieren Agentenfunktionen in den Editor, um eine intuitivere visuelle Entwicklungserfahrung zu ermöglichen.


    3. Vollautomatischer KI-Ingenieur (völlig autonom)

    Solche Tools verfügen in der Regel über unabhängigere Betriebsfunktionen und können den Prozess von der Bedarfsanalyse bis zur Bereitstellung im Web oder in einer eigenständigen Umgebung abschließen.


    Vergleichstabelle der Kernfunktionen

    Werkzeugname Hauptschnittstelle Kernvorteile
    Claude Code CLI (Terminal) Es wurde nativ von Anthropic entwickelt und folgt sehr genau den Anweisungen von Claude 3.5.
    Aider CLI (Terminal) Open Source, unterstützt mehrere Modelle und verfügt über eine starke automatisierte Git-Verwaltung.
    Cursor IDE (Herausgeber) Die Benutzeroberfläche weist den höchsten Integrationsgrad auf und eignet sich für Entwickler, die nicht gerne das Terminal wechseln.
    Cline VS-Code-Plugin Open Source und völlig transparent, Sie können verschiedene API-Schlüssel selbst verbinden.

    So wählen Sie aus



    Claude Code

    Claude Code ist ein von Anthropic entwickeltes agentenbasiertes Befehlszeilenschnittstellen-Tool (CLI). Es läuft direkt im Terminal des Entwicklers und kann die gesamte Programmcodebibliothek verstehen, Terminalbefehle ausführen, Dateien bearbeiten und bei der Verarbeitung des Git-Workflows helfen, sodass Entwickler komplexe Programmieraufgaben in natürlicher Sprache erledigen können.


    Kernfunktionen


    Installationsmethode

    Claude Code erfordert die Node.js 18+-Umgebung, die mit den folgenden Methoden installiert werden kann:

    1. Mit npm installieren:
      npm install -g @anthropic-ai/claude-code
    2. Starten Sie das Tool:
      Geben Sie das Projektverzeichnis einclaudeJetzt können Sie den interaktiven Modus starten.

    Betriebsmodi und Tastenkombinationen

    Funktion Betriebsmodus/Tastenkombinationen
    Plan Mode Shift + Tab(Mac/Linux) bzwAlt + M(Windows). Erstellen Sie vor der Ausführung einen detaillierten Plan.
    Auto-accept Alle Änderungen werden automatisch übernommen, ohne dass jede einzelne bestätigt werden muss.
    Datei auswählen eingeben@Suchen Sie schnell nach bestimmten Dateien und fügen Sie sie als Hintergrundwissen hinzu.
    Anweisungen ausführen verwenden!Präfix, um Bash-Befehle direkt in der Sitzung auszuführen (zum Beispiel:!ls -la)。

    Häufig verwendete integrierte Befehle


    Hardware- und Systemanforderungen


    Für häufige Popups zur Berechtigungsbestätigung und die Notwendigkeit eines verzeichnisübergreifenden Zugriffs können Optimierungseinstellungen über Startparameter und integrierte Befehle vorgenommen werden.

    1. Reduzieren Sie Pop-ups zur Berechtigungsbestätigung

    Standardmäßig bestätigt Claude Code gefährliche Befehle (z. B. das Löschen von Dateien und das Ausführen von Systembefehlen) nacheinander. Um in den „Automatisierungsmodus“ zu wechseln und Störungen zu reduzieren, verwenden Sie die folgenden Parameter:


    2. Greifen Sie auf andere Verzeichnisse als das aktuelle Verzeichnis zu

    Aus Sicherheitsgründen ist Claude Code standardmäßig auf das Projektverzeichnis beschränkt, in dem es gestartet wird. Um auf externe Pfade zuzugreifen, gibt es drei Methoden:


    3. Richten Sie einen dauerhaften Alias ​​ein (Alias)

    Um einen schnellen Start zu ermöglichen und diese Einstellungen in Zukunft zu übernehmen, wird empfohlen, dass Sie.bashrcoder.zshrc(Cygwin/Linux) Alias ​​hinzufügen:

    alias c='claude --auto-accept . /home/user/common_library'

    Dinge zu beachten


    Für die Anforderungen eines vollautomatischen Starts (keine Bestätigung) und des Zugriffs auf externe Verzeichnisse stellt Claude Code spezielle CLI-Parameter zur Verfügung, um dies zu erreichen. Diese Funktionen werden oft als „YOLO-Modus“ bezeichnet und eignen sich für den Einsatz in einer vertrauenswürdigen Umgebung oder Sandbox.

    1. Vollautomatische Ausführung: Überspringen Sie alle Berechtigungsbestätigungen

    Wenn Sie nicht ausführen möchtenlsmkdirOder wenn Sie beim Bearbeiten einer Datei immer wieder auf „OK“ klicken, können Sie die folgenden gefährlichen Parameter verwenden:


    2. Auf externe Verzeichnisse zugreifen: Berechtigungspfad hinzufügen

    Standardmäßig kann Claude nur das Verzeichnis lesen und schreiben, in dem es gestartet wird. Um auf andere Pfade zuzugreifen, verwenden Sie--add-dir


    3. Kombinationsgeschick: Der stärkste automatische Startbefehl

    Wenn Sie es sofort richtig machen und ungehindert direkt zwischen mehreren Verzeichnissen entwickeln möchten, können Sie eine Kombination aus Folgendem verwenden:

    claude --dangerously-skip-permissions --add-dir ../library --add-dir ~/shared_configs

    Vergleichstabelle der Startparameter

    Parametername Funktionsbeschreibung Anwendbare Situationen
    --dangerously-skip-permissions Berechtigungsbestätigung für alle Tools (Bash, Lesen, Schreiben) überspringen. Erfordert umfangreiches automatisches Refactoring oder Betrieb in einer Sandbox-Umgebung.
    --add-dir <path> Ermächtigt Claude, auf bestimmte Pfade außerhalb des aktuellen Verzeichnisses zuzugreifen. Für die projektübergreifende Entwicklung ist möglicherweise der Verweis auf externe Dokumentation erforderlich.
    --permission-mode acceptEdits Akzeptieren Sie Dateiänderungen automatisch, fragen Sie aber trotzdem nach, wenn Sie Bash-Befehle ausführen. Relativ sicherer Automatisierungsmodus.

    Sicherheitserinnerung



    Cursor

    Cursor ist ein KI-Code-Editor, der auf Basis von VS-Code entwickelt wurde. Es handelt sich nicht nur um ein Plug-in, sondern es bettet KI-Funktionen tief in die unterste Ebene des Editors ein, sodass dieser den Kontext des gesamten Projekts verstehen und automatisch Code schreiben, rekonstruieren und reparieren kann. Da es VS-Code erbt, können Benutzer alle ursprünglichen Einstellungen und erweiterten Funktionen direkt importieren.


    Grundinstallation

    1. Software herunterladen:Gehe zuOffizielle Cursor-Website, das System erkennt automatisch Ihr Betriebssystem (Windows, macOS, Linux) und bietet den Download an.
    2. Importeinstellungen:Nach der Installation und dem Start werden Sie von Cursor gefragt, ob Sie Erweiterungen, Verknüpfungen und Designs aus VS Code importieren möchten. Es wird empfohlen, „Importieren“ zu wählen, um Entwicklungsgewohnheiten nahtlos zu integrieren.
    3. Login-Konto:Registrieren Sie sich und melden Sie sich bei Ihrem Cursor-Konto an. Die kostenlose Version (Hobby) bietet eine begrenzte Anzahl von Abfragen für Modelle höherer Ordnung (wie GPT-4o oder Claude 3.5 Sonnet) und wechselt danach zu einem kleineren Modell.

    Kernfunktionsnutzung

    1. Cmd + K (Inline Edit)

    Rufen Sie die KI direkt im Code-Editor auf:

    2. Cmd + L (Chat Pane)

    Chat-Dialog in der Seitenleiste:

    3. Cmd + I (Komponistenmodus)

    Dies ist der leistungsstärkste „Agent“-Modus von Cursor:


    Erweiterte Einrichtungstechniken

    Funktionsname Einstellungsmethode veranschaulichen
    Modellwechsel Unteres Menü der Seitenleiste Wechseln Sie zwischen Claude 3.5 Sonnet, GPT-4o oder Cursor Small.
    Rules for AI Settings > General Passen Sie den Antwortstil der KI an (z. B. verwenden Sie immer traditionelles Chinesisch, der Code muss bestimmte Spezifikationen erfüllen).
    Index Project Settings > Features Stellen Sie sicher, dass die lokale Indizierung aktiviert ist, damit die KI die Dateien des gesamten Projekts genau durchsuchen kann.

    Vergleich häufig verwendeter Tastenkombinationen


    Dinge zu beachten



    Aider


    Installieren

    Aider ist ein terminalbasiertes KI-Pairing-Programmiertool, das die direkte Änderung des lokalen Quellcodes unterstützt. Bitte stellen Sie vor der Installation sicher, dass das System ordnungsgemäß ausgestattet istPython 3.8Die oben genannten Versionen sind die gleichen wieGit

    python -m pip install aider-chat

    API-Schlüsselkonfiguration

    Vor dem Start muss der vom KI-Dienstanbieter bereitgestellte Schlüssel als Umgebungsvariable festgelegt werden. Aider unterstützt standardmäßig verschiedene Modelle wie Anthropic und OpenAI:

    Geben Sie nach Abschluss der Einstellung das Terminal einaiderDadurch wird die Konversationsoberfläche geöffnet.


    Dateioperationen

    Aider liest und ändert nur Dateien, die Sie angeben, um dem Kontext beizutreten, um Token-Kosten zu sparen und die Genauigkeit zu verbessern:


    Codebearbeitung

    Sie können Aider direkt mithilfe natürlicher Sprache auffordern, Aufgaben auszuführen, z. B. „Helfen Sie mir, diese Klasse in zwei Dateien aufzuteilen“ oder „Bestehende Fehler beheben“. Nach der Durchführung der Änderung führt Aider dies automatisch durchGit Commit, und verfassen Sie automatisch eine Übermittlungsnachricht basierend auf dem geänderten Inhalt.


    Anweisung

    Anweisung Funktionsbeschreibung
    /undo Machen Sie die letzte von der KI durchgeführte Codeänderung und das Git-Commit rückgängig.
    /diff Zeigen Sie eine Vorschau der Änderungen an, die an der aktuellen KI im Vergleich zur Originalversion vorgenommen wurden.
    /chat-mode Wechseln Sie zwischen Konversationsmodi (z. B. wird der Codemodus zum Ändern von Dateien verwendet, der Fragemodus wird nur für Fragen und Antworten verwendet).
    /help Zeigt die vollständige Liste der integrierten Befehle an.
    /exit Beenden Sie das Aider-Programm.


    Aider verwendet ein lokales Modell


    Machbarkeit und Prinzipien

    Aider unterstützt mehrere Möglichkeiten zur Schnittstelle mit lokal ausgeführten kostenlosen und Open-Source-Modellen. Die gebräuchlichste Methode ist die VerwendungOllamaLM StudiooderLocalAIWarten Sie, bis das Tool einen lokalen Server erstellt hat, der mit der OpenAI-API-Spezifikation kompatibel ist, und lassen Sie Aider dann auf die Serveradresse verweisen.


    Umgesetzt über Ollama

    Dies ist derzeit die einfachste und gängigste Lokalisierungslösung:

    aider --model ollama/deepseek-coder-v2

    Kerneinstellungsparameter

    Parameter Funktionsbeschreibung
    --model Geben Sie den Modellnamen an. Lokale Modelle liegen normalerweise im Format vorollama/<model_name>
    --openai-api-base Wenn Sie LM Studio verwenden, müssen Sie die lokale API-URL manuell angeben (z. Bhttp://localhost:1234/v1)。
    --no-stream Wenn die lokale Inferenzleistung nicht ausreicht und die Verbindung instabil ist, können Sie die Streaming-Ausgabe deaktivieren, um die Stabilität zu verbessern.

    Einschränkungen und Herausforderungen lokaler Modelle


    Empfohlene lokale Modelle

    Nicht alle Modelle sind für die Verwendung mit Aider geeignet. Die folgenden lokalen Open-Source-Modelle werden derzeit von der Community als leistungsstärker bei Programmentwicklungsaufgaben anerkannt:



    Gesetze im Zusammenhang mit der Softwareentwicklung

    Urheberrecht

    Softwarecodes, Designdokumente, Benutzerhandbücher usw. unterliegen alle dem Urheberrechtsschutz. Der Urheberrechtsschutz wird automatisch mit Abschluss der Erstellung hergestellt, eine Registrierung ist nicht erforderlich und das unbefugte Kopieren, Ändern, Verbreiten oder kommerzielle Nutzen ist untersagt.

    Patentrecht

    Wenn es sich bei der Software um technologische Innovationen oder einzigartige Algorithmen handelt, können Sie Patentschutz beantragen. Patente unterliegen der Prüfung und Genehmigung und schützen die ausschließlichen Rechte des Erfinders an technischen Lösungen, reine Programmlogik wird jedoch in der Regel nicht durch Patente geschützt.

    Markenrecht

    Softwarenamen, Logos und Markenidentitäten können als Marken eingetragen werden, um das Markenimage und die Marktdifferenzierung zu schützen und zu verhindern, dass andere damit Verwirrung stiften.

    Gesetz zum Schutz von Geschäftsgeheimnissen

    Nicht offengelegte Programmierdetails, Algorithmen, Datenbankstrukturen usw. sind Geschäftsgeheimnisse. Das Unternehmen sollte es durch Vertraulichkeitsvereinbarungen, Informationsmanagementsysteme usw. schützen.

    Vorschriften zur Informationssicherheit

    Beispielsweise verlangen das Personal Information Law und das Information Security Management Law von Benutzern, dass sie während des Softwareentwicklungsprozesses ordnungsgemäß mit personenbezogenen Daten umgehen und die Informationssicherheit gewährleisten. Verstöße können verwaltungs- oder strafrechtlich verfolgt werden.

    Vertragsrecht und Genehmigungsklauseln

    Bei der Softwareentwicklung handelt es sich häufig um Vertragsverträge, kooperative Entwicklungsverträge, Softwarelizenzbedingungen usw., in denen die Rechte und Pflichten beider Parteien, das Eigentum am Programmcode, die Wartungsverantwortung, die Vertraulichkeitspflicht usw. klar definiert sind, um Rechtsstreitigkeiten zu vermeiden.

    Vorschriften im Zusammenhang mit Internet und E-Commerce

    Der Online-Betrieb von Software umfasst Netzwerkdienste, elektronische Zahlungen, den Online-Schutz geistiger Eigentumsrechte usw. und muss Vorschriften wie dem Gesetz über elektronische Signaturen und dem Gesetz über elektronische Transaktionen entsprechen.

    Geistige Eigentumsrechte in der Softwareentwicklung

    Copyright

    Der Softwarecode fällt unter den Urheberrechtsschutz und Entwickler besitzen automatisch das Urheberrecht, ohne dass eine zusätzliche Registrierung erforderlich ist. Der Urheberrechtsschutz erstreckt sich auf Quellcode, Designdateien, Benutzerhandbücher usw.

    Patent

    Handelt es sich bei der Software um Neuheiten und technische Innovationen, kann unter Umständen ein Patentschutz beantragt werden. Beispiele hierfür sind einzigartige Algorithmen oder Methoden zur Lösung technischer Probleme, reine Codelogik liegt jedoch normalerweise außerhalb des Patentschutzes.

    Markenrechte

    Softwarenamen und Logos können als Marken eingetragen werden, um Produkte aus unterschiedlichen Quellen zu unterscheiden und Marktverwechslungen zu vermeiden.

    Geschäftsgeheimnisse

    Nicht offengelegte Programmierdetails, Datenbankstrukturen und Algorithmen können durch Geschäftsgeheimnisse geschützt werden. Es muss sich auf die unternehmensinterne Vertraulichkeitsvereinbarung und Managementmaßnahmen verlassen, um diese aufrechtzuerhalten.

    Autorisierungsmodus

    Software kann über verschiedene Lizenzmodelle veröffentlicht werden, beispielsweise proprietäre Software, freie Software und Open-Source-Lizenzen (wie GPL, MIT). Unterschiedliche Lizenzmodelle wirken sich auf die Rechte der Benutzer zur Änderung und Weiterverbreitung aus.

    Verletzungsrisiko

    Die unbefugte Nutzung des Codes, der Bilder oder Algorithmen einer anderen Person kann eine Urheberrechtsverletzung darstellen. Der Entwicklungsprozess sollte sicherstellen, dass die Quelle des Programmcodes legal ist, um Rechtsstreitigkeiten zu vermeiden.

    internationalen Schutz

    Geistige Eigentumsrechte sind territorialer Natur, können aber in vielen Ländern durch internationale Verträge wie die Berner Übereinkunft und das TRIPS-Übereinkommen bis zu einem gewissen Grad geschützt werden.



    Software-Einkaufszentrum

    Software-Verkaufsplattform

    Im Jahr 2026 wird die Wahl der richtigen Software-Vertriebsplattform von Ihrem Softwaretyp und Ihrem Zielmarkt abhängen. Im Folgenden sind die Klassifizierungen und Merkmale der Mainstream-Plattformen aufgeführt:


    Universelle digitale Produkte und SaaS-Plattformen

    Vertriebsplattform für Spiele und Desktop-Anwendungen

    Einkaufszentrum für Unternehmens- und Mobilanwendungen

    Taiwanesische lokale E-Commerce-Plattform


    Vergleichstabelle zur Plattformauswahl

    Nachfrageziel Empfohlene Plattform Kernvorteile
    Automatisieren Sie die globale Steuerverarbeitung Paddle / Lemon Squeezy Sparen Sie sich die Mühe der Steuererklärung in verschiedenen Ländern
    Streben Sie nach maximalem Verkehr Steam / App Store Vorgefertigte riesige Benutzerbasis
    Erstellen Sie schnell eine offizielle Marken-Website Shopify / SHOPLINE Hochgradig individuelles Einkaufserlebnis
    Frühzeitige Akquise von Seed-Benutzern AppSumo Erhalten Sie schnell Bargeld durch Werbeaktionen



    email: [email protected]
    
    T:0000
    資訊與搜尋 | 回dev首頁
    email: Yan Sa [email protected] Line: 阿央
    電話: 02-27566655 ,03-5924828