Inital commit. Solutions to k&r chapter one

master
Tibor Bizjak 2023-05-02 13:51:17 +02:00
commit 9890fece0f
22 changed files with 1057 additions and 0 deletions

View File

@ -0,0 +1,6 @@
#include <stdio.h>
main()
{
printf("hello world\n");
}

View File

@ -0,0 +1,20 @@
#include <stdio.h>
main()
{
float fahr, celsius;
int lower, upper, step;
lower = 0;
upper = 300;
step = 20;
printf("Fahr\tCels\n");
fahr = lower;
while (fahr <= upper) {
celsius = (5.0 / 9.0) * (fahr - 32.0);
printf("%4.0f\t%3.1f\n", fahr, celsius);
fahr = fahr + step;
}
}

View File

@ -0,0 +1,20 @@
#include <stdio.h>
main()
{
int fahr, celsius;
int lower, upper, step;
lower = 0;
upper = 300;
step = 20;
printf("Cels\tFahr\n");
celsius = lower;
while (celsius <= upper) {
fahr = (celsius / 5) * 9 + 32;
printf("%4d\t%4d\n", celsius, fahr);
celsius = celsius + step;
}
}

View File

@ -0,0 +1,13 @@
#include <stdio.h>
#define LOWER 0
#define UPPER 300
#define STEP 20
main()
{
int fahr;
for (fahr = UPPER; fahr >= LOWER; fahr = fahr - STEP)
printf("%3d %6.1f\n", fahr, (5.0 / 9.0) * (fahr - 32));
}

View File

@ -0,0 +1,6 @@
#include <stdio.h>
void main()
{
printf("%d\n", getchar() != EOF);
}

View File

@ -0,0 +1,6 @@
#include <stdio.h>
void main()
{
printf("%d\n", EOF);
}

View File

@ -0,0 +1,20 @@
#include <stdio.h>
void main()
{
int c;
long bl, tb, nl;
bl = tb = nl = 0;
while ((c = getchar()) != EOF)
{
if (c == ' ')
++bl;
if (c == '\t')
++tb;
if (c == '\n')
++nl;
}
printf("blanks : %ld\ntabs : %ld\nnewlines : %ld\n", bl, tb, nl);
}

View File

@ -0,0 +1,14 @@
#include <stdio.h>
#define BLANK ' '
void main()
{
int c, prev = -1;
while ((c = getchar()) != EOF) {
if (prev != BLANK || c != BLANK)
putchar(c);
prev = c;
}
}

View File

@ -0,0 +1,17 @@
#include <stdio.h>
void main()
{
int c;
while ((c = getchar()) != EOF) {
if (c == '\t')
printf("\\t");
else if (c == '\b')
printf("\\b");
else if (c == '\\')
printf("\\\\");
else
putchar(c);
}
}

View File

@ -0,0 +1,24 @@
#include <stdio.h>
#define IN 0
#define OUT 1
void main()
{
int c, state = OUT;
while ((c = getchar()) != EOF) {
if (c == ' ' || c == '\n' || c =='\t') {
if (state == IN) {
putchar('\n');
state = OUT;
}
continue;
}
putchar(c);
state = IN;
}
if (state == IN)
putchar('\n');
}

View File

@ -0,0 +1,67 @@
#include <stdio.h>
#define MAXLEN 10
/* print historgram of word lengths */
void main()
{
int c, i, len;
/* no word has len = 0; we subscribe with count-1 */
/* the last element is the count of words wiht len > MAXLEN */
int counts[MAXLEN + 1];
/* initializing */
len = 0;
for (i = 0; i <= MAXLEN; ++i)
counts[i] = 0;
/* counting */
while ((c = getchar()) != EOF) {
if (c == ' ' || c == '\n' || c == '\t') {
if (len > 0) {
if (len > MAXLEN)
++counts[MAXLEN];
else
++counts[len-1];
len = 0;
}
continue;
}
++len;
}
int j, max, bound;
bound = max = 0;
for (i = 0; i <= MAXLEN; ++i)
if (counts[i] > 0) {
bound = i;
if (counts[i] > max)
max = counts[i];
}
/* printing horizontal */
printf("----- horizontal -----\n");
for (i = 0; i <= bound; ++i) {
if (i == MAXLEN)
printf(">%2d ", MAXLEN);
else
printf("%3d ", i + 1);
for (j = 0; j < counts[i]; ++j)
putchar('#');
putchar('\n');
}
printf("\n\n");
/* printing vertical */
printf("----- vertical -----\n");
for (i = max; i > 0; --i) {
for (j = 0; j <= bound; ++j)
if (counts[j] >= i)
putchar('#');
else
putchar(' ');
putchar('\n');
}
}

