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.
Laut der neuesten Rangliste der Programmiersprachen sind hier die 20 besten Programmiersprachen im Jahr 2024:
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#.
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:
[capture](parameters) { function body }lambda parameters: expression(parameters) => expression
#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;
}
# Verwenden Sie den Lambda-Ausdruck, um die Summe zweier Zahlen zu berechnen
add = Lambda x, y: x + y
print(add(5, 10)) # Ausgabe: 15
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}");
}
}
map、filterUndreduceWarten Sie, bis Funktionen höherer Ordnung auf Sammlungen angewendet werden.# 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())
}
}
| Sprache | Unterstützung | veranschaulichen |
|---|---|---|
| Python | ✅ | Dynamische, vollständige Reflexion, einfache rekursive Objekt-/Behälterinspektion. |
| JavaScript / TypeScript | ✅ | Das Objekt ist ein Schlüsselwert und verfügbarObject.valuesRekursion. |
| Ruby | ✅ | instance_variablesreflektierendes Element. |
| PHP | ✅ | get_object_vars()Oder Reflexion. |
| C# (.NET) | ✅ | Reflection erhält Felder/Eigenschaften und weist eine gute Typsicherheit auf. |
| Java | ✅ | java.lang.reflectScanbare Felder. |
| Kotlin | ✅ | Die JVM-Reflexion ist vollständig, ähnlich wie bei Java. |
| Go | ✅ | reflectZugänglich für Strukturfelder. |
| Swift | ◑ | MirrorBesuche 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. |
| Rust | ❌ | Keine Laufzeitreflexion, oft implementiert durch Derive/Trait. |
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
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
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;
}
}
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
}
}
isAllZero, oder verwenden Sie eine Vorlage/ein Makro, um die Mitglieder zu erweitern.deriveMakros generieren automatisch Implementierungen für Typen (z. B. benutzerdefinierte Merkmale).IsAllZero)。eps, um Genauigkeitsprobleme zu vermeiden, die zu Fehleinschätzungen führen.isAllZero()Methode zur Vermeidung kostspieliger Reflexionsscans.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.
| 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. |
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.
| 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 |
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.
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.
MQ ist bei der Bewältigung vorübergehender Szenarien mit hohem Datenverkehr von entscheidender Bedeutung und kann Backend-Dienste vor Abstürzen schützen.
In komplexen verteilten Systemen und Microservice-Architekturen wird MQ verwendet, um Dienste zu isolieren und gegenseitige Abhängigkeiten zu reduzieren.
Sammeln Sie große Mengen an Protokolldaten von Front-End-Anwendungen oder Servern in einem zentralen Verarbeitungssystem.
Insbesondere MQ-/Streaming-Plattformen mit hohem Durchsatz wie Apache Kafka eignen sich ideal für die Verarbeitung kontinuierlicher Echtzeitdatenströme.
Die größten Herausforderungen bei der Verwendung der HTTP-API zur Übertragung großer Binärdaten (Binärdaten) wie Bilder und Videos sind:
Dies ist die standardmäßigste und gebräuchlichste Methode für einen Browser oder eine Clientanwendung zum Hochladen von Dateien.
multipart/form-data; boundary=YourBoundaryString
Wenn Sie nur eine einzelne Datei hochladen müssen, können Sie den binären Inhalt der Datei direkt als Betreff der Anfrage verwenden.
image/jpegoderimage/png;Video:video/mp4。
Konvertieren Sie Binärdaten in ASCII-Strings und betten Sie sie zur Übertragung in Textformate wie JSON oder XML ein.
Content-TypeDarüber hinaus werden APIs zur Verarbeitung einfacher Textformate unterstützt.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.
image/jpegodervideo/mp4。
attachment; filename="example.mp4"weist den Browser an, den Inhalt als Datei herunterzuladen, anstatt ihn direkt anzuzeigen.Bei besonders großen Dateien (insbesondere Videos) werden die folgenden Techniken zur Verbesserung der Zuverlässigkeit und Effizienz empfohlen:
RangeFordern Sie ein bestimmtes Fragment eines Archivs an (z. B.Range: bytes=100-200). Dies ist sehr wichtig für das Video-Streaming (Streaming), da der Player nur den Teil herunterladen kann, der abgespielt werden muss, und das schnelle Vor- und Zurückspulen unterstützt.Der Kern der Streaming-Übertragung besteht darin, Audio- und Videoinhalte effizient, stabil und mit geringer Latenz vom Server zum Client zu übertragen.
Dies ist der Grundstein moderner Streaming-Dienste. Der Server kodiert denselben Videoinhalt in mehrere Versionen unterschiedlicher Qualität (Bitrate, Auflösung).
CDN ist für Streaming-Dienste, die sich an globale Benutzer richten, unverzichtbar.
Wird zum Komprimieren und Dekomprimieren von Audio- und Videodaten verwendet, um die Dateigröße zu reduzieren.
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.
#!/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.
#!/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.
#!/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.
if [Bedingung]; dann
Anweisungen
fi
Um in if mehrere Bedingungen gleichzeitig zu erfüllen, verwenden Sie:
-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
[[ ]] &&(empfehlen)if [[ "$a" -gt 0 && "$b" -gt 0 ]]; dann
echo „a und b sind beide größer als 0“
fi
&&if [ "$a" -gt 0 ] && [ "$b" -gt 0 ]; dann
echo „a und b sind beide größer als 0“
fi
Es kann ausgeführt werden, solange eine der Bedingungen erfüllt ist:
-o(veraltet, aber verfügbar)if [ "$a" -eq 0 -o "$b" -eq 0 ]; dann
echo „a oder b ist 0“
fi
[[ ]] ||(empfehlen)if [[ "$a" -eq 0 || "$b" -eq 0 ]]; dann
echo „a oder b ist 0“
fi
||if [ "$a" -eq 0 ] || [ "$b" -eq 0 ]; dann
echo „a oder b ist 0“
fi
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
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
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
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
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
| 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 ] |
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
[[ ]]rechtzeitige Unterstützung&&Und||[ ]Es wird empfohlen, mehrere bedingte Anweisungen zusammen zu verwenden&& / ||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
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
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
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
| 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. |
"$var"), um Syntaxfehler zu vermeiden, wenn die Variable einen Nullwert hat.casewerden von oben nach unten verglichen. Sobald das Spiel erfolgreich ist und Begegnung;;stoppt, also versetzen Sie bitte den spezifischen Modus in den allgemeinen Modus (z. B*)Vor.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
---
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
---
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
---
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
---
| 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. |
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
existieren(( ))Dabei folgt die Rangfolge der Operationen standardmäßigen mathematischen und logischen Konventionen:
( )Höchste Priorität.*, /, %。+, -。<, >, <=, >=。&&(UND) hat Vorrang vor|| (OR)。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
| 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. |
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
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: $?“
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.
#!/bin/bash
# Dies ist der Ausgabeinhalt und wird erfasst
echo „Ubuntu_User“
# Dies ist der Endzustand und wird nicht von Backticks erfasst
Ausgang 0
# Backticks verwenden
RESULT=`./get_name.sh`
# Verwenden Sie $() (empfohlene moderne Schreibweise)
ERGEBNIS=$(./get_name.sh)
echo „Das erhaltene Ergebnis ist: $RESULT“
| 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“
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.
Dies ist die häufigste Verwendung.returnZurückgegeben wird der Statuscode (0-255), nicht die Zeichenfolgendaten.
#!/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
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。
# 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
Quelle ./sub_script.sh
echo „Skript gibt Status zurück: $?“
echo „Umgebungsvariablen abrufen: $APP_STATUS“
WeilreturnEs können nur Zahlen (Statuscodes) zurückgegeben werden. Um Zeichenfolgen oder große Datenmengen zu erhalten, empfiehlt sich die KombinationechoUndBefehlsersetzung。
#!/bin/bash
berechne() {
lokaler Wert=$(( $1 + $2 ))
# Ergebnisse auf stdout ausgeben
echo „$val“
# Ausführungsstatuscode zurückgeben
0 zurückgeben
}
Berechnen Sie 10 20
# 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“
| 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. |
In Bash können Sie mithilfe der bedingten Beurteilung prüfen, ob eine Variable leer ist. Hier sind einige gängige Methoden:
-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.
-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.
#!/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.
Bash unterstützt zwei Arten von Arrays:
fruits=("apple" "banana" "cherry")
echo "${fruits[0]}" # apple
echo "${fruits[1]}" # banana
echo "${fruits[@]}"
echo "${#fruits[@]}"
fruits+=("date")
for fruit in "${fruits[@]}"; do
echo "$fruit"
done
declare -A capital
capital["Taiwan"]="Taipei"
capital["Japan"]="Tokyo"
echo "${capital["Japan"]}" # Tokio
for Geben Sie „${!capital[@]}“ ein; tun
echo „Das Kapital von $key ist ${capital[$key]}“
erledigt
declare -AerklärenDas 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.
combined=("${array1[@]}" "${array2[@]}")
Dadurch werden alle Elemente aus beiden Arrays in einem neuen Array zusammengeführtcombined。
array1=("Apfel" "Banane")
array2=("cherry" "date")
kombiniert=("${array1[@]}" "${array2[@]}")
echo „Kombiniertes Array:“
für Element in „${combined[@]}“; tun
echo „$item“
erledigt
array1+=("${array2[@]}")
Das wirdarray2Inhalte werden direkt hinzugefügtarray1hinteren.
"${array[@]}"Formular, um zu verhindern, dass Elemente falsch erweitert werdenstr="Hallo Welt"
if [[ "$str" == hallo* ]]; dann
echo „String beginnt mit Hallo“
fi
veranschaulichen:verwenden[[ ]]Unterstützung des Schalenmustervergleichs,*Stellt ein beliebiges Zeichen dar.
if [[ "$str" =~ ^hello ]]; dann
echo „String beginnt mit Hallo“
fi
veranschaulichen: ^Zeigt den Anfang an,[[ ]]In=~ist ein regulärer Vorgang.
caseErzählenFall „$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.
expr(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.
[[ ]]Vergleichen[ ]Vollständigere Funktionen, deren Verwendung empfohlen wird=~Es können reguläre Ausdrücke verwendet werden, aber denken Sie daran, keine Anführungszeichen hinzuzufügen-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
! -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
-e: Ob die Datei oder das Verzeichnis existiert (egal welcher Typ)-f: Ob es sich um eine „allgemeine Datei“ handelt-d: Ob es sich um ein „Verzeichnis“ handelt-L: Ob es sich um einen „symbolischen Link“ handeltPATH_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
-e-doder-ftarget_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)
find: Unterverzeichnisse auflisten (keine Rekursion)-mindepth 1:Eigenes Verzeichnis ausschließen-maxdepth 1:Nur die erste Ebene auflisten-type d:Nur Verzeichnisse auflisten-print0übereinstimmenread -d $'\0': Behandeln Sie Pfade mit Leerzeichenfor dir in "${subdirs[@]}"; do
echo "$dir"
done
subdirs=( "$target_dir"/*/ )
Diese Schreibweise verwendet Platzhalter, um Unterverzeichnisse abzugleichen, kann jedoch weder Dateien ausschließen noch Leerzeichen und Sonderzeichen verarbeiten.
path="~/myfolder/file.txt"
realpath "$(eval echo "$path")"
path="~/myfolder/file.txt"
realpath "$(echo "$path" | sed "s|^~|$HOME|")"
path="~/myfolder/file.txt"
readlink -f "$(eval echo "$path")"
realpath "$(eval echo "$path")"
grep „Schlüsselwort“-Dateiname
grep -i „Schlüsselwort“-Dateiname
grep -n „Schlüsselwort“-Dateiname
grep -r Verzeichnispfad „Schlüsselwort“.
grep -o „Schlüsselwort“-Dateiname
grep -H „Schlüsselwort“-Dateiname
grep „Schlüsselwort 1“ Dateiname | grep „Schlüsselwort 2“
#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
#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“
grep -rin Verzeichnispfad „Schlüsselwort“.
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.
subdirs=()
while IFS= read -r -d $'\0' dir; do
subdirs+=("$dir")
done < <(find . -type d -print0)
-print0: Beenden Sie jedes Ergebnis mit einem Nullzeichen ohne Zeilenumbrüche.-d $'\0':readLesen Sie jeweils ein nullterminiertes ElementIFS=: Verhindern Sie, dass Leerzeichen als Feldtrennzeichen behandelt werden-r: Vermeiden Sie das Überspringen von Zeichen während der Verarbeitungtxt_files=()
while IFS= read -r -d $'\0' file; do
txt_files+=("$file")
done < <(find "$(pwd)" -type f -name "*.txt" -print0)
finden . -type f -print0 | while IFS= read -r -d $'\0' file; tun
echo „Verarbeitung: $file“
# your_command „$file“
erledigt
finden . -type d -print0 | while IFS= read -r -d $'\0' dir; tun
if [[ "$dir" == *" "* ]]; dann
echo „Verzeichnis mit Leerzeichen: $dir“
fi
erledigt
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.
-print0Undread -d $'\0'Der sicherste Weg, mit beliebigen Dateinamen umzugehen-0WarteszeneIn 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` 無法持續讀取。
-print0subdirs=()
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).
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.
für dir in „${subdirs[@]}“; tun
echo „Verzeichnis gefunden: $dir“
erledigt
mapfile -d '' -twird verarbeitet-print0Der sicherste und Bash-nativste Wegvar="line1
line2
line3"
while IFS= read -r line; tun
echo „Lesen: $line“
erledigt <<< „$var“
IFS=Vermeiden Sie beschnittene Leerzeichen-rVermeiden Sie, dass Escapezeichen analysiert werden<<<ist ein Here-String und behandelt den Variableninhalt als Eingabe für whileread -r first_line <<< „$var“
echo „Erste Zeile: $first_line“
readarray -t lines <<< "$var"
for line in "${lines[@]}"; do
echo "$line"
done
find . -mindepth 1 -maxdepth 1 -type d -name "abc*" -printf "%T@ %p\n" | sort -nr | cut -d' ' -f2-
-mindepth 1 -maxdepth 1: Nur Unterverzeichnisse unter dem aktuellen Verzeichnis auflisten-name "abc*": Name beginnt mit abc-printf "%T@ %p\n": Änderungszeit (Zeitstempel) und Verzeichnisnamen ausdruckensort -nr: Sortieren nach Zeitwert von neu nach altcut -d' ' -f2-: Zeitstempel entfernen und nur den Pfad anzeigen./abc_latest
./abc_old
./abc_2020
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
-printfExklusive Funktion für die GNU-Suche, Standard in macOSfindNicht unterstützt, verfügbargfindErsatz%T@Stellt die „Zeit der letzten Änderung (Sekunden)“ dar. Wenn Sie eine Zeit erstellen müssen, sind zusätzliche Werkzeuge erforderlich.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.
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.
mountAnweisung, um zu prüfen, ob der Mount schreibgeschützt istMNT="/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.
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.
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.
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.
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。
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。
„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。
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.
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.
Im Folgenden wird die Ausgabe als UTF-8-codiert gespeichertteeAnleitungsformat:
command | iconv -t utf-8 | tee -a output.txt
-tStellt „Zielkodierung“ dar.output.txtdokumentieren.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.
Win + Reingebencmdund drücken Sie die EingabetastecmdKann direkt von diesem Pfad aus geöffnet werdendir: Dateien und Ordner im aktuellen Verzeichnis anzeigencd: Zum Beispiel Verzeichnisse wechselncd C:\Userscls:Bildschirminhalt löschencopy: Zum Beispiel Dateien kopierencopy a.txt b.txtdel: Dateien löschenmkdir:Erstellen Sie einen neuen Ordnerrmdir: Ordner löschenecho: Beispielsweise Text ausgebenecho Helloexit: Eingabeaufforderungszeichen schließendir > file.txtErgebnisse in Datei ausgebendir | find "txt"Filter enthälttxtdas Ergebnis.batDie Datei führt mehrere Befehle gleichzeitig aussetVariablen anzeigen und festlegenipconfig /flushdnsodersfc /scannowWarten auf Anweisungen zur SystemwartungKann verwendet werden&、&&oder||Um die Anweisungen fortzusetzen:
cmd /k „Erster Befehl und zweiter Befehl“
&: Unabhängig davon, ob der erste erfolgreich ist oder fehlschlägt, wird der nächste ausgeführt.&&: Führen Sie den nächsten nur aus, wenn der erste erfolgreich ist||: Führen Sie den nächsten nur aus, wenn der erste fehlschlägtNach der ersten Anweisung hinzufügencall, können Sie mit der Ausführung einer weiteren Batchdatei fortfahren:
cmd /k „Erster Befehl & zweiter.bat aufrufen“
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.
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).
Vom System oder Benutzer festgelegte Variablen sind während der gesamten Betriebssystemsitzung verfügbar. Zum Beispiel:%PATH%、%TEMP%。
Umgebungsvariablen anzeigen:verwendensetBefehl.
set
Umgebungsvariablen festlegen/ändern (nur aktuelle CMD-Sitzung):
set MY_VAR=Hello
In der Batchdatei (.batoder.cmdDatei)setDie durch den Befehl definierten Variablen sind nur während der Ausführung dieser Batchdatei gültig.
im EinsatzforBeim Schleifen definierte Variablen, die zum Durchlaufen von Dateien, Ordnern oder numerischen Sequenzen verwendet werden. Wird normalerweise mit einem einzelnen Buchstaben und vorangestellten zwei Prozentzeichen benannt, zum Beispiel:%%A(in einer Batchdatei) oder ein einzelnes Prozentzeichen, zum Beispiel:%A(Bei direkter Ausführung über die Befehlszeile).
Parameter, die bei der Ausführung an die Batchdatei übergeben werden. Zum Beispiel:%1ist der erste Parameter,%2ist der zweite Parameter,%0Ist der Pfad und Name der Batchdatei selbst.
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
@echo aus
set MESSAGE=Dies ist eine Batch-Nachricht
echo%MESSAGE%
Pause
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. )
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
| 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. |
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.
grep, aber Sie können das integrierte verwendenfindDer Befehl erzielt einen ähnlichen Effekt.Befehl | „Stichwort“ findendir | „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
/I: Groß-/Kleinschreibung ignorieren, zum Beispielfind /I "error"/V: Zeilen anzeigen, die keine Schlüsselwörter enthalten/C: Zeigt nur die Anzahl der übereinstimmenden Zeilen anfindDie UND-Bedingung ist erfüllt:type log.txt | find "Error" | find "2025"
findstr:type log.txt | findstr /I "error warning fail"
findstrEs handelt sich um eine CMD-Version des erweiterten Suchtools, das mehrere Schlüsselwörter und reguläre Ausdrücke unterstützt.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“
~/.bash_profileoder~/.bashrc。AutoRunEinstellungen werden automatisch ausgeführt, wenn Inhalte vorhanden sind.HKEY_CURRENT_USER\Software\Microsoft\Command Processor
HKEY_LOCAL_MACHINE\Software\Microsoft\Command Processor
AutoRun, der Inhalt kann auf den auszuführenden Batchdateipfad festgelegt werden:AutoRun = "C:\Users\YourName\cmd_startup.bat"
%SystemRoot%\System32\cmd.exe /k "C:\Users\YourName\cmd_startup.bat"
/kFühren Sie die Batchdatei nach dem Start aus und lassen Sie das Fenster geöffnet.%AppData%\Microsoft\Windows\Start Menu\Programs\Startup
| 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 |
HKEY_CURRENT_USER\Software\Microsoft\Command Processorexistiert.AutoRunWenn Sie den Wert angeben, wird er automatisch erstellt und als angegebener Batchdateipfad festgelegt.@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
reg query: Wird verwendet, um zu überprüfen, ob der Anmeldeschlüssel oder -wert vorhanden ist.errorlevel: Kann verwendet werden, um zu bestimmen, ob das Abfrageergebnis erfolgreich ist (0 bedeutet vorhanden, 1 bedeutet nicht vorhanden).reg add: Erstellen Sie einen Anmeldeschlüssel oder -wert./f: Keine Aufforderung zur Zwangsdeckung.%AUTORUN_PATH%Ändern Sie es in den Batch-Dateipfad, den Sie beim Start von CMD automatisch ausführen möchten.@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
PSModulePathwird existierenCYGWINvariabel, oderSHELL=/bin/bashWin + XWählen Sie „Windows PowerShell“ oder „Windows Terminal“powershellKann direkt von diesem Pfad aus geöffnet werdenGet-ChildItem: Dateien und Ordner im aktuellen Verzeichnis auflisten (ähnlich wiedir)Set-Location: Verzeichnis wechseln (Abkürzungcd)Clear-Host:Bildschirminhalt löschen (Abkürzungcls)Copy-Item:Dateien oder Ordner kopierenRemove-Item: Dateien oder Ordner löschenNew-Item:Erstellen Sie eine neue Datei oder einen neuen OrdnerWrite-Output: Ausgabetext (Abkürzungecho)Exit:Schließen Sie PowerShellGet-Process | Where-Object {$_.CPU -gt 100}Get-ChildItem > file.txtls、cp、rmKann direkt verwendet werden$var = "Hello", Ausgabe$var.ps1Dateiausführung mehrerer BefehleGet-EventLog、Set-ExecutionPolicyWarten auf Anweisungen zur SystemwartungGet-Variable: Zeigt alle Variablen in der aktuellen PowerShell-Sitzung anGet-ChildItem variable:: Alle Variablen über den Variablentreiber anzeigen# 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:
variable:Kann beispielsweise als Pfad zur Manipulation von Variablen verwendet werdenGet-Content variable:PATHWhere-Object,Zum Beispiel:Get-Variable | Where-Object { $_.Name -like "P*" }Nur Variablen anzeigen, die mit P beginnenPrä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.
Wird verwendet, um den Inhalt anderer Dateien in die aktuelle Datei einzufügen.
#include <filename>: Wird zum Einschließen von Standardbibliotheks-Headerdateien verwendet. Der Präprozessor sucht nach Dateien im Standard-System-Header-Dateipfad des Compilers.#include "filename": Wird zur Aufnahme benutzerdefinierter Header-Dateien verwendet. Der Präprozessor durchsucht zunächst das Verzeichnis der aktuellen Quellcodedatei und dann den Systempfad.#include <iostream> // Die Standard-E/A-Bibliothek einbinden
#include "my_utility.h" // Benutzerdefinierte Header-Datei einschließen
Literales Ersetzungsmakro, das zum Definieren symbolischer Konstanten oder Codefragmente verwendet wird.
#define: Makro definieren.#undef: Makro aufheben.#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;
}
Ermöglicht Ihnen die Entscheidung, ob ein bestimmter Codeblock basierend auf dem Wert eines Präprozessormakros kompiliert werden soll.
#ifdef: Wenn das Makro definiert ist, kompilieren Sie nachfolgende Blöcke.#ifndef: Wenn das Makro nicht definiert ist, kompilieren Sie nachfolgende Blöcke. (wird häufig in Include Guard verwendet)#if: Bestimmen Sie, ob basierend auf dem Wert des angegebenen konstanten Ganzzahlausdrucks kompiliert werden soll.#else / #elif: Ersetzung oder nachträgliche Beurteilung der bedingten Kompilierung.#endif: Beenden Sie den bedingten Kompilierungsblock.#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
#error: Zwingt den Präprozessor, die Kompilierung zu stoppen, wenn er auf diese Direktive stößt, und zeigt die angegebene Fehlermeldung an.#warning: Gibt die angegebene Warnmeldung aus, ohne die Kompilierung zu stoppen (keine Standardanweisung, wird aber von vielen Compilern unterstützt).#ifndef VERSION_DEFINED
#error „Versionsnummernmakro VERSION_DEFINED muss definiert werden!“
#endif
#pragma: Wird zum Senden spezieller Anweisungen an den Compiler verwendet. Das Verhalten hängt stark vom Compiler ab (z. B.#pragma onceUnd#pragma warning)。#line: Wird verwendet, um die aktuelle Zeilennummer und den Dateinamen zu ändern, die angezeigt werden, wenn der Compiler Fehler oder Warnungen meldet.#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.
Im C/C++-Standard traditionell durch die VerwendungWache einbeziehenUm den Zweck zu erreichen, eine wiederholte Einbeziehung zu verhindern.#pragma onceBietet eine sauberere Alternative.
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.
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.
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 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.
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:
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
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
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 ): Speichern Sie den aktuellen Stapelstatus der Warneinstellungen.#pragma warning( pop ):Auf die neueste Version wiederherstellenpushDer gespeicherte Zustand.#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
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
4996)JaCompiler-spezifisch. Sie müssen die richtige Nummer für den von Ihnen verwendeten Compiler suchen (z. B. MSVC).#pragma warningFunktionen, aber sie bevorzugen im Allgemeinen die Verwendung-W...Befehlszeilenflags oder spezielle#pragma GCC diagnosticStruktur zur Steuerung von Warnungen.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.
Die meisten Funktionen der C++-Standardbibliothek befinden sich instd::innerhalb des Namensraums. Zu den Hauptkategorien und Funktionen gehören:
std::cout: Standard-Ausgabe-Streaming-Objekt, das zum Drucken von Daten auf der Konsole verwendet wird.std::cin: Standard-Eingabestreamobjekt, das zum Lesen von Daten aus der Konsole verwendet wird.std::endl: Zeilenumbrüche ausgeben und den Puffer leeren.std::ifstream / std::ofstream: Datei-Eingabe-/Ausgabe-Streaming.Sammlungskategorien, die zum Speichern von Daten verwendet werden:
std::vector:Ein Array mit dynamischer Größe.std::list: Zwei-Wege-Verbindungssequenz.std::map: Eine sortierte Sammlung von Schlüssel-Wert-Paaren (Rot-Schwarz-Baum-Implementierung).std::unordered_map: Eine ungeordnete Sammlung von Schlüssel-Wert-Paaren (Hash-Tabellen-Implementierung).std::set: Eine sortierte Sammlung eindeutiger Schlüsselwerte.std::string: Kategorie, die zur Verarbeitung von Zeichenfolgen verwendet wird.Eine Reihe allgemeiner Funktionen für Container- und Bereichsoperationen:
std::sort: Elemente innerhalb des Bereichs sortieren.std::find: Suchen Sie den angegebenen Wert innerhalb des Bereichs.std::copy: Kopiert Elemente von einem Bereich in einen anderen.std::shared_ptr / std::unique_ptr: Intelligente Indikatoren für die automatisierte Speicherverwaltung.std::thread: Wird für die Multithread-Programmierung verwendet.std::function: Universeller Funktions-Wrapper.std::pair / std::tuple: Vorlage zum Speichern einer festen Anzahl von Werten unterschiedlichen Typs.zugreifenstd::Es gibt zwei Hauptmethoden für Entitäten in einem Namespace:
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;
}
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.
In C++,std::stringIst eine Kategorie (Klasse). Wenn Sie astd::stringWenn einer Variablen kein Anfangswert zugewiesen wird, ruft sie den Standardkonstruktor auf.
"")。0。NULLIndikator, sondern ein gültiges Objekt.#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: ''
}
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;
}
}
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 |
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
}
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“
}
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“
}
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)
}
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;
}
| 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 |
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;
}
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;
}
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"));
}
| 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. |
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.
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;
}
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;
}
}
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.
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.
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;
}
std::stringstream ss(input_str): Diese Kategorie behandelt die Eingabezeichenfolge als Eingabestream (Eingabestream) und ihre Funktion ähnelt der beim Lesen aus einer Datei.std::ifstream。>>):
while (ss >> token): Dies ist eine idiomatische C++-Stream-Leseschleife. Solange der Stream die Daten erfolgreich extrahiert und speicherttokenVariable, wird die Schleife weiter ausgeführt.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;
}
std::arrayIst eine Containerklasse in der C++-Standardbibliothek, die für Situationen geeignet ist, in denen die Größe zur Kompilierungszeit festgelegt wird.std::arrayBietet mehr Funktionalität und Sicherheit.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.
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)。
std::vector: **Bevorzugt**std::array: **Bevorzugt**#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;
}
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).
std::vector: anwendbar, verwendensize()Holen Sie sich die Grenzen.std::array: anwendbar, verwendensize()Holen Sie sich die Grenzen.#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).
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.
std::vector: **Empfohlen** (wenn STL-Algorithmus oder spezifische Steuerung erforderlich ist)std::array: **Empfohlen** (wenn STL-Algorithmus erforderlich ist)#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;
}
| 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. |
std::array<std::array<std::array<float, 2>, 2>, 2> twoLines;
std::array<std::array<std::array<float, 2>, 2>, 2> twoLinesCopy;
std::arrayUnterstützt das vollständige Kopieren von flachen zu tiefen Ebenen, sodass es direkt verwendet werden kann=:
twoLinesCopy = twoLines;
std::copy(twoLines.begin(), twoLines.end(), twoLinesCopy.begin());
std::memcpy(&twoLinesCopy, &twoLines, sizeof(twoLines));
twoLinesCopy = twoLines;std::copyGeeignet für Anwendungen, die generische STL-Methoden erfordern.memcpyGilt nur für POD (Plain Old Data) und keine Konstruktor-/Dekonstruktorlogik.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.
Wenn ein C++-Programm versucht, auf ungültigen Speicher zuzugreifen, zum Beispiel:
nullptrder Erinnerung.deleteoderfreeFreier 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.
#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;
}
Der beste Ansatz besteht darin, das Auftreten solcher Fehler während der Entwurfsphase Ihres Codes zu verhindern, anstatt zu versuchen, sie abzufangen:
std::vectorUndstd::string,verwendenat()stattdessen eine Memberfunktion verwenden[]Operator. Wannat()Wenn der Wert außerhalb der Grenzen liegt, wird eine C++-Ausnahme ausgelöststd::out_of_range, kann standardisiert werdentry-catcherfassen.std::unique_ptr, std::shared_ptr), um den Speicherlebenszyklus zu automatisieren. Dereferenzieren Sie niemalsnullptrund prüft, ob der Zeiger gültig ist, bevor er dereferenziert wird.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;
}
}
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)。
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.
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.
#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;
}
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:
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;
}
}
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;
}
}
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.
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.
System::ArgumentOutOfRangeExceptionBevor 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!");
}
| 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. |
nums[i]Vorher bestätigeni < nums->Count。int value = (nums->Count > 1) ? nums[1] : 0;
System::Linq), können Sie verwendenElementAtOrDefault(1), der den Standardwert des Typs (0 für int) zurückgibt, wenn der Index nicht vorhanden ist.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;
}
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.
floatDer Maximalwert (ungefähr 3,4 $ \times 10^{38}$).doubleder Maximalwert.intder Maximalwert.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();
}
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;
}
}
| 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. |
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。
Ab C++20 ist die Standardbibliothek<numbers>Präzise und typsichere mathematische Konstanten werden in der Header-Datei bereitgestellt.
#include <numbers>#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;
}
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.
#include <cmath>(oder<math.h>)#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
}
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)$).
#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;
}
std::numbers::pi。const double PI = 3.14159...;M_PIMakro, aber seien Sie sich seiner nicht standardmäßigen Natur bewusst.#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;
}
values->Count - 1。Schlüssel 1: Standardabweichung = 0,8981 Schlüssel 2: Standardabweichung = 1,1180 Schlüssel 3: Keine Informationen
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
}
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
});
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;
});
}
std::sortKein einzelner Sortieralgorithmus, sondern ein Hybridalgorithmus, der die Vorteile jedes Algorithmus kombiniert und das Worst-Case-Szenario vermeidet. Seine Funktionslogik ist wie folgt:
| 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。 |
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。
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;
}
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;
}
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) |
aoderbWenn es 0 ist, wird empfohlen, einen Mindestwert zu verwenden (z. B1e-6) zum Vergleich, um Genauigkeitsprobleme zu vermeiden.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.
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;
}
}
Aus der Steigungsformel $m = -\frac{a}{b}$:
| 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. |
Bei der Beurteilung der Punkt-zu-Linie-Position wird empfohlen, zunächst diese Prüfung durchzuführen:
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.
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, zint、floatoderdouble。
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
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
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);
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.
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
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.
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.
.hDie Datei erklärt nur die Existenz der Kategorie der anderen Partei und enthält nicht direkt die Header-Datei der anderen Partei..cppDie Datei enthält die Header-Dateien der anderen, sodass der Compiler die vollständige Klassendefinition erhalten kann.// 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
#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
#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;
}
}
#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();
}
}
ClassA.hUndClassB.hverwenden wir Vorwärtsdeklarationen nur, um die Existenz der anderen Kategorie anzuzeigen, um Zirkelverweise zu vermeiden..cppDas Archiv enthält die Header-Datei der anderen Partei und stellt so sicher, dass bei Verwendung des Indikators die vollständige Kategoriedefinition der anderen Partei erhalten wird.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.
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。
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。
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.
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.
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;
}
std::ifstream: geerbt vonstd::istream, speziell zur Verarbeitung von Dateieingabeströmen verwendet. zum Zeitpunkt der Erstellung (oder Verwendung).open()Funktion) wird versuchen, die Datei zu öffnen.input_file.is_open(): Dies ist die Standardfehlerprüfung. Wenn die Datei nicht existiert oder das Programm keine Leseberechtigung hat, wird diese Funktion zurückgegebenfalse。std::getline(stream, string):
input_file), um Daten zu lesen.std::stringGegenstände, wie zline)Mitte.\n,daherlineDie Variable enthält keine Newline-Zeichen.true。std::ifstreamObjekt (input_file) zerstört wird, ruft es automatisch seinen Destruktor auf, um den zugrunde liegenden Dateisteuerungscode zu schließen. Dies ist eine zuverlässige Methode zur Ressourcenverwaltung (RAII, Resource Acquisition Is Initialization).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:
std::setw(width): Legen Sie die Mindestbreite des nächsten Ausgabefelds fest.std::left / std::right: Legen Sie die Ausrichtung des Textes in der Spalte fest (links oder rechts).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;
}
std::ofstream: Streaming-Kategorie für die Dateiausgabe. Wird zum Schreiben von Daten in Dateien verwendet.#include <iomanip>: Diese Header-Datei muss enthalten sein, um den I/O-Stream-Manipulator zu verwenden.output_file << left;:
rightoderinternalAbdeckung.output_file << setw(column_width) << token;:
setw(width): Legen Sie die Mindestbreite der als nächstes auszugebenden Daten fest. Wenn die Länge des Ausgabestrings kleiner als die eingestellte Breite ist, wird er mit Leerzeichen aufgefüllt.setwNur gültig für den nächsten Ausgabevorgang, der unmittelbar darauf folgt, daher muss er einmal vor jedem Ausgabetoken aufgerufen werden.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
Nach dem Herunterladen müssen Sie das Skript ausführen, um die ausführbare Datei von vcpkg zu kompilieren, die generiert wirdvcpkg.exe:
.\bootstrap-vcpkg.bat./bootstrap-vcpkg.shDieser Schritt ermöglicht es Entwicklungstools (wie Visual Studio), die von vcpkg installierten Pakete automatisch zu erkennen:
implementieren.\vcpkg integrate install. Nach Abschluss kann das neue Projekt, das Sie in VS erstellen, direkt erstellt werden#includeKit, der Pfad muss nicht manuell festgelegt werden.
Fügen Sie beim Ausführen der CMake-Konfiguration die folgenden Parameter hinzu, um eine Verknüpfung mit der vcpkg-Toolchain-Datei herzustellen:
-DCMAKE_TOOLCHAIN_FILE=[vcpkg-Pfad]/scripts/buildsystems/vcpkg.cmake
| 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 |
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。
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.
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.
| Sprache | Anwendbare Situationen | Bemerkung |
|---|---|---|
| Python | Schnelle Entwicklung, Testautomatisierung | Gilt für Seriell, USB HID |
| C/C++ | Entwicklung eingebetteter Steuerungen und Treiber | Zugriff auf Low-Level-Speicher und Hardware |
| C# | Windows-Benutzeroberfläche + Steuergerät | Geeignet für COM-Port und USB-Kommunikation |
| Java | Plattformübergreifende Steuerung | Wird bei Low-End-Geräten seltener verwendet |
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()
SerialPort-Port = neuer SerialPort("COM4", 9600);
port.Open();
port.WriteLine("MOVE 100");
String-Antwort = port.ReadLine();
Console.WriteLine("Response: " + Antwort);
port.Close();
libusb(C)、pyusb(Python)、HidSharp(C#) und andere FunktionsbibliothekenSocket 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()
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.
// 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);
}
}
}
<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 | Empfohlenes Set | Ist es kostenlos? |
|---|---|---|
| Android | ZXing / ML Kit | Ja |
| Web | QuaggaJS / jsQR | Ja |
| Windows | Dynamsoft / ZXing.NET | Dynamsoft für kommerzielle Nutzung |
| Python | ZBar / pyzbar | Ja |
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-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.
Das folgende Format kann beispielsweise Steuercodes kodieren:
Einige Barcode-Generatoren ermöglichen die Einbettung von Sonderzeichen, wie zum Beispiel:
\x0Dbedeutet Enter\x03bedeutet Strg-C^C、[CTRL+C]Die spezielle Syntax hängt vom Tool abDie meisten professionellen Barcodedrucker (z. B. Zebra, Honeywell) sind werkseitig voreingestelltSteuercodeausgabe deaktivieren, muss über die vom Scanner bereitgestellten „Einstellungen Barcode“ aktiviert werden:
Zum Beispiel in einer Windows-Anwendung:
keydownUndCtrlPassende Tastenkombinationsverarbeitung.Codierung von ASCII 3 mit Code128:
Eingabe:\x03Hallo Welt
Nachdem der Barcode gescannt wurde, wird Strg+C ausgelöst und „Hello World“ ausgegeben.
sudo apt update && sudo apt upgrade -y
sudo apt install -y wget curl unzip zip git ca-certificates
sudo apt install -y openjdk-17-jdk
sudo dpkg -i ~/Downloads/android-studio-*.deb || sudo apt -f install -y
android-studiooder dekomprimieren.tar.gz:
tar -xzf ~/Downloads/android-studio-*.tar.gz -C ~
~/android-studio/bin/studio.sh
sudo apt install -y android-sdk-platform-tools
adb kill-server
adb start-server
adb devices
sudo dpkg -i ~/Downloads/code_*.deb || sudo apt -f install -y
sudo apt update && sudo apt install -y openjdk-17-jdk unzip git
wget https://dl.google.com/android/repository/commandlinetools-linux-11076708_latest.zip
unzip commandlinetools-linux-*_latest.zip -d ~/android-sdk
~/.bashrcoder~/.zshrc):
export ANDROID_SDK_ROOT=$HOME/android-sdk
export PATH=$ANDROID_SDK_ROOT/cmdline-tools/bin:$ANDROID_SDK_ROOT/platform-tools:$PATH
sdkmanager "platform-tools" "platforms;android-34" "build-tools;34.0.0"
adb devicesSehendeviceDer Test kann nun bereitgestellt werden.adb installoder Framework-CLI (z. Bflutter run) Stellen Sie die App auf dem Mobiltelefon bereit.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.
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>
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!");
}
});
}
}
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!“.
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" />
if (ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION)
!= PackageManager.PERMISSION_GRANTED) {
ActivityCompat.requestPermissions(this,
new String[]{Manifest.permission.ACCESS_FINE_LOCATION}, 1);
}
LocationManager locationManager = (LocationManager) getSystemService(Context.LOCATION_SERVICE);
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);
}
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);
}
});
}
Um eine Sprachassistentenfunktion wie Siri oder Hey Google zu implementieren, müssen Sie die folgenden Komponenten kombinieren:
<uses-permission android:name="android.permission.RECORD_AUDIO"/>
<uses-permission android:name="android.permission.INTERNET"/>
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);
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);
}
});
Wenn Sie den Hintergrund beibehalten und per Stimme aktivieren möchten, müssen Sie Folgendes verwenden:
RECORD_AUDIOBerechtigungen.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.
SpeechRecognizerLanger Hintergrundbetrieb.SpeechRecognizerErkennen Sie vollständige Sprachbefehle.Ö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;
}
}
NotificationChannel channel = new NotificationChannel("voice_channel",
"Voice Assistant", NotificationManager.IMPORTANCE_LOW);
NotificationManager manager = getSystemService(NotificationManager.class);
manager.createNotificationChannel(channel);
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();
Intent serviceIntent = new Intent(this, VoiceService.class);
ContextCompat.startForegroundService(this, serviceIntent);
RECORD_AUDIOBerechtigungen.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.
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).
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.
Die iOS-Entwicklung verwendet hauptsächlichXcode, die offizielle integrierte Entwicklungsumgebung (IDE) von Apple.
Das Erlernen der iOS-Entwicklung erfordert die Beherrschung der folgenden Grundlagen:
Hier sind einige hilfreiche Lern- und Entwicklungsressourcen:
Xcode ist eine von Apple bereitgestellte integrierte Entwicklungsumgebung (IDE) für die Entwicklung von macOS-, iOS-, watchOS- und tvOS-Anwendungen.
Sie können die neueste Version von Xcode aus dem Mac App Store oder der offiziellen Entwickler-Website von Apple herunterladen.
Praktische Tipps zur Verbesserung der Entwicklungseffizienz:
Verwandte Lern- und Referenzressourcen:
Swift ist Apples moderne Programmiersprache für die Entwicklung von iOS-, macOS-, watchOS- und tvOS-Apps.
varUndlet?Und!Behandelt das Vorhandensein oder Fehlen eines Wertsif、switch、for、whilefuncDefinition, unterstützt Parameterbezeichnungen und mehrere RückgabewerteclassUndstructSwift ist nicht nur für das Apple-Ökosystem gedacht, es kann auch für serverseitige Entwicklung und plattformübergreifende Tools verwendet werden.
Verwandte Lern- und Referenzressourcen:
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.
Die Syntax von Objective-C kombiniert die Funktionen von C und Smalltalk und verwendet das @-Symbol, um Spracherweiterungen anzuzeigen.
@interfaceUnd@implementation[object method]@propertyUnd@synthesizeDie Objective-C-Entwicklung erfolgt hauptsächlich mit Apples Xcode.
Hier sind einige Ressourcen zum Lernen und Nachschlagen:
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.
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.
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.
| 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. |
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 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 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 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 ist eine Ingenieursdisziplin, die Software systematisch und geplant entwickelt, betreibt und wartet. Ziel ist der Aufbau qualitativ hochwertiger, wartbarer, zuverlässiger und anspruchsvoller Softwaresysteme.
Bitte geben Sie den offiziellen Namen dieses Projekts ein.
Erläutern Sie den Grund für dieses Projekt, Hintergrundthemen und zu lösende Kernthemen und definieren Sie klare Projektziele.
Skizzieren Sie die Systemfunktionen und die Gesamtarchitektur, die mit dem Systemarchitekturdiagramm gepaart werden können.
Sie können Hauptbildschirmskizzen oder Wireframes anhängen, um die Elemente und interaktiven Prozesse jedes Bildschirms zu beschreiben.
Listen Sie die Hauptstruktur, Felder, Korrelationen usw. der Datentabelle auf.
Listen Sie externe Systeme, APIs oder andere Softwarekomponenten auf, die integriert werden müssen.
Listen Sie potenzielle Risiken und Einschränkungen auf (z. B. Budget, Arbeitskräfte, Technologie usw.).
Links zu verwandten Dokumenten, Referenzmaterialien, Begriffsdefinitionen usw.
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.
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.
git init:Initialisieren Sie die VersionsbibliothekGit-Klon [URL]:Remote-Projekt kopierengit add [Datei]:Änderungen zum Staging-Bereich hinzufügengit commit -m „Nachricht“: Änderungen übermittelngit push: Änderungen an das Remote-Repository übertragengit pull: Remote-Änderungen abrufen und zusammenführengit branch: Zweige anzeigen oder erstellengit merge: Zweige zusammenführenGit 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.
git --versionum zu bestätigen, dass die Installation erfolgreich war.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]“
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
git initodergit clone)git add)git commit)git push / git pull)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.
Stellen Sie zunächst sicher, dass Ihr lokaler Index mit dem neuesten Fortschritt auf der Remote-Seite aktualisiert wird:
git fetch --all
verwenden--hardDer Parameter verweist den aktuellen Zweig auf den entsprechenden Remote-Zweig (vorausgesetzt, Ihr Zweig ist der Hauptzweig):
git reset --hard origin/main
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:
# 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
| 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 |
git reset --hardist eine gefährliche Operation. Nach der Ausführung wird der gesamte lokale, nicht festgeschriebene Code ausgeführtAbruf nicht möglich。origin/mainErsetzen Sie ihn durch den tatsächlichen Remote-Zweignamen, den Sie derzeit verwenden (z. B.origin/masteroderorigin/dev)。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.
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.
Wenn die Datei widersprüchliche Tags enthält, können Sie die Unterschiede mit den folgenden Methoden anzeigen:
git diff<<<<<<<、=======Und>>>>>>>markieren.git diff --ours <file>git diff --theirs <file>
git diff -p <file>
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
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).
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:
<<<<, ====, >>>>markieren.git add <file>(Fügen Sie die aufgelöste Datei zum temporären Speicherbereich hinzu.)git commit(Merge-Commit abschließen).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.
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.
git pull --rebasegit 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.
git pull --rebase
--rebase?--rebaseSie können Ihren Commit-Verlauf übersichtlich halten, ohne redundante Merge-Commits.Angenommen, Sie übernehmen einige Änderungen lokal und es gibt neue Festschreibungen auf der Remote-Seite, verwenden Siegit pull --rebasetreffen:
Wenn beim Wiedergeben eines lokalen Commits ein Konflikt auftritt, fordert Git zur manuellen Konfliktlösung auf:
git addBühnenaufgelöste Dateien.git rebase --continueSpielen Sie den Commit weiter ab.git rebase --abortZurück zum Status Quo.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.
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:
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. |
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.
Benutzername/Repository-Name)。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.
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:
rm -rf <Ordnername>
rd /s /q <Ordnername>
---
| 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) |
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.
git --version
git version 2.x.x, bedeutet, dass es installiert wurde; Wenn „Unrecognized git command“ angezeigt wird, müssen Sie Git installieren.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.
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.
Sobald die Einstellungen abgeschlossen sind, können Sie die folgenden Vorgänge direkt in Visual Studio ausführen:
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.
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.
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.
So installieren Sie CMake auf verschiedenen Betriebssystemen:
brew install cmake. Sie können die .dmg-Datei auch herunterladen und manuell installieren.sudo apt update && sudo apt install cmake。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.
| 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. |
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.
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.
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.
# 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
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.
Docker Pull [Bildname]: Bilddatei herunterladenDocker Run [Bildname]: Ausführungscontainerdocker ps: Ausführende Container anzeigenDocker Stop [Container-ID]: Stoppen Sie den Containerdocker rm [Container-ID]: Container löschendocker build -t [Name] .: Erstellen Sie eine Bilddatei basierend auf Dockerfiledocker images: Bilddateiliste anzeigen# 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 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
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.
| 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. |
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.
| 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. |
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 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.
api-ms-win-*Virtuelle DLLs, die mit beginnen, erzeugen keine falschen Warnungen zu zirkulären Abhängigkeiten oder Fehler bei fehlenden Dateien.| 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++) |
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.
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.
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:
| 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. |
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:
NAME NOT FOUNDDatensätze, die Ihnen genau sagen können, wo das Programm die DLL nicht gefunden hat.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 Code、JetBrainsIn anderen gängigen Entwicklungsumgebungen analysiert es Kommentare und Kontext, um sofort Codezeilen oder ganze Funktionen vorzuschlagen.
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.
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 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.
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.
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.
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.
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.
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.
Solche Tools integrieren Agentenfunktionen in den Editor, um eine intuitivere visuelle Entwicklungserfahrung zu ermöglichen.
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.
| 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. |
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.
Claude Code erfordert die Node.js 18+-Umgebung, die mit den folgenden Methoden installiert werden kann:
npm install -g @anthropic-ai/claude-code
claudeJetzt können Sie den interaktiven Modus starten.| 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)。 |
/help: Zeigt alle verfügbaren Befehle und Anweisungen an./clear: Den aktuellen Konversationsverlauf löschen und den Kontextraum zurücksetzen./stats: Aktuelle Token-Nutzungs- und Ausgabenstatistiken anzeigen./doctor: Diagnostizieren Sie, ob der Installationsstatus normal ist./compact: Konversationsinhalte manuell komprimieren, um Platz zu sparen.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.
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:
--auto-accept, wodurch das Tool die vorgeschlagenen Anweisungen automatisch ausführt, ohne nachzufragen. Beachten Sie jedoch, dass dies bei der Ausführung destruktiver Anweisungen wie z. B. nicht möglich istrm).claude --auto-accept
/approve-all, wodurch vorübergehend volle Vertrauenswürdigkeit für nachfolgende Vorgänge in der aktuellen Sitzung gewährt wird.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:
claude . /path/to/another/project
@Und fügen Sie den absoluten Pfad zur externen Datei ein und fügen Sie deren Inhalt in den Kontext ein:Bitte helfen Sie mir, auf die Einstellungen von @/etc/nginx/nginx.conf zu verweisen, um das aktuelle Projekt zu ändern.
ln -s /path/to/external_dir ./external_dir
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'
--auto-acceptSpäter führt Claude möglicherweise Shell-Befehle aus, die Sie nicht überprüft haben. Es wird empfohlen, es nur in einer vertrauenswürdigen Projektumgebung zu verwenden.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.
Wenn Sie nicht ausführen möchtenls、mkdirOder wenn Sie beim Bearbeiten einer Datei immer wieder auf „OK“ klicken, können Sie die folgenden gefährlichen Parameter verwenden:
--dangerously-skip-permissions--allow-dangerously-skip-permissions--permission-mode bypassPermissionsverwenden.Standardmäßig kann Claude nur das Verzeichnis lesen und schreiben, in dem es gestartet wird. Um auf andere Pfade zuzugreifen, verwenden Sie--add-dir:
claude --add-dir <path>
claude --add-dir ../another-project --add-dir /var/logWenn 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
| 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. |
--dangerously-skip-permissionsZerstörerisch. Wenn Claude den Befehl falsch einschätzt (z. B. versehentlich eine Datei löscht), wird das System ihn nicht abfangen.rootodersudoDie Ausführung dieses Parameters mit einer Identität kann aufgrund von Sicherheitsmechanismen blockiert sein. Es wird empfohlen, es mit allgemeinen Benutzerrechten auszuführen.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.
Rufen Sie die KI direkt im Code-Editor auf:
Cmd + K(Windows fürCtrl + K)。Chat-Dialog in der Seitenleiste:
Cmd + LÖffnen Sie das Chatfenster.@Files、@Codebaseoder@Webum den Bereich der AI-Referenz anzugeben.Dies ist der leistungsstärkste „Agent“-Modus von Cursor:
Cmd + IStarten Sie Composer.| 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. |
Cmd + KLassen Sie sich von der KI beim Schreiben komplexer Shell-Anweisungen unterstützen.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
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:
export ANTHROPIC_API_KEY=your-keysetx ANTHROPIC_API_KEY your-keyGeben Sie nach Abschluss der Einstellung das Terminal einaiderDadurch wird die Konversationsoberfläche geöffnet.
Aider liest und ändert nur Dateien, die Sie angeben, um dem Kontext beizutreten, um Token-Kosten zu sparen und die Genauigkeit zu verbessern:
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 | 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 unterstützt mehrere Möglichkeiten zur Schnittstelle mit lokal ausgeführten kostenlosen und Open-Source-Modellen. Die gebräuchlichste Methode ist die VerwendungOllama、LM 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.
Dies ist derzeit die einfachste und gängigste Lokalisierungslösung:
ollama pull deepseek-coder-v2(Oder wählen Sie ein Modell, das für Programme wie Qwen2.5-Coder optimiert ist).--modelDer Parameter gibt den Ollama-Modellpfad an.aider --model ollama/deepseek-coder-v2
| 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. |
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:
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.
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.
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.
Nicht offengelegte Programmierdetails, Algorithmen, Datenbankstrukturen usw. sind Geschäftsgeheimnisse. Das Unternehmen sollte es durch Vertraulichkeitsvereinbarungen, Informationsmanagementsysteme usw. schützen.
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.
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.
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.
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.
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.
Softwarenamen und Logos können als Marken eingetragen werden, um Produkte aus unterschiedlichen Quellen zu unterscheiden und Marktverwechslungen zu vermeiden.
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.
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.
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.
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.
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:
| 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]