C Academy · leksjon

Legg til variabler

Lagre og hent verdier.

Leksjon 4 av 413 trinn

Legg til variabler er en gratis leksjon i C Academy på CoddyKit. Dette er leksjon 4 av 4. Du kan lese hele leksjonen gratis nedenfor – og deretter øve praktisk i nettleseren med en innebygd kodeeditor og en AI-veileder som er tilgjengelig døgnet rundt. Den er en del av læringsløpet i C Academy, og fremdriften din synkroniseres mellom nettet og CoddyKit-appen. Kurset i C Academy inneholder totalt 4 leksjoner.

Utover aritmetikk

For å støtte x = 5 og senere x + 1 trenger tolken identifikatorer og et sted å lagre verdiene deres. Dette lageret er miljøet.

Vi utvider lexeren, parseren og evaluatoren slik at de håndterer navn og tilordning.

Leksing av identifikatorer

En identifikator begynner med en bokstav eller understrek og fortsetter med bokstaver, sifre eller understreker. Vi kopierer navnet inn i tokenet.

En buffer med fast størrelse holder eksempelet enkelt; ekte lexere interniserer navn.

#include <ctype.h>
#include <string.h>

typedef struct { TokKind kind; int value; char name[32]; } Token;

static Token lex_ident(void) {
  Token t; t.kind = TOK_IDENT; int i = 0;
  while (isalnum((unsigned char)peek()) || peek() == '_')
    if (i < 31) t.name[i++] = advance(); else advance();
  t.name[i] = '\0';
  return t;
}

En variabelnode

AST-et får to nodetyper: en variabelreferanse og en tilordning. Begge lagrer variabelnavnet.

Tilordningen lagrer også uttrykket hvis verdi den tilordner.

typedef struct Node {
  enum { N_NUM, N_BINOP, N_VAR, N_ASSIGN } kind;
  int value; char op; char name[32];
  struct Node *left, *right;  /* assign uses right as value expr */
} Node;

Miljøet

Miljøet knytter navn til verdier. En enkel lineær tabell med navn/verdi-par er tilstrekkelig for en liten tolk.

Større språk bruker hashtabeller for oppslag i O(1) og nøstede scope-er.

#define MAX_VARS 64

typedef struct {
  char names[MAX_VARS][32];
  int  values[MAX_VARS];
  int  count;
} Env;

static Env env;  /* global for this tiny example */

Sette en variabel

En tilordning oppdaterer enten en eksisterende plass eller legger til en ny. Lineært søk holder koden kort.

Ved å returnere den lagrede verdien kan tilordninger brukes som uttrykk, som i y = (x = 3).

#include <string.h>

static int env_set(const char *name, int v) {
  for (int i = 0; i < env.count; i++)
    if (strcmp(env.names[i], name) == 0) {
      env.values[i] = v; return v;
    }
  strcpy(env.names[env.count], name);
  env.values[env.count] = v;
  env.count++;
  return v;
}

Lese en variabel

Et oppslag søker etter navnet og returnerer verdien. En referanse til en udefinert variabel er en kjøretidsfeil.

Ved å fange dette her får du en tydelig melding i stedet for en tilfeldig verdi.

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

static int env_get(const char *name) {
  for (int i = 0; i < env.count; i++)
    if (strcmp(env.names[i], name) == 0)
      return env.values[i];
  fprintf(stderr, "undefined variable: %s\n", name);
  exit(1);
}

Parsing av tilordning

Tilordning har lavest presedens og er høyreassosiativ. Vi parser en faktor; hvis den er en frittstående identifikator etterfulgt av =, bygger vi en assign-node.

Ellers er identifikatoren bare en variabelavlesning.

static Node *parse_assign(void) {
  if (cur().kind == TOK_IDENT) {
    char saved[32]; strcpy(saved, cur().name);
    bump();
    if (cur().kind == TOK_ASSIGN) {
      bump();
      Node *val = parse_assign();
      return assign_node(saved, val);
    }
    return var_node(saved);  /* not an assignment */
  }
  return parse_expr();
}

Evaluere variabler

Evaluatoren får to nye tilfeller. En variabelnode slår opp navnet i miljøet; en assign-node evaluerer verdiuttrykket og lagrer det.

Begge gjenbruker hjelpefunksjonene env_get og env_set.