View File

@ -0,0 +1,41 @@
#include <stdio.h>
#define CHARS 254
/* prints character frequency histogram */
void main()
{
int i, c;
int counts[CHARS];
/* initializing */
for (i = 0; i < CHARS; ++i)
counts[i] = 0;
/* counting */
while ((c = getchar()) != EOF) {
++counts[c];
}
/* printing */
for (c = 0; c < CHARS; ++c) {
if (counts[c] == 0)
continue;
if (c == '\n')
printf("\\n ");
else if (c == ' ')
printf("' ' ");
else if (c == '\t')
printf("\\t ");
else if (c == '\b')
printf("\\b ");
else
printf("%c ", c);
for (i = 0; i < counts[c]; ++i)
putchar('#');
putchar('\n');
}
}

View File

@ -0,0 +1,22 @@
#include <stdio.h>
#define LOWER 0
#define UPPER 300
#define STEP 20
float cels_of_fahr(float fahr);
int main()
{
int fahr;
printf("%3c %6c\n", 'F', 'C');
for (fahr = LOWER; fahr <= UPPER; fahr = fahr + STEP)
printf("%3d %6.1f\n", fahr, cels_of_fahr(fahr));
return 0;
}
float cels_of_fahr(float fahr)
{
return (5.0/9.0) * (fahr-32);
}

View File

@ -0,0 +1,63 @@
#include <stdio.h>
#define MAXLINE 1000
int mygetline(char line[], int maxline);
void copy(char to[], char from[]);
/* print longest input line */
int main()
{
int len, max; /* current, max lenght */
char line[MAXLINE+1], longest[MAXLINE+1]; /* current, longest line; +1 for \0 */
max = 0;
while ((len = mygetline(line, MAXLINE)) > 0)
if (len > max) {
max = len;
copy(longest, line);
}
if (max > 0) {
printf("%d ", max);
if (max <= MAXLINE && longest[max-1] == '\n') {
longest[max-1] = '\\';
printf("\n%sn\n", longest);
} else if (max <= MAXLINE) {
printf("\n%s\n", longest);
} else
printf("(first %d chars)\n%s...\n", MAXLINE, longest);
} else
printf("No lines found\n");
return 0;
}
/* mygetline : read part of line smaller than lim-1 into s, return length */
int mygetline(char s[], int maxline)
{
int c, i;
for (i=0; (c=getchar()) != EOF; ++i) {
if (i < maxline)
s[i] = c;
if (c == '\n') {
++i;
break;
}
}
if (i < maxline)
s[i] = '\0';
else
s[maxline] = '\0';
return i;
}
/* copy : copy 'from' to 'to'; assume 'to' is big enough */
void copy(char to[], char from[])
{
int i;
for(i = 0; (to[i] = from[i]) != '\0'; ++i)
;
}

View File

@ -0,0 +1,30 @@
#include <stdio.h>
/* print line number and lines longer than 80 chars (excluding \n) */
int main()
{
int c, i, ln;
char buff[81]; /* +1 for \0 */
ln = 1;
buff[80] = '\0';
for (i = 0; (c = getchar()) != EOF; ++i) {
if (c == '\n') {
if (i > 80)
putchar('\n');
++ln;
i = -1;
} else if (i < 80) {
buff[i] = c;
} else {
if (i == 80)
printf("%d %s", ln, buff);
putchar(c);
}
}
if (i > 80 && c != '\n')
putchar('\n');
}

