Skrifið forrit sem les línur af aðalinntaki og skrifar þær í öfugri röð á aðalúttak. Forritið á að nota hlaða, sem fylgir með beinagrindinni, til að víxla röðinni. Forritið má gera ráð fyrir að hámarkslengd línu sé 8192 bæti með núll-bætinu.
#include <stdio.h>
#include "stack.h"
int main(void)
{
char buf[8192];
struct stack s;
stack_init(&s);
while (1)
{
if (fgets(buf, sizeof(buf), stdin) == NULL)
break;
stack_push(&s, buf);
}
while (!stack_empty(&s))
{
printf("%s", stack_pop(&s));
}
}
Klárið útfærslu á walktree fallinu í beinagrindinni. Fallið tekur inn fallbendi og bendi á streng sem inniheldur slóð í skráarkerfinu. Fallið gengur yfir allar skrár og möppur sem liggja undir slóðinni og fyrir hverja skrá/möppu þá er kallað á fallbendinn með viðföngum sem lýsa þeirri tilteknu skrá/möppu.
Forritið á að nota hlaða, sem fylgir með beinagrindinni, til að halda utan um möppur sem á eftir að heimsækja. Í upphafi þá er uppgefin slóð sett á hlaðann, en síðan í hvert skipti sem fallið rekst á möppu í göngunni þá er hún sett á hlaðann. Fallið lýkur keyrslu þegar hlaðinn er tómur.
#include <stdio.h>
#include <dirent.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include "stack.h"
#include <errno.h>
#include <string.h>
int walktree(char *root, void (*fn)(char type, char *path, char *fn, struct stat *st))
{
DIR *dir;
struct dirent *entry;
struct stat st;
char buf[8192];
struct stack s;
stack_init(&s);
stack_push(&s, root);
while (!stack_empty(&s))
{
char *dp = stack_pop(&s);
dir = opendir(dp);
if (dir == NULL)
{
free(dp);
continue;
}
while ((entry = readdir(dir)))
{
if (entry->d_name[0] == '.')
continue;
snprintf(buf, sizeof(buf), "%s/%s", dp, entry->d_name);
if (lstat(buf, &st) < 0)
continue;
if (S_ISDIR(st.st_mode))
{
fn('D', buf, entry->d_name, &st);
stack_push(&s, buf);
}
else if (S_ISREG(st.st_mode))
{
fn('F', buf, entry->d_name, &st);
}
}
closedir(dir);
free(dp);
}
}
void printfile(char type, char *path, char *fn, struct stat *st)
{
if (type == 'D')
printf("%c %s\n", type, path);
else
printf("%c %s (%ld bytes)\n", type, path, st->st_size);
}
int main(int argc, char *argv[])
{
if (argc < 2)
{
fprintf(stderr, "usage: walker <path>\n");
return 1;
}
walktree(argv[1], printfile);
return 0;
}
Ef forritið virkar rétt þá ætti að vera hægt að keyra það með einu viðfangi (slóð á möppu) og fá út lista eins og hér fyrir neðan.
hhg@hhg:~/t2/V3/walker$ ./walker /home/hhg/t2/V3 D /home/hhg/t2/V3/walker F /home/hhg/t2/V3/sort.c (973 bytes) F /home/hhg/t2/V3/dirprint.c (592 bytes) F /home/hhg/t2/V3/count.c (1038 bytes) F /home/hhg/t2/V3/sort (7509 bytes) F /home/hhg/t2/V3/count (7433 bytes) D /home/hhg/t2/V3/reverse F /home/hhg/t2/V3/reverse/Makefile (190 bytes) F /home/hhg/t2/V3/reverse/reverse.c (274 bytes) F /home/hhg/t2/V3/reverse/reverse.o (1228 bytes) F /home/hhg/t2/V3/reverse/stack.h (365 bytes) F /home/hhg/t2/V3/reverse/stack.c (583 bytes) F /home/hhg/t2/V3/reverse/stack.o (1096 bytes) F /home/hhg/t2/V3/reverse/reverse (7525 bytes) F /home/hhg/t2/V3/walker/Makefile (210 bytes) F /home/hhg/t2/V3/walker/walker.o (51596 bytes) F /home/hhg/t2/V3/walker/stack.h (365 bytes) F /home/hhg/t2/V3/walker/walker.c (1226 bytes) F /home/hhg/t2/V3/walker/stack.c (582 bytes) F /home/hhg/t2/V3/walker/walker (80677 bytes) F /home/hhg/t2/V3/walker/stack.o (27436 bytes) hhg@hhg:~/t2/V3/walker$
Skrifið forrit sem les línur af aðalinntaki og skrifar þær í vaxandi stafrófsröð á aðalúttak.
Notið beinagrindina hér fyrir neðan og klárið útfærsluna.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
char *readline(FILE *fp)
{
size_t size = 0;
size_t len = 0;
size_t last = 0;
char *buf = NULL;
while (!feof(fp))
{
size += BUFSIZ;
buf = realloc(buf, size);
if (fgets(buf+last, size-last, fp) == NULL)
break;
len = strlen(buf);
last = len - 1;
if (buf[last] == '\n')
break;
}
if (len == 0)
{
free(buf);
return NULL;
}
return buf;
}
int cmp(const void *va, const void *vb)
{
const char *a = *(char * const *)va;
const char *b = *(char * const *)vb;
return strcmp(a, b);
}
int main(void)
{
char **lines;
size_t size = 1024;
int n = 0;
int i;
lines = malloc(sizeof(char *) * size);
while (1)
{
if (n >= size)
{
size *= 2;
lines = realloc(lines, sizeof(char *) * size);
}
char *line = readline(stdin);
if (line == NULL)
break;
lines[n++] = line;
}
qsort(lines, n, sizeof(char *), cmp);
for (i = 0; i < n; i++)
printf("%s", lines[i]);
}
Skrifið forrit sem les orð af aðalinntaki og prentar út á aðalúttak hversu oft hvert orð kemur fyrir í inntakinu.
Notið beinagrindina hér fyrir neðan og klárið útfærsluna.
(Athugið að þetta forrit notar mjög hægvirka línulega leit, það er leitað í öllu fylkinu í hverri uppflettingu, en seinna í námskeiðinu munið þið læra betri aðferðir.)
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
struct word
{
char *word;
int count;
};
struct state
{
struct word **words;
size_t alloc;
size_t len;
};
void state_init(struct state *s)
{
s->alloc = 8192;
s->len = 0;
s->words = malloc(sizeof(struct word *) * s->alloc);
}
struct word *state_get(struct state *s, char *word)
{
int i;
struct word *h;
for (i = 0; i < s->len; i++)
{
if (!strcmp(s->words[i]->word, word))
return s->words[i];
}
if (s->len >= s->alloc)
{
s->alloc *= 2;
s->words = realloc(s->words, sizeof(struct word *) * s->alloc);
}
h = malloc(sizeof(struct word));
h->word = strdup(word);
h->count = 0;
s->words[s->len] = h;
s->len++;
return h;
}
int main(void)
{
char buf[8192];
struct state state;
int i;
state_init(&state);
while (1)
{
if (scanf("%8191s", buf) != 1)
break;
struct word *w = state_get(&state, buf);
w->count++;
}
for (i = 0; i < state.len; i++)
{
struct word *w = state.words[i];
printf("%s: %d\n", w->word, w->count);
}
}