int eval(Node *n) {
  switch (n->kind) {
    case N_NUM:    return n->value;
    case N_VAR:    return env_get(n->name);
    case N_ASSIGN: return env_set(n->name, eval(n->right));
    case N_BINOP: {
      int l = eval(n->left), r = eval(n->right);
      switch (n->op) {
        case '+': return l + r; case '-': return l - r;
        case '*': return l * r; case '/': return l / r;
      }
    }
  }
  return 0;
}

Et fungerende REPL-trinn

Dette programmet lagrer en variabel og leser den deretter tilbake i et uttrykk – alt gjennom miljøet. Det modellerer én linje i en ekte tolk.

Kjør det for å se tilordning og oppslag samarbeide.

#include <stdio.h>
#include <string.h>

#define MAX_VARS 64
static char names[MAX_VARS][32];
static int  values[MAX_VARS];
static int  count;

static int env_set(const char *n,int v){
  for(int i=0;i<count;i++) if(!strcmp(names[i],n)){values[i]=v;return v;}
  strcpy(names[count],n); values[count]=v; count++; return v;
}
static int env_get(const char *n){
  for(int i=0;i<count;i++) if(!strcmp(names[i],n)) return values[i];
  return 0;
}

int main(void){
  env_set("x", 5);            /* x = 5 */
  int r = env_get("x") + 1;   /* x + 1 */
  printf("x = %d\n", env_get("x"));
  printf("x + 1 = %d\n", r);
  return 0;
}

Scope-er og skyggelegging

Et enkelt flatt miljø er globalt. Ekte språk legger til nøstede scope-er, slik at lokale variabler i en funksjon ikke overskriver navn utenfor funksjonen.

Dette implementerer du ved å lenke sammen miljøer: oppslag går fra det innerste scopet og utover.

typedef struct Env {
  char names[MAX_VARS][32];
  int  values[MAX_VARS];
  int  count;
  struct Env *parent;  /* enclosing scope */
} Env;

Hva blir neste steg?

Med variabler på plass kan du legge til setninger, betingelser og funksjoner. Hver av dem er en ny nodetype pluss et eval-tilfelle.

Herfra kan den samme lexer-parser-evaluator-pipelinen utvides til et ekte lite språk.

Rask sjekk

Tenk over hva miljøet har ansvar for.

Oppsummering

Du la til identifikatorer i lexeren, var/assign-noder i AST-et, et miljø med set og get, samt eval-tilfeller for avlesning og tilordning.

Tolken husker nå tilstand – grunnlaget for setninger og funksjoner.

Gratis å komme i gang

Lær deg C med en AI-veileder – gratis

Skriv og kjør ekte kode i nettleseren, få umiddelbar hjelp fra en AI-veileder som er tilgjengelig døgnet rundt, og fortsett der du slapp – på nettet eller i appen.

Kurs
39
Leksjoner
144

Ofte stilte spørsmål

Er leksjonen «Legg til variabler» gratis?

Ja – hele teksten i «Legg til variabler» er gratis å lese her på nettet. For å øve interaktivt med en innebygd kodeeditor og en AI-veileder som er tilgjengelig døgnet rundt, og for å låse opp resten av C Academy-kurset, kan du oppgradere til CoddyKit PRO. Kurset i C Academy inneholder totalt 4 leksjoner.

Hva lærer jeg i «Legg til variabler»?

Lagre og hent verdier. Du øver på C Academy med praktisk kode som du kjører direkte i nettleseren, mens en AI-veileder som er tilgjengelig døgnet rundt, svarer på spørsmålene dine mens du jobber deg gjennom leksjonen.

Trenger jeg erfaring for å begynne med C Academy?

Ingen tidligere erfaring er nødvendig. C Academy på CoddyKit er lagt opp for både nybegynnere og viderekomne, så De kan begynne her eller helt fra start og lære i Deres eget tempo. Dette er leksjon 4 av 4.

Hvor lang tid tar leksjonen «Legg til variabler»?

De fleste CoddyKit-leksjoner tar omtrent 5–10 minutter. Hver leksjon er kort og interaktiv, slik at De gjør jevne fremskritt og kan fortsette akkurat der De slapp – både på nettet og i appen.

Kan jeg skrive og kjøre kode i denne C Academy-leksjonen?

Ja. Alle C Academy-leksjoner har en innebygd kodeeditor, slik at De kan skrive og kjøre ekte kode direkte i nettleseren og få umiddelbar tilbakemelding fra AI – uten lokal konfigurering.

Alle leksjonene i dette kurset

  1. Tokeniser inndata
  2. Analyser uttrykk
  3. Evaluer treet
  4. Legg til variabler
← Tilbake til C Academy