View File

@ -0,0 +1,37 @@
#include <stdio.h>
#define MAXBUFF 1000
/* removes trailing spaces and tabs */
int main()
{
int i, c;
char buff[MAXBUFF+1]; /* +1 fo \0 */
i = 0;
buff[MAXBUFF] = '\0';
while ((c = getchar()) != EOF) {
if (c == ' ' || c == '\t') {
if (i < MAXBUFF) {
buff[i] = c;
++i;
} else {
/* gracefully handle overflow */
printf("%s", buff);
i = 0;
}
} else if (c == '\n') {
buff[0] = c;
i = 1;
} else {
if (i > 0) {
buff[i] = '\0';
printf("%s", buff);
i = 0;
}
putchar(c);
}
}
return 0;
}

View File

@ -0,0 +1,61 @@
#include <stdio.h>
#define MAXLINE 1000
void reverse(char s[]);
int mystrlen(char s[]);
int get_line(char s[], int maxline);
/* reverses input line by line */
int main()
{
int end = 0;
char line[MAXLINE + 1];
while (end != EOF) {
end = get_line(line, MAXLINE);
reverse(line);
printf("%s", line);
if (end != EOF)
putchar(end);
}
}
/* reverses string 's' in place */
void reverse(char s[])
{
char c;
int i, len = mystrlen(s);
for (i = 0; i < len / 2; ++i) {
c = s[i];
s[i] = s[len-i-1];
s[len-i-1] = c;
}
}
/* returns length of string 's' */
int mystrlen(char s[])
{
int len;
for (len = 0; s[len] != '\0'; ++len)
;
return len;
}
/* reads (possibly truncated) line from input to s, returns \n or EOF */
int get_line(char s[], int maxline)
{
int c, i;
for (i=0; (c=getchar()) != EOF && c != '\n'; ++i) {
if (i < maxline)
s[i] = c;
}
if (i < maxline)
s[i] = '\0';
else
s[maxline] = '\0';
return c;
}

View File

@ -0,0 +1,48 @@
#include <stdio.h>
#include <stdlib.h>
#define TABSTOP 4
void detab(int tabstop);
int fill(int indent, int tabstop);
/* detab input, takes one optional argument for tabstop width */
int main(int argc, char *argv[])
{
int tabstop;
if (argc < 2 || !(tabstop = atoi(argv[1])))
detab(TABSTOP);
else
detab(tabstop);
return 0;
}
/* detabs input with spaces, tab stop width is 'tabstop' */
void detab(int tabstop)
{
int c, indent = 0; /* indent starts at 0 */
while ((c = getchar()) != EOF)
if (c == '\t')
indent = fill(indent, tabstop);
else {
putchar(c);
indent = (c == '\n') ? 0 : indent + 1;
}
}
/* fills output with spaces from indent to next tabstop */
/* returns new indent */
int fill(int indent, int tabstop)
{
int w = tabstop - indent % tabstop;
for (; w > 0; --w) {
putchar(' ');
++indent;
}
return indent;
}

View File

@ -0,0 +1,44 @@
#include <stdio.h>
#include <stdlib.h>
#define TABSTOP 4
void entab(int tabstop);
/* entab input, takes one optional argument for tabstop width */
int main(int argc, char *argv[])
{
int tabstop;
if (argc < 2 || !(tabstop = atoi(argv[1])))
entab(TABSTOP);
else
entab(tabstop);
return 0;
}
/* entabs input with spaces, tab stop width is 'tabstop' */
void entab(int tabstop)
{
int c, indent; /* indent starts at 1 */
int bn = 0; /* current number of blanks */
for (indent = 1; (c = getchar()) != EOF; ++indent)
if (c == ' ') {
if (indent % tabstop || bn == 0)
/* dont entab single spaces */
++bn;
else {
bn = 0;
putchar('\t');
}
} else {
for(; bn > 0; --bn)
putchar(' ');
putchar(c);
if (c == '\n')
indent = 0;
}
}

