C Academy · Oppitunti

Muuttujien lisääminen

Tallentakaa ja palauttakaa arvoja.

Oppitunti 4/413 vaihetta

Muuttujien lisääminen on ilmainen C Academy-oppitunti CoddyKitissä. Tämä on oppitunti 4/4. Voit lukea koko oppitunnin alta ilmaiseksi ja harjoitella sen jälkeen käytännössä selaimessa sisäänrakennetulla koodieditorilla ja ympäri vuorokauden käytettävissä olevan tekoälytuutorin avulla. Oppitunti kuuluu C Academy-oppimispolkuun, ja edistymisesi synkronoituu verkon ja CoddyKit-sovelluksen välillä. C Academy-kurssilla on yhteensä 4 oppituntia.

Aritmetiikan tuolle puolen

Jotta x = 5 ja myöhemmin x + 1 voidaan tukea, tulkki tarvitsee tunnisteet ja paikan niiden arvojen tallentamiseen. Tätä tallennuspaikkaa kutsutaan ympäristöksi.

Laajennamme leksikaalista analysaattoria, jäsennintä ja evaluatoria käsittelemään nimiä ja sijoituksia.

Tunnisteiden leksikaalinen analyysi

Tunniste alkaa kirjaimella tai alaviivalla ja jatkuu kirjaimilla, numeroilla tai alaviivoilla. Kopioimme nimen tokeniin.

Kiinteän kokoinen puskuri pitää esimerkin yksinkertaisena; oikeat leksikaaliset analysaattorit internöivät nimet.

#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;
}

Muuttujasolmu

AST saa kaksi uutta solmutyyppiä: muuttujaviitteen ja sijoituksen. Kumpikin tallentaa muuttujan nimen.

Sijoitus säilyttää lisäksi lausekkeen, jonka arvon se tallentaa.

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;

Ympäristö

Ympäristö yhdistää nimet arvoihin. Pienelle tulkille riittää yksinkertainen nimien ja arvojen pareista koostuva lineaarinen taulukko.

Suuremmissa kielissä käytetään hajautustauluja vakioajan O(1) hakuun ja sisäkkäisiin näkyvyysalueisiin.

#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 */

Muuttujan arvon asettaminen

Sijoitus joko päivittää olemassa olevaa paikkaa tai lisää uuden. Lineaarinen haku pitää koodin lyhyenä.

Tallennetun arvon palauttaminen mahdollistaa sijoitusten käytön lausekkeina, kuten 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;
}

Muuttujan lukeminen

Haku etsii nimen ja palauttaa sen arvon. Määrittelemättömään muuttujaan viittaaminen on ajonaikainen virhe.

Kun tämä havaitaan tässä vaiheessa, saadaan selkeä ilmoitus roska-arvon palauttamisen sijaan.

#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);
}

Sijoituksen jäsentäminen

Sijoituksella on pienin etusija, ja se on oikealle assosiatiivinen. Jäsennämme faktorin; jos se on yksittäinen tunniste, jota seuraa =, muodostamme assign-solmun.

Muussa tapauksessa tunniste on pelkkä muuttujan luku.

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();
}

Muuttujien evaluointi

Evaluatoriin lisätään kaksi tapausta. Muuttujasolmu hakee nimensä ympäristöstä; assign-solmu evaluoi arvolausekkeensa ja tallentaa tuloksen.

Molemmat käyttävät uudelleen apufunktioita env_get ja 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;
}

Toimiva REPL-vaihe

Tämä ohjelma tallentaa muuttujan ja lukee sen sitten takaisin lausekkeessa — kaikki ympäristön kautta. Se mallintaa oikean tulkin yhtä riviä.

Suorittakaa ohjelma nähdäksenne, miten sijoitus ja haku toimivat yhdessä.

#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;
}

Näkyvyysalueet ja peittäminen

Yksi tasainen ympäristö on globaali. Oikeat kielet lisäävät sisäkkäiset näkyvyysalueet, jotta funktion paikalliset muuttujat eivät peitä ulompia nimiä.

Tämä toteutetaan ketjuttamalla ympäristöjä: haku etenee sisimmästä näkyvyysalueesta ulospäin.

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

Mihin seuraavaksi?

Kun muuttujat ovat käytössä, voitte lisätä lauseita, ehtolauseita ja funktioita. Kukin niistä on uusi solmutyyppi sekä sitä vastaava eval-tapaus.

Tästä eteenpäin sama leksikaalisen analysaattorin, jäsentimen ja evaluatorin muodostama putki skaalautuu oikeaksi pieneksi kieleksi.

Pikatarkistus

Pohdi, mistä ympäristö vastaa.

Kertaus

Lisäsitte leksikaaliseen analysaattoriin tunnisteet, AST:hen var- ja assign-solmut, set- ja get-operaatiot sisältävän ympäristön sekä eval-tapaukset lukemista ja sijoituksia varten.

Tulkki muistaa nyt tilan — tämä on lauseiden ja funktioiden perusta.

Aloita maksutta

Opi C tekoälytuutorin avulla — ilmaiseksi

Kirjoita ja suorita oikeaa koodia selaimessa, saa välitöntä apua tekoälytuutorilta ympäri vuorokauden ja jatka siitä, mihin jäit, verkossa tai sovelluksessa.

Kurssit
39
Oppitunnit
144

Usein kysytyt kysymykset

Onko oppitunti ”Muuttujien lisääminen” ilmainen?

Kyllä – oppitunnin ”Muuttujien lisääminen” koko tekstin voi lukea täällä verkossa ilmaiseksi. Jos haluat harjoitella interaktiivisesti sisäänrakennetulla koodieditorilla ja ympäri vuorokauden käytettävissä olevan tekoälytuutorin avulla sekä avata koko C Academy-kurssin, päivitä CoddyKit PROhon. C Academy-kurssilla on yhteensä 4 oppituntia.

Mitä opin oppitunnilla ”Muuttujien lisääminen”?

Tallentakaa ja palauttakaa arvoja. Harjoittelet C Academy-aihetta koodilla, jonka suoritat suoraan selaimessa. Ympäri vuorokauden käytettävissä oleva tekoälytuutori vastaa kysymyksiisi oppitunnin aikana.

Tarvitsenko kokemusta aloittaakseni C Academy-opiskelun?

Aiempi kokemus ei ole tarpeen. CoddyKitin C Academy-oppimispolku sopii vasta-alkajista edistyneisiin, joten voit aloittaa tästä tai alusta ja edetä omaan tahtiisi. Tämä on oppitunti 4/4.

Kuinka kauan ”Muuttujien lisääminen”-oppitunnin suorittaminen kestää?

Useimmat CoddyKitin oppitunnit kestävät noin 5–10 minuuttia. Jokainen oppitunti on lyhyt ja interaktiivinen, joten edistyt tasaisesti ja voit jatkaa siitä, mihin jäit – sekä verkossa että sovelluksessa.

Voinko kirjoittaa ja suorittaa koodia tällä C Academy-oppitunnilla?

Kyllä. Jokainen C Academy-oppitunti sisältää sisäänrakennetun koodieditorin, joten voit kirjoittaa ja suorittaa oikeaa koodia suoraan selaimessa ja saada välitöntä palautetta tekoälyltä – paikallista asennusta ei tarvita.

Kaikki tämän kurssin oppitunnit

  1. Syötteen tokenisointi
  2. Lausekkeiden jäsentäminen
  3. Puun evaluointi
  4. Muuttujien lisääminen
← Takaisin: C Academy