0Pricing
C Academy · Lektion

Eingaben tokenisieren

Wandeln Sie Text in Tokens um.

Eingaben tokenisieren ist eine kostenlose C Academy-Lektion auf CoddyKit. Dies ist Lektion 1 von 4. Du kannst die komplette Lektion unten kostenlos lesen – dann übst du sie direkt im Browser mit einem integrierten Code-Editor und einem KI-Tutor rund um die Uhr. Sie ist Teil des C Academy-Lernpfads, und dein Fortschritt wird über Web und CoddyKit-App synchronisiert. Der C Academy-Kurs umfasst insgesamt 4 Lektionen.

Was ist ein Tokenizer?

Ein Interpreter beginnt damit, rohen Text in Tokens umzuwandeln – die kleinsten bedeutungstragenden Einheiten. Für die Zeichenfolge 3 + 4 * 2 gibt der Tokenizer (oder Lexer) Zahlen und Operatoren aus.

Diese Phase entfernt Leerraum und klassifiziert jede Zeichengruppe, sodass der Parser nie mit rohen Bytes arbeiten muss.

Ein Token-Typ

Wir modellieren jedes Token mit einem Enum-Tag und einer Nutzlast. Zahlen enthalten einen Integerwert; für Operatoren und Klammern genügt ihre Art.

Wenn der Wert in der Struct gespeichert wird, muss der Quelltext später nicht erneut durchsucht werden.

typedef enum {
  TOK_NUM, TOK_PLUS, TOK_MINUS,
  TOK_STAR, TOK_SLASH,
  TOK_LPAREN, TOK_RPAREN, TOK_EOF
} TokKind;

typedef struct {
  TokKind kind;
  int value; /* used when kind == TOK_NUM */
} Token;

Scanposition

Der Lexer durchläuft die Quelle mit einem Cursorzeiger. Eine kleine Hilfsfunktion sieht sich das aktuelle Zeichen an, ohne es zu verbrauchen, und gibt am Ende '\0' zurück.

Zeigerarithmetik hält den Scanner schnell und einfach.

static const char *src;

static char peek(void) {
  return *src;
}

static char advance(void) {
  return *src++;
}

Leerraum überspringen

Bevor wir ein Token lesen, verwerfen wir Leerzeichen und Tabulatoren. Das standardmäßige isspace aus <ctype.h> verarbeitet jedes Leerraumzeichen.

Zeilenumbrüche gelten hier als Leerraum, daher kann sich der Ausdruck über mehrere Zeilen erstrecken.

#include <ctype.h>

static void skip_ws(void) {
  while (isspace((unsigned char)peek()))
    advance();
}

Eine Zahl lexen

Wenn der Cursor auf einer Ziffer steht, sammeln wir aufeinanderfolgende Ziffern zu einer Ganzzahl. Durch Multiplizieren mit zehn und Addieren jeder Ziffer wird der Wert von links nach rechts aufgebaut.

Die Schleife endet beim ersten Zeichen, das keine Ziffer ist, und lässt den Cursor für das nächste Token bereit.

static int lex_number(void) {
  int n = 0;
  while (isdigit((unsigned char)peek())) {
    n = n * 10 + (advance() - '0');
  }
  return n;
}

Die Funktion next_token

Die zentrale Routine überspringt Leerraum und verzweigt anschließend anhand des aktuellen Zeichens. Ziffern werden zu einem TOK_NUM; jeder Operator wird seiner eigenen Art zugeordnet.

Wenn das abschließende NUL erreicht wird, entsteht ein TOK_EOF als Signal zum Beenden.

static Token next_token(void) {
  skip_ws();
  char c = peek();
  if (c == '\0') return (Token){TOK_EOF, 0};
  if (isdigit((unsigned char)c))
    return (Token){TOK_NUM, lex_number()};
  advance();
  switch (c) {
    case '+': return (Token){TOK_PLUS, 0};
    case '-': return (Token){TOK_MINUS, 0};
    case '*': return (Token){TOK_STAR, 0};
    case '/': return (Token){TOK_SLASH, 0};
    case '(': return (Token){TOK_LPAREN, 0};
    case ')': return (Token){TOK_RPAREN, 0};
  }
  return (Token){TOK_EOF, 0};
}

Den Lexer ausführen

Hier sehen Sie ein vollständiges Programm, das einen Ausdruck in Tokens zerlegt und die Art jedes Tokens ausgibt. Bei Zahlen wird zusätzlich der Wert ausgegeben.

Beachten Sie, dass die Schleife endet, sobald sie TOK_EOF liest.

#include <stdio.h>
#include <ctype.h>

typedef enum { TOK_NUM, TOK_PLUS, TOK_STAR, TOK_EOF } TokKind;
typedef struct { TokKind kind; int value; } Token;

static const char *src;
static char peek(void){ return *src; }
static char advance(void){ return *src++; }