View File

@ -0,0 +1,117 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define TABSTOP 8
#define WIDTH 80
// the RATIO can't be less than 1/2
#define RATIO 2.0/3.0
#define BREAKSTR "-"
int bstrlen = strlen(BREAKSTR);
void fold(int width, int maxind);
void flush_wbuff(int wbi, char wbuff[]);
int insert_break(char buff[], int wbi);
int is_blank(char c);
int mv_cur(int n, char c);
/* fold input, takes one optional argument for max line width (excl \n) */
int main(int argc, char *argv[])
{
int w;
if (argc < 2 || (w = atoi(argv[1])) < 2)
fold(WIDTH, RATIO * WIDTH);
else
fold(w, RATIO * w);
return 0;
}
/* folds input lines to length, where minw <= length <= 'width'
* if a line has no blank spaces after 'minw' chars a BREAKSTR is inserted */
void fold(int width, int minw)
{
int c, n = 0; // n=0 is start of line
int wbi = 0; // word buffer index
char wbuff[width - minw]; // word buffer for words over minw
while ((c = getchar()) != EOF) {
n = mv_cur(n, c);
if (c == '\n' || (n >= width+1 && is_blank(c))) {
// handle newlines
flush_wbuff(wbi, wbuff);
putchar('\n');
n = wbi = 0;
continue;
}
if (n <= minw) // always print chars before minw
putchar(c);
else if (n <= width) {
/* add word (optionaly leading blank) after minw to wbuff
* empty buffer if new blank is found */
if (is_blank(c)) {
flush_wbuff(wbi, wbuff);
wbi = 0;
}
wbuff[wbi] = c;
++wbi;
} else { // one char over edge, c != ' '
n = insert_break(wbuff, wbi) + 1;
putchar(c);
wbi = 0;
}
}
}
void flush_wbuff(int wbi, char wbuff[])
{
printf("%.*s", wbi, wbuff);
}
/* print buff and insert line break where its most fitting,
* return new cursor position
* '\n' is inserted before the last word or 'BREAKSTR\n' is inserted */
int insert_break(char wbuff[], int wbi)
{
int i;
if (wbi == 0) {
putchar('\n');
return 0;
}
if (is_blank(wbuff[0])) {
putchar('\n');
for (i=1; i < wbi; ++i)
putchar(wbuff[i]);
return wbi - 1;
}
flush_wbuff(wbi-bstrlen, wbuff);
printf("%s\n", BREAKSTR);
for (i = wbi-bstrlen; i < wbi; ++i)
putchar(wbuff[i]);
return bstrlen;
}
/* return new cursor position */
int mv_cur(int n, char c)
{
if (c == '\t')
return n + (TABSTOP - n % TABSTOP);
else if (c == '\b')
return n;
return n+1;
}
int is_blank(char c)
{
return (c == ' ' || c == '\t');
}

View File

@ -0,0 +1,139 @@
#include <stdio.h>
#define MAXBUFF 100
void ignore_line(void);
int ignore_multiline(void);
int pass_char_const(char fst);
int pass_string(char fst);
int flush_buff(char buff[], int bi);
int is_blank(char c);
/* remove comments from input; remove empty lines and trailing spaces
* left by removed comments; Check for the following errors:
* - invalid string literals
* - invalid char constants
* - non-terminating multi line comments */
int main()
{
int a, b;
int bi = 0; // blank buffer index
char blank_buff[MAXBUFF]; // blank buffer
for (a = getchar(); (b = getchar()) != EOF; a = b)
if (a == '/' && b == '*') {
bi = 0;
if (ignore_multiline()) {
printf("\nerror : no terminator for multiline comment\n");
return 1;
}
b = getchar();
} else if (a == '/' && b == '/') {
bi = 0;
ignore_line();
putchar('\n');
b = getchar();
} else if (a == '\'') {
bi = flush_buff(blank_buff, bi);
putchar('\'');
if (pass_char_const(b)) {
printf("\nerror : invalid character constant\n");
return 1;
}
b = getchar();
} else if (a == '"') {
bi = flush_buff(blank_buff, bi);
putchar('"');
if (pass_string(b)) {
printf("\nerror : invalid string literal\n");
return 1;
}
b = getchar();
} else if (is_blank(a)) {
if (bi >= MAXBUFF)
bi = flush_buff(blank_buff, bi);
blank_buff[bi] = a;
++bi;
} else if (a == '\n') {
flush_buff(blank_buff, bi);
blank_buff[0] = a;
bi = 1;
} else {
bi = flush_buff(blank_buff, bi);
putchar(a);
}
if (a != EOF)
putchar(a);
return 0;
}
/* ignore line of input */
void ignore_line()
{
int c;
while ((c = getchar()) != EOF && c != '\n')
;
}
/* ignore input until comment termination occurs
* return 1 if error otherwise 0 */
int ignore_multiline()
{
int a, b;
for (a = getchar(); (b = getchar()) != EOF; a = b)
if (a == '*' && b == '/')
return 0;
return 1;
}
/* pass the tail of a character constant from input to ouput
* return 1 if error otherwise 0 */
int pass_char_const(char fst)
{
int c;
putchar(fst);
if (fst == '\\') {
if ((c = getchar()) == EOF)
return 1;
putchar(c);
}
if ((c = getchar()) == EOF || c != '\'')
return 1;
putchar(c);
return 0;
}
/* pass the tail (wihtout fst element) of a
* C string literal from input to output.
* 'fst' is the first character of the string tail
* return 1 if error otherwise 0 */
int pass_string(char fst)
{
int snd;
putchar(fst);
for (; (snd = getchar()) != EOF; fst = snd) {
putchar(snd);
if (fst == '\n')
break;
if (snd == '"' && fst != '\\')
return 0;
}
return 1;
}
/* print buffer 'buff' and return 0 */
int flush_buff(char buff[], int bi)
{
printf("%.*s", bi, buff);
return 0;
}
int is_blank(char c)
{
return c == ' ' || c == '\t' || c == '\b';
}

View File