static Token next_token(void){
  while (isspace((unsigned char)peek())) advance();
  char c = peek();
  if (c=='\0') return (Token){TOK_EOF,0};
  if (isdigit((unsigned char)c)){
    int n=0; while(isdigit((unsigned char)peek())) n=n*10+(advance()-'0');
    return (Token){TOK_NUM,n};
  }
  advance();
  if (c=='+') return (Token){TOK_PLUS,0};
  return (Token){TOK_STAR,0};
}

int main(void){
  src = "12 + 3 * 4";
  Token t;
  do {
    t = next_token();
    if (t.kind==TOK_NUM) printf("NUM %d\n", t.value);
    else if (t.kind==TOK_PLUS) printf("PLUS\n");
    else if (t.kind==TOK_STAR) printf("STAR\n");
    else printf("EOF\n");
  } while (t.kind != TOK_EOF);
  return 0;
}

Ein Token Lookahead

Parser müssen das nächste Token meist untersuchen, bevor sie es verbrauchen. Wir speichern ein Token in einem globalen current und laden es nach jedem Match neu.

Dieser Lookahead um genau ein Token genügt für unsere LL(1)-Grammatik.

static Token current;

static void init_lexer(const char *s) {
  src = s;
  current = next_token();
}

static Token cur(void) { return current; }

static void bump(void) { current = next_token(); }

Lexikalische Fehler melden

Ein unbekanntes Zeichen – etwa $ oder @ – sollte nicht stillschweigend verschwinden. Ein robuster Lexer meldet das fehlerhafte Byte und bricht ab.

Ein schneller Abbruch im Lexer verhindert, dass spätere Phasen fehlerhafte Tokens sehen.

#include <stdio.h>
#include <stdlib.h>

static void lex_error(char c) {
  fprintf(stderr, "lex error: unexpected '%c'\n", c);
  exit(1);
}

Operatoren aus mehreren Zeichen

Echte Sprachen enthalten Tokens wie == oder <=. Um sie zu lexen, sehen wir uns nach dem ersten Zeichen ein weiteres an.

Vervollständigt das nächste Byte den Operator, verbrauchen wir beide Zeichen; andernfalls geben wir die Form mit nur einem Zeichen aus.

/* fragment: distinguish '=' from '==' */
if (peek() == '=') {
  advance();
  if (peek() == '=') { advance(); /* TOK_EQ */ }
  else { /* TOK_ASSIGN */ }
}

Warum Tokens wichtig sind

Indem Zeichen zu Tokens zusammengefasst werden, arbeitet der Parser mit einem übersichtlichen, typisierten Datenstrom. Operatorpräzedenz, Gruppierung und Fehler lassen sich dadurch leichter nachvollziehen.

Als Nächstes führen wir diese Tokens einem Recursive-Descent-Parser zu.

Kurze Überprüfung

Überlegen Sie, was der Lexer für Gruppierungssymbole erzeugt.

Zusammenfassung

Sie haben einen Lexer erstellt: einen Token-Typ, einen Scan-Cursor, das Überspringen von Leerraum, das Lexen von Zahlen und einen next_token-Dispatcher mit einem Token Lookahead.

Diese Tokens sind die Eingabe für das Parsing, bei dem daraus ein Syntaxbaum erstellt wird.

Häufig gestellte Fragen

Ist die Lektion „Eingaben tokenisieren“ kostenlos?

Ja — der vollständige Text von „Eingaben tokenisieren“ ist hier im Web kostenlos zu lesen. Um sie interaktiv zu üben (integrierter Code-Editor und 24/7 KI-Tutor) und den Rest des C Academy-Kurses freizuschalten, upgrade auf CoddyKit PRO. Der C Academy-Kurs umfasst insgesamt 4 Lektionen.

Was lerne ich in „Eingaben tokenisieren“?

Wandeln Sie Text in Tokens um. Du übst C Academy mit praktischem Code, den du direkt im Browser ausführst, und ein 24/7 KI-Tutor beantwortet deine Fragen während du die Lektion bearbeitest.

Brauche ich Erfahrung, um C Academy zu starten?

Keine Vorkenntnisse erforderlich. C Academy auf CoddyKit ist für Anfänger bis fortgeschrittene Lernende strukturiert, sodass du hier starten oder von Anfang an beginnen und in deinem eigenen Tempo voranschreiten kannst. Dies ist Lektion 1 von 4.

Wie lange dauert die Lektion „Eingaben tokenisieren“?

Die meisten CoddyKit-Lektionen dauern etwa 5–10 Minuten. Jede ist kompakt und interaktiv, sodass du stetig Fortschritte machst und genau dort weitermachst, wo du aufgehört hast – im Web und in der App.

Kann ich in dieser C Academy-Lektion Code schreiben und ausführen?

Ja. Jede C Academy-Lektion enthält einen integrierten Code-Editor, sodass du echten Code direkt in deinem Browser schreibst und ausführst und sofort KI-Feedback erhältst — ohne lokale Einrichtung erforderlich.

Alle Lektionen in diesem Kurs

  1. Eingaben tokenisieren
  2. Ausdrücke parsen
  3. Den Baum auswerten
  4. Variablen hinzufügen
← Zurück zu C Academy