@ -0,0 +1,242 @@
#include <stdio.h>
#include <string.h>
#define TABSTOP 8
#define BUFFSIZE 100
#define ESCAPED "0bnt\\"
#define LINEN 5
#define ERRMSG_SIZE 100
#define ERR_ESC_EOF "expected escape character, got EOF"
#define ERR_ESC_INV "invalid escape character"
#define ERR_STR_TRM "expected string termination"
#define ERR_CHAR_EOF "expected character constant, got EOF"
#define ERR_CHAR_TRM "expected character constant termination"
#define ERR_COMM_TRM "expected multi-line comment termination"
/* global input line and character counting */
int ln = 1;
int cn = 0;
int ln_getchar()
{
int c;
if ((c = getchar()) == '\n' || c == EOF) {
cn = 0;
++ln;
} else
++cn;
return c;
}
#define getchar() ln_getchar()
int print_context();
int check_escaped(char errmsg[], int d);
int check_multiline(char errmsg[]);
int check_char_const(char errmsg[]);
int check_string(char errmsg[]);
int getcharb();
int ithchar(int i);
int prevchar();
int print_buff(int n);
void print_line();
void ignore_line();
void copy(char from[], char to[]);
/* check c program on input for unabalanced parantheses
* string termination, comment termination and char constant
* validity */
int main()
{
int i, c;
int err = 0;
char errmsg[ERRMSG_SIZE];
while (!err && (c = getcharb()) != EOF) {
if (c == '"' && check_string(errmsg)) {
err = 1;
} else if (c == '\'' && check_char_const(errmsg)) {
err = 2;
} else if (prevchar() == '/' && c == '*' && check_multiline(errmsg)) {
err = 3;
} else if (c == '/' && prevchar() == '/') {
ignore_line();
}
}
if (!err)
return 0;
int li = print_context();
printf("%d:%d: error: %s\n", ln-1, li+1, errmsg);
return 0;
}
/* print context of error and arrow pointing to cursor
* position where error was raised */
int print_context()
{
int i, li = print_buff(LINEN);
if (li < 0) {
for (i = li; i < -1; ++i)
putchar(' ');
} else {
print_line();
for (i = li; i > 0; --i)
putchar(' ');
}
printf("^\n");
return li;
}
// ---------------------- validation functions ------------------------
/* check multiline comment termination */
int check_multiline(char errmsg[])
{
int c;
while ((c = getcharb()) != EOF)
if (prevchar() == '*' && c == '/')
return 0;
copy(ERR_COMM_TRM, errmsg);
return 1;
}
/* check char constant validity and termination */
int check_char_const(char errmsg[])
{
int c;
if ((c = getcharb()) == EOF) {
copy(ERR_CHAR_EOF, errmsg);
return 1;
}
if (c == '\\' && check_escaped(errmsg, '\''))
return 1;
if ((c = getcharb()) == EOF || c != '\'') {
copy(ERR_CHAR_TRM, errmsg);
return 1;
}
return 0;
}
/* check string termination */
int check_string(char errmsg[])
{
int c;
while ((c = getcharb()) != EOF && c != '\n') {
if (c == '\\' && check_escaped(errmsg, '"'))
return 1;
else if (c == '"')
return 0;
}
copy(ERR_STR_TRM, errmsg);
return 1;
}
/* check if \(next input char) makes a valid escape char
* \'d' is considered valid, pass negative 'd' to make optional */
int check_escaped(char errmsg[], int d)
{
int i, c = getcharb();
if (c == EOF) {
copy(ERR_ESC_EOF, errmsg);
return 1;
}
if (c == d)
return 0;
for (i = 0; i < strlen(ESCAPED); ++i)
if (ESCAPED[i] == c)
return 0;
copy(ERR_ESC_INV, errmsg);
return 1;
}
// ------------------------- buffered input -------------------------
int ibi = 0;
int iblen = 0;
int ibtrunc = 0
/* cyclic input stream buffer
* 'ibi' is the current buffer index
* 'iblen' is the buffer length
* 'ibtrunc' is the number of characters truncated
* from first line in buffer */
char in_buff[BUFFSIZE];
/* get char from input, put it in buffer and return it
* otherwise same as getchar */
int getcharb()
{
int c;
if ((c = getchar()) == EOF)
return EOF;
ibtrunc = (iblen == BUFFSIZE && in_buff[ibi] == '\n') ? 0 : ibtrunc + 1;
in_buff[ibi] = c;
++ibi;
if (iblen < BUFFSIZE)
++iblen;
else if (ibi >= BUFFSIZE)
ibi = 0;
return c;
}
/* return ith char of buffer indexed from 'ibi'
* doesnt check validity of i */
int ithchar(int i)
{
int ri = ibi + i; // real index
return (ri < iblen) ? in_buff[ri] : in_buff[ri - iblen];
}
/* returns second last buffered input char
* if there is none return -1 */
int prevchar()
{
return (iblen > 1) ? ithchar(iblen-2) : -1;
}
/* return the (relative) index of the start of relevant context in buffer */
int context_start(int n)
{
}
// ----------------------- utility functions --------------------------
/* ignore line of input */
void ignore_line()
{
int c;
while ((c = getcharb()) != EOF && c != '\n')
;
}
/* print first line of input */
void print_line()
{
int c;
while ((c = getchar()) != EOF && c != '\n')
putchar(c);
putchar('\n');
}
/* copy from 'from' to 'to'
* 'to' must be large enough */
void copy(char from[], char to[])
{
int i;
for (i = 0; from[i] != '\0'; ++i)
to[i] = from[i];
to[i] = '\0';
}