Compare commits
21 Commits
fb131919a7
...
b0f766e725
Author | SHA1 | Date |
---|---|---|
Tibor Bizjak | b0f766e725 | |
Tibor Bizjak | d40f20afb7 | |
Tibor Bizjak | 09fb685153 | |
Tibor Bizjak | 8ebefb2974 | |
Tibor Bizjak | bd26ae43a5 | |
Tibor Bizjak | 291e9e87ec | |
Tibor Bizjak | 3fd2a66b17 | |
Tibor Bizjak | 11e44def75 | |
Tibor Bizjak | 3c529c1b9b | |
Tibor Bizjak | ff3df46f36 | |
Tibor Bizjak | ee037ecf6f | |
Tibor Bizjak | 70a6cd85ab | |
Tibor Bizjak | 2b9c7e9bcb | |
Tibor Bizjak | 44774f3582 | |
Tibor Bizjak | 4efe1541d0 | |
Tibor Bizjak | a481bec3ba | |
Tibor Bizjak | 9df28e0ec9 | |
Tibor Bizjak | ee59768555 | |
Tibor Bizjak | e6de3d1193 | |
Tibor Bizjak | bcff42f74d | |
Tibor Bizjak | b127575211 |
|
@ -16,8 +16,12 @@
|
|||
!k\&r/[0-9]*/
|
||||
# and excercise solutions
|
||||
!k\&r/*/[0-9]*.c
|
||||
!k\&r/*/[0-9]*/
|
||||
!k\&r/*/[0-9]*/*.c
|
||||
# do ignore _ prefixed files
|
||||
k\&r/**/_*
|
||||
# and header files
|
||||
!k\&r/*/*.h
|
||||
!k\&r/**/*.h
|
||||
|
||||
# ---- udemy c++ .gitignore ----
|
||||
# except udemy cpp
|
||||
|
|
|
@ -3,8 +3,10 @@
|
|||
#define STACK_H
|
||||
#define printerr(format, ...) printf("error: " format "\n", ##__VA_ARGS__)
|
||||
|
||||
/* ERROR MESSAGES */
|
||||
#define EMPTY_STACK_ERR "stack empty"
|
||||
#define SHORT_STACK_ERR "not enough elements on stack"
|
||||
#define FULL_STACK_ERR "stack full, can't push %g"
|
||||
|
||||
#ifndef MAX_STACK
|
||||
#define MAX_STACK 100
|
|
@ -4,15 +4,11 @@
|
|||
#include <assert.h>
|
||||
|
||||
#define MAX_STACK 100
|
||||
#include "04-glob-stack.h"
|
||||
#include "04-tokens.h"
|
||||
#include "global-stack.h"
|
||||
#include "tokens.h"
|
||||
|
||||
/* --------- ERROR MESSAGES */
|
||||
#define printerr(format, ...) printf("error: " format "\n", ##__VA_ARGS__)
|
||||
#define ZERODIV_ERR "zero divisor"
|
||||
#define DOMAIN_ERR "operand not in domain [%d, %d]"
|
||||
#define NEG_ERR "negative operand %g"
|
||||
#define FULL_STACK_ERR "stack full, can't push %g"
|
||||
#define UNKNOWN_TOKEN_ERR "unknown token %s"
|
||||
#define VAR_NOT_SET_ERR "variable %c has no value"
|
||||
|
||||
|
@ -192,27 +188,25 @@ char * parsef(char s[], double *x)
|
|||
int sign = SIGN(s);
|
||||
ATOI(s, *x);
|
||||
|
||||
#define X(sep) *s != sep &&
|
||||
if (DEC_SEP 1) {
|
||||
*x *= sign;
|
||||
return s;
|
||||
int exp = 0;
|
||||
/* fractional part */
|
||||
#define X(sep) *s == sep ||
|
||||
if (DEC_SEP 0) {
|
||||
s++;
|
||||
ATOI(s, *x, exp--);
|
||||
*x *= pow(10, exp);
|
||||
}
|
||||
*x *= sign;
|
||||
#undef X
|
||||
/* exponent part */
|
||||
#define X(sep) *s == sep ||
|
||||
if (EXP_SEP 0) {
|
||||
s++;
|
||||
sign = SIGN(s);
|
||||
exp = 0;
|
||||
ATOI(s, exp);
|
||||
*x *= pow(10, sign * exp);
|
||||
}
|
||||
#undef X
|
||||
s++;
|
||||
/* fractional part */
|
||||
int exp = 0;
|
||||
ATOI(s, *x, exp--);
|
||||
*x *= sign * pow(10, exp);
|
||||
|
||||
#define X(sep) *s != sep &&
|
||||
if (EXP_SEP 1)
|
||||
return s;
|
||||
#undef X
|
||||
s++;
|
||||
/* exponent */
|
||||
sign = SIGN(s);
|
||||
exp = 0;
|
||||
ATOI(s, exp);
|
||||
*x *= pow(10, sign * exp);
|
||||
return s;
|
||||
}
|
|
@ -2,6 +2,13 @@
|
|||
|
||||
#define TOKENS_H
|
||||
#include <math.h>
|
||||
#define printerr(format, ...) printf("error: " format "\n", ##__VA_ARGS__)
|
||||
|
||||
/* ERROR MESSAGES */
|
||||
#define ZERODIV_ERR "zero divisor"
|
||||
#define DOMAIN_ERR "operand not in domain [%d, %d]"
|
||||
#define NEG_ERR "negative operand %g"
|
||||
|
||||
/* --------- CALCULATOR FUNCTION TYPES */
|
||||
/* the following macros allow us to call native c constructs
|
||||
* in a declarative style */
|
||||
|
@ -18,7 +25,7 @@
|
|||
/* unary function */
|
||||
#define UNARY_FUN(F) push(F(pop()))
|
||||
/* unary function with tests */
|
||||
#define UNARY_T_FUN(F, T, ...) \
|
||||
#define UNARY_T_FUN(F, ...) \
|
||||
do { double op = pop(); __VA_ARGS__ push(F(op)); } while (0)
|
||||
/* commutative function */
|
||||
#define COMM_FUN(F) push(F(pop(), pop()))
|
||||
|
@ -89,4 +96,5 @@
|
|||
OPERATORS \
|
||||
MATH_H_BINDINGS
|
||||
|
||||
#undef printerr
|
||||
#endif // TOKENS_H
|
|
@ -0,0 +1,47 @@
|
|||
#include <stdio.h>
|
||||
|
||||
#define MAXLINE 1000 /* maximum input line length */
|
||||
|
||||
int getln(char line[], int lim);
|
||||
int strindex(char source[], char searchfor[]);
|
||||
|
||||
/* find: prints lines containing pattern, returns number of matching lines */
|
||||
int find(char *pattern, char lineno_flag, char except_flag)
|
||||
{
|
||||
char line[MAXLINE];
|
||||
int found = 0;
|
||||
long lineno;
|
||||
|
||||
for (lineno = 1; getln(line, MAXLINE) > 0; lineno++)
|
||||
if ((strindex(line, pattern) >= 0) != except_flag) {
|
||||
if (lineno_flag)
|
||||
printf("%ld:", lineno);
|
||||
printf("%s", line);
|
||||
found++;
|
||||
}
|
||||
return found;
|
||||
}
|
||||
|
||||
/* getline: get line (including \n) into s, return length */
|
||||
int getln(char *s, int lim)
|
||||
{
|
||||
int c, i = 0;
|
||||
|
||||
while (--lim > 0 && (c = getchar()) != EOF && (s[i++] = c) != '\n')
|
||||
;
|
||||
s[i] = '\0';
|
||||
return i;
|
||||
}
|
||||
|
||||
/* strindex: return index of t in s, -1 if none */
|
||||
int strindex(char s[], char t[])
|
||||
{
|
||||
int i, j, k;
|
||||
for (i = 0; s[i]; i++) {
|
||||
for (j=i, k=0; t[k] && s[j] == t[k]; j++, k++)
|
||||
;
|
||||
if (k > 0 && !t[k])
|
||||
return i;
|
||||
}
|
||||
return -1;
|
||||
}
|
|
@ -0,0 +1,132 @@
|
|||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <assert.h>
|
||||
|
||||
#define BUFF_BITS 10
|
||||
#define BUFF_SIZE (1 << BUFF_BITS)
|
||||
|
||||
/* buffered_ln: structure for buffered input line */
|
||||
struct buffered_ln {
|
||||
unsigned long lineno; /* line number */
|
||||
unsigned int len; /* line length */
|
||||
|
||||
char self[BUFF_SIZE]; /* line buffer */
|
||||
int last_char; /* last read char of line
|
||||
when equals to EOF or \n the line
|
||||
has been read to completion */
|
||||
};
|
||||
|
||||
void init_bln(struct buffered_ln *);
|
||||
int get_bln(struct buffered_ln *);
|
||||
void flush_bln(struct buffered_ln *);
|
||||
int sub_of_bln(const char *pattern, struct buffered_ln *, unsigned plen);
|
||||
|
||||
/* find: finds occurences of pattern in input lines */
|
||||
int find(char *pattern, char lineno_flag, char except_flag)
|
||||
{
|
||||
size_t plen = strlen(pattern);
|
||||
if (plen-1 > BUFF_SIZE) {
|
||||
printf("error: length of pattern > max line\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
struct buffered_ln bln;
|
||||
init_bln(&bln);
|
||||
|
||||
while (get_bln(&bln))
|
||||
if (sub_of_bln(pattern, &bln, plen) == !except_flag) {
|
||||
if (lineno_flag)
|
||||
printf("%ld:", bln.lineno);
|
||||
flush_bln(&bln);
|
||||
}
|
||||
}
|
||||
|
||||
/* init_bln: initalizes buffered line struct */
|
||||
void init_bln(struct buffered_ln *bln)
|
||||
{
|
||||
bln->lineno = 0;
|
||||
bln->len = 0;
|
||||
bln->last_char = '\n';
|
||||
}
|
||||
|
||||
#define OVERFLOW_MASK (~0 << BUFF_BITS)
|
||||
#define INDEX_MASK (~OVERFLOW_MASK)
|
||||
#define bln_i(i) ((i) & INDEX_MASK) /* casts unsigned integer i to a valid bln index */
|
||||
|
||||
#define overflowed_bln(bln) (bln->len & OVERFLOW_MASK) /* 1 if bln is overflowed */
|
||||
/* eol_bln: 1 if bln si finalized (last_char is \n or EOF) */
|
||||
#define eol_bln(bln) (bln->last_char == EOF || bln->last_char == '\n')
|
||||
#define bln_next_i(bln) bln_i(bln->len) /* next writable index of bln */
|
||||
#define bln_start_i(bln) (overflowed_bln(bln) ? bln_next_i(bln) : 0) /* starting index of bln */
|
||||
|
||||
/* getchar_bln: gets char from input and writes it to bln, returns it */
|
||||
#define getchar_bln(bln) \
|
||||
(bln->self[bln_next_i(bln)] = bln->last_char, ++bln->len, bln->last_char = getchar())
|
||||
|
||||
/* get_bln: skips current line in buffer line bln, sets bln to next line of input
|
||||
* returns 0 on EOF and a postivie value otherwise */
|
||||
int get_bln(struct buffered_ln *bln)
|
||||
{
|
||||
/* finalize previous line */
|
||||
while (!eol_bln(bln))
|
||||
bln->last_char = getchar();
|
||||
if (bln->last_char == EOF)
|
||||
return 0;
|
||||
/* init next line */
|
||||
bln->lineno++;
|
||||
bln->len = 0;
|
||||
return (bln->last_char = getchar()) != EOF;
|
||||
}
|
||||
|
||||
/* flush_bln: flushes buffered line bln to stdout */
|
||||
void flush_bln(struct buffered_ln *bln)
|
||||
{
|
||||
unsigned i;
|
||||
/* print overflowed chars */
|
||||
if (overflowed_bln(bln)) {
|
||||
for (i = BUFF_SIZE; i < bln->len; i++)
|
||||
putchar('.');
|
||||
for (i = bln_next_i(bln); i < BUFF_SIZE; i++)
|
||||
putchar(bln->self[i]);
|
||||
}
|
||||
/* print buffered chars */
|
||||
for (i = 0; i < bln_next_i(bln); i++)
|
||||
putchar(bln->self[i]);
|
||||
/* print not yet read chars */
|
||||
for (; !eol_bln(bln); bln->last_char = getchar())
|
||||
putchar(bln->last_char);
|
||||
putchar('\n');
|
||||
}
|
||||
|
||||
/* sub_of_bln: returns 0 if pattern with length plen is not a substring of
|
||||
* buffered line bln and a positive value otherwise */
|
||||
int sub_of_bln(const char *pattern, struct buffered_ln *bln, const unsigned plen)
|
||||
{
|
||||
/* buffered line must not be overflowed */
|
||||
assert(!overflowed_bln(bln));
|
||||
|
||||
/* fill buffer with plen-1 chars */
|
||||
for (; bln->len < plen-1; getchar_bln(bln))
|
||||
if (eol_bln(bln))
|
||||
return 0;
|
||||
|
||||
unsigned i, j;
|
||||
int k;
|
||||
/* handle buffered chars */
|
||||
for (i = plen-1; i < bln->len; i++) {
|
||||
for (j = i, k = plen-1; k >= 0 && bln->self[j] == pattern[k]; k--, j--)
|
||||
;
|
||||
if (k < 0)
|
||||
return 1;
|
||||
}
|
||||
/* handle no yet read chars */
|
||||
for (; !eol_bln(bln); getchar_bln(bln)) {
|
||||
if (bln->last_char != pattern[plen-1])
|
||||
continue;
|
||||
for (j = bln_i(bln_next_i(bln)-1), k = plen-2; k >=0 && bln->self[j] == pattern[k]; k--, j = bln_i(j-1))
|
||||
;
|
||||
if (k < 0)
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
|
@ -0,0 +1,63 @@
|
|||
#include <stdio.h>
|
||||
|
||||
/* compile with find-no-overflow.c or find-opt.c
|
||||
* gcc main.c [find-no-overflow.c | find-opt.c] */
|
||||
|
||||
int find(char *pattern, char lineno_flag, char except_flag);
|
||||
|
||||
#define ARG_FLAGS X('n', lineno) X('x', except)
|
||||
|
||||
/* find pattern given by first arg in lines and print them
|
||||
* takes optional flags
|
||||
* -x : print all except matching
|
||||
* -n : print line numbers */
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
int i;
|
||||
char c;
|
||||
|
||||
/* declare flag variables */
|
||||
#define X(c, flag) char flag##_flag = 0;
|
||||
ARG_FLAGS
|
||||
#undef X
|
||||
char **parg = argv;
|
||||
/* parse flag arguments */
|
||||
for (i = 1; *++parg; ) {
|
||||
if (**parg != '-' || !(*parg)[1]) {
|
||||
argv[i++] = *parg;
|
||||
continue;
|
||||
}
|
||||
while (c = *++parg[0])
|
||||
switch (c) {
|
||||
#define X(C, flag) case C: flag##_flag = 1; break;
|
||||
ARG_FLAGS
|
||||
#undef X
|
||||
default:
|
||||
printf("error: illegal option -%c\n", c);
|
||||
argc = 0;
|
||||
break;
|
||||
}
|
||||
--argc;
|
||||
}
|
||||
|
||||
/* illegal arguments */
|
||||
if (argc != 2) {
|
||||
printf("usage: find ");
|
||||
#define X(c, _) printf("[-%c] ", c);
|
||||
ARG_FLAGS
|
||||
#undef X
|
||||
printf("pattern\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
char *pattern = argv[1];
|
||||
/* verify pattern */
|
||||
for (i = 0; (c = pattern[i]) != '\0'; i++)
|
||||
if (c == '\n') {
|
||||
printf("error: newline in pattern\n");
|
||||
return -2;
|
||||
}
|
||||
|
||||
int found = find(pattern, lineno_flag, except_flag);
|
||||
return found;
|
||||
}
|
|
@ -1,118 +0,0 @@
|
|||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <math.h>
|
||||
#include <assert.h>
|
||||
|
||||
int grep(char pattern[]);
|
||||
|
||||
/* grep with graceful buffer overflow */
|
||||
/* parse and verify arg pattern, pass it to grep */
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
/* verify arg is given */
|
||||
if (argc < 2) {
|
||||
printf("error: excpected pattern\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
char *pattern = argv[1];
|
||||
|
||||
/* verify pattern */
|
||||
char c;
|
||||
int i;
|
||||
for (i = 0; (c = pattern[i]) != '\0'; i++)
|
||||
if (c == '\n') {
|
||||
printf("error: newline in pattern\n");
|
||||
return -2;
|
||||
}
|
||||
|
||||
int found = grep(pattern);
|
||||
printf("found = %d\n", found);
|
||||
return found;
|
||||
}
|
||||
|
||||
void println(void);
|
||||
int flush_lnbuff(void);
|
||||
int getch_lnbuff(void);
|
||||
|
||||
/* grep: prints lines containing pattern, returns number of matching lines */
|
||||
int grep(char *pattern)
|
||||
{
|
||||
int found, i, c;
|
||||
const int plen = strlen(pattern);
|
||||
|
||||
i = found = 0;
|
||||
|
||||
while ((c = getch_lnbuff()) != EOF)
|
||||
if (c != pattern[i])
|
||||
i = 0;
|
||||
else if (++i == plen) { // found match
|
||||
i = 0;
|
||||
found++;
|
||||
flush_lnbuff();
|
||||
println();
|
||||
}
|
||||
return found;
|
||||
}
|
||||
|
||||
/* println: prints next line from stdin
|
||||
* prints newline on EOF */
|
||||
void println()
|
||||
{
|
||||
int c;
|
||||
while ((c = getchar()) != EOF && c != '\n')
|
||||
putchar(c);
|
||||
putchar(c);
|
||||
}
|
||||
|
||||
/* ------------------------ line buffer ---------------------- */
|
||||
|
||||
#define LNBUFF_LEN 128
|
||||
|
||||
/* the line buffer lenght must be a power of two */
|
||||
static_assert(!(LNBUFF_LEN % 2), "Line buffer length is not a power of two!");
|
||||
|
||||
/* line_buffer: global overflowing line buffer */
|
||||
struct {
|
||||
char self[LNBUFF_LEN];
|
||||
unsigned len;
|
||||
} lnbuff = {.len= 0};
|
||||
|
||||
/* LNBUFF_I: current index in line buffer */
|
||||
#define LNBUFF_I (lnbuff.len & (LNBUFF_LEN - 1))
|
||||
|
||||
/* getch_lnbuff: getchar and add it to buffer */
|
||||
int getch_lnbuff()
|
||||
{
|
||||
int c = getchar();
|
||||
|
||||
if (c == EOF || c == '\n') // new line
|
||||
lnbuff.len = 0;
|
||||
else {
|
||||
lnbuff.self[LNBUFF_I] = c;
|
||||
lnbuff.len++;
|
||||
}
|
||||
|
||||
return c;
|
||||
}
|
||||
|
||||
/* flush_lnbuff: print contents of line buffer, return length */
|
||||
int flush_lnbuff()
|
||||
{
|
||||
int i;
|
||||
|
||||
/* handle overflowing chars */
|
||||
if (lnbuff.len > LNBUFF_LEN) {
|
||||
for (i = LNBUFF_LEN; i < lnbuff.len; i++)
|
||||
putchar('.');
|
||||
for (i = LNBUFF_I; i < LNBUFF_LEN; i++)
|
||||
putchar(lnbuff.self[i]);
|
||||
}
|
||||
/* handle rest of chars */
|
||||
for (i = 0; i < LNBUFF_I; i++)
|
||||
putchar(lnbuff.self[i]);
|
||||
|
||||
i = lnbuff.len;
|
||||
lnbuff.len = 0;
|
||||
return i;
|
||||
}
|
|
@ -1,15 +0,0 @@
|
|||
#include <stdio.h>
|
||||
|
||||
#define W 80
|
||||
#define REPEAT 4000000
|
||||
|
||||
int main()
|
||||
{
|
||||
int i, j;
|
||||
for (i = 0; i < REPEAT; i++) {
|
||||
for (j = 0; j < W; j++)
|
||||
putchar('y');
|
||||
putchar('\n');
|
||||
}
|
||||
return 0;
|
||||
}
|
|
@ -1,75 +0,0 @@
|
|||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#define MAXLINE 1000 /* maximum input line length */
|
||||
|
||||
int grep(char *pattern);
|
||||
|
||||
/* somewhat optimized book version of grep */
|
||||
/* find all lines matching pattern */
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
/* verify arg is given */
|
||||
if (argc < 2) {
|
||||
printf("error: excpected pattern\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
char *pattern = argv[1];
|
||||
|
||||
/* verify pattern */
|
||||
char c;
|
||||
int i;
|
||||
for (i = 0; (c = pattern[i]) != '\0'; i++)
|
||||
if (c == '\n') {
|
||||
printf("error: newline in pattern\n");
|
||||
return -2;
|
||||
}
|
||||
|
||||
int found = grep(pattern);
|
||||
printf("found = %d\n", found);
|
||||
return found;
|
||||
}
|
||||
|
||||
int getln(char line[], int lim);
|
||||
int strindex(char source[], char searchfor[], int slen);
|
||||
|
||||
/* grep: prints lines containing pattern, returns number of matching lines */
|
||||
int grep(char *pattern)
|
||||
{
|
||||
char line[MAXLINE];
|
||||
int found = 0;
|
||||
int slen = strlen(pattern);
|
||||
|
||||
while (getln(line, MAXLINE) > 0)
|
||||
if (strindex(line, pattern, slen) >= 0) {
|
||||
printf("%s", line);
|
||||
found++;
|
||||
}
|
||||
return found;
|
||||
}
|
||||
|
||||
/* getline: get line (including \n) into s, return length */
|
||||
int getln(char *s, int lim)
|
||||
{
|
||||
int c, i = 0;
|
||||
|
||||
while (--lim > 0 && (c = getchar()) != EOF && (s[i++] = c) != '\n')
|
||||
;
|
||||
s[i] = '\0';
|
||||
return i;
|
||||
}
|
||||
|
||||
/* strindex: return index of t in s, -1 if none */
|
||||
int strindex(char s[], char t[], int slen)
|
||||
{
|
||||
int i, j;
|
||||
|
||||
for (i = j = 0; s[i]; i++)
|
||||
if (s[i] != t[j])
|
||||
j = 0;
|
||||
else if (++j == slen) { // found match
|
||||
return i - slen + 1;
|
||||
}
|
||||
return -1;
|
||||
}
|
|
@ -0,0 +1,101 @@
|
|||
#include <stdio.h>
|
||||
#include <ctype.h>
|
||||
#include <assert.h>
|
||||
#include <math.h>
|
||||
|
||||
int getint(int *p);
|
||||
int getfloat(float *p);
|
||||
|
||||
/* ungetchar: push char c back to input stream */
|
||||
#define ungetchar(c) ungetc(c, stdin)
|
||||
|
||||
|
||||
/* tests getfloat, prints input to output, puts valid numbers
|
||||
* in brackets : n -> [n] */
|
||||
int main()
|
||||
{
|
||||
float x;
|
||||
int r;
|
||||
while ((r = getfloat(&x)) != EOF)
|
||||
if (!r) {
|
||||
int c;
|
||||
putchar(getchar());
|
||||
while (!isdigit(c = getchar()) && c != EOF && c != '-' && c != '+')
|
||||
putchar(c);
|
||||
ungetchar(c);
|
||||
} else
|
||||
printf("[%g]", x);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* we assert that EOF is negative */
|
||||
static_assert(EOF < 0, "EOF is not a negative number");
|
||||
|
||||
/* ugetint: gets unsigned int from input to n
|
||||
* n must be intialized by caller
|
||||
* takes optional arguments for loop increment
|
||||
* last char read is stored in varvar_c */
|
||||
#define ugetint(var_c, n, ...) \
|
||||
do { \
|
||||
for (; isdigit(var_c = getchar()); __VA_ARGS__) \
|
||||
n = 10 * (n) + var_c - '0'; \
|
||||
} while (0)
|
||||
|
||||
/* getint : gets int from input and overwrites it to p
|
||||
* returns 1 on valid integer, 0 if no integer is found
|
||||
* and EOF on EOF. */
|
||||
int getint(int *p)
|
||||
{
|
||||
int c;
|
||||
if ((c = getchar()) == EOF)
|
||||
return EOF;
|
||||
|
||||
/* handle sign */
|
||||
int sign = (c == '-') ? -1 : ((c == '+') ? 1 : 0);
|
||||
if (sign)
|
||||
c = getchar();
|
||||
if (!isdigit(c)) { /* not a number */
|
||||
ungetchar(c);
|
||||
if (sign)
|
||||
ungetchar((sign > 0) ? '+' : '-');
|
||||
return 0;
|
||||
}
|
||||
|
||||
*p = c - '0';
|
||||
ugetint(c, *p);
|
||||
ungetchar(c);
|
||||
*p *= (sign) ? sign : 1;
|
||||
return 1;
|
||||
}
|
||||
|
||||
#define DEC_SEP X('.') X(',')
|
||||
#define EXP_SEP X('e') X('E')
|
||||
|
||||
/* getfloat : gets float from input and overwrites it to p
|
||||
* returns 1 on valid integer, 0 if no integer is found
|
||||
* and EOF on EOF. */
|
||||
int getfloat(float *p)
|
||||
{
|
||||
char flag;
|
||||
int n;
|
||||
if ((flag = getint(&n)) < 1) /* not a number */
|
||||
return flag;
|
||||
*p = n;
|
||||
|
||||
int exp, c = getchar();
|
||||
/* fractional part */
|
||||
#define X(C) c == C ||
|
||||
if (DEC_SEP 0) {
|
||||
n = exp = 0;
|
||||
ugetint(c, n, exp--);
|
||||
*p += n * pow(10, exp);
|
||||
}
|
||||
#undef X
|
||||
/* exponent part */
|
||||
#define X(C) c == C ||
|
||||
if ((EXP_SEP 0) && getint(&exp)) {
|
||||
*p *= pow(10, exp);
|
||||
} else
|
||||
ungetchar(c);
|
||||
return 1;
|
||||
}
|
|
@ -0,0 +1,40 @@
|
|||
#include <stdio.h>
|
||||
|
||||
char *strcat(char *s, const char *t);
|
||||
char *strcpy(char *t, const char *s);
|
||||
size_t strlen(const char *s);
|
||||
|
||||
/* passes args to strcat, prints result */
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
if (argc < 3)
|
||||
return 1;
|
||||
char s[strlen(argv[1]) + strlen(argv[2])];
|
||||
strcat(strcpy(s, argv[1]), argv[2]);
|
||||
printf("%s\n", s);
|
||||
}
|
||||
|
||||
/* strcat: concat string t to end of string s */
|
||||
char *strcat(char *s, const char *t)
|
||||
{
|
||||
int slen = strlen(s);
|
||||
return strcpy(s + slen, t) - slen;
|
||||
}
|
||||
|
||||
/* strcpy: copy string s to t */
|
||||
char *strcpy(char *t, const char *s)
|
||||
{
|
||||
char *tc = t;
|
||||
while ((*t++ = *s++))
|
||||
;
|
||||
return tc;
|
||||
}
|
||||
|
||||
/* strlen: return length of string s (without \0) */
|
||||
size_t strlen(const char *s)
|
||||
{
|
||||
const char *sc = s;
|
||||
while (*s++)
|
||||
;
|
||||
return s - sc - 1;
|
||||
}
|
|
@ -0,0 +1,21 @@
|
|||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
int strend(const char *s, const char *t);
|
||||
|
||||
/* passes args to strend, prints result */
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
if (argc < 3)
|
||||
return 1;
|
||||
printf("%s\n", (strend(argv[1], argv[2])) ? "true" : "false");
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* strend: returns 1 if t == end of s otherwise false */
|
||||
int strend(const char *s, const char *t)
|
||||
{
|
||||
size_t s_len = strlen(s);
|
||||
size_t t_len = strlen(t);
|
||||
return (s_len >= t_len) && !strcmp(s + s_len - t_len, t);
|
||||
}
|
|
@ -0,0 +1,64 @@
|
|||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
char *strncpy(char *t, const char *s, size_t n);
|
||||
char *strncat(char *t, const char *s, size_t n);
|
||||
int strncmp(const char *s, const char *t, size_t n);
|
||||
|
||||
/* strlen: returns string length (w/o '\0') */
|
||||
size_t strlen(const char *s)
|
||||
{
|
||||
const char * const sc = s;
|
||||
while (*s++)
|
||||
;
|
||||
return s - sc - 1;
|
||||
}
|
||||
|
||||
/* takes args s1, s2, n and passes them to the above declared
|
||||
* functions, prints the results */
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
if (argc < 4)
|
||||
return 1;
|
||||
|
||||
int n = atoi(argv[3]);
|
||||
char s[strlen(argv[1]) + strlen(argv[2]) + 1];
|
||||
/* strncpy */
|
||||
printf("strncpy: %s\n", strncpy(s, argv[1], n));
|
||||
/* strncat */
|
||||
printf("strncat: %s\n", strncat(s, argv[2], n));
|
||||
/* strncmp */
|
||||
int comp = strncmp(argv[1], argv[2], n);
|
||||
printf("strncmp: %.*s ", n, argv[1]);
|
||||
putchar((comp > 0) ? '>' : (comp < 0) ? '<' : '=');
|
||||
printf(" %.*s\n", n, argv[2]);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* strncpy: copies at most n chars from s to t, returns t*/
|
||||
char *strncpy(char *t, const char *s, size_t n)
|
||||
{
|
||||
char * const tc = t;
|
||||
while (n-- && (*t++ = *s++))
|
||||
;
|
||||
*t = '\0';
|
||||
return tc;
|
||||
}
|
||||
|
||||
/* strncat: concats at most n chars of s to t, returns t */
|
||||
char *strncat(char *t, const char *s, size_t n)
|
||||
{
|
||||
strncpy(t + strlen(t), s, n);
|
||||
return t;
|
||||
}
|
||||
|
||||
/* strncmp: compares at most n chars of s and t */
|
||||
int strncmp(const char *s, const char *t, size_t n)
|
||||
{
|
||||
if (!n)
|
||||
return 0;
|
||||
while (--n && *s && (*s == *t))
|
||||
s++, t++;
|
||||
return *s - *t;
|
||||
}
|
|
@ -0,0 +1,109 @@
|
|||
#include <stdio.h>
|
||||
|
||||
/* array bounds */
|
||||
#define MAXLINES 100
|
||||
#define BUFF_SIZE (80 * MAXLINES)
|
||||
|
||||
int readlines(char *lines[], int maxlines, char *ln_buff, size_t lb_size);
|
||||
void writelines(char *lines[], int n);
|
||||
void qsort_string(char *v[], int left, int right);
|
||||
|
||||
/* sorts lines from stdin and prints them */
|
||||
int main()
|
||||
{
|
||||
char *lines[MAXLINES];
|
||||
char buffer[BUFF_SIZE];
|
||||
|
||||
int line_count = readlines(lines, MAXLINES, buffer, BUFF_SIZE);
|
||||
if (line_count < 0) {
|
||||
line_count = -line_count - 1;
|
||||
printf("warning: buffer overflow occured, read %d lines\n", line_count);
|
||||
} else if (line_count > MAXLINES) {
|
||||
line_count = MAXLINES;
|
||||
printf("warning: too many lines, read %d lines\n", line_count);
|
||||
}
|
||||
qsort_string(lines, 0, line_count-1);
|
||||
writelines(lines, line_count);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* ---------- reading/printing functions */
|
||||
#include <assert.h>
|
||||
#include <ctype.h>
|
||||
|
||||
/* writelines: prints n lines */
|
||||
void writelines(char *lines[], int n)
|
||||
{
|
||||
while (n--)
|
||||
printf("%s\n", *lines++);
|
||||
}
|
||||
|
||||
/* readlines: reads lines from input, writing them to ln_buff
|
||||
* and line pointers to lines.
|
||||
* returns number of lines read,
|
||||
* -lines_read-1 < 0 on buffer overflow
|
||||
* maxlines+1 on lines overflow */
|
||||
int readlines(char *lines[], int maxlines, char *buffer, size_t buff_size)
|
||||
{
|
||||
assert(maxlines > 0);
|
||||
char ** const fst_line = lines;
|
||||
int c, not_empty = 0;
|
||||
|
||||
for (*lines = buffer; (c = getchar()) != EOF && buff_size; --buff_size) {
|
||||
not_empty |= !isspace(c);
|
||||
if (c == '\n') {
|
||||
if (!not_empty) { /* skip empty lines */
|
||||
buff_size += buffer - *lines;
|
||||
buffer = *lines;
|
||||
continue;
|
||||
}
|
||||
not_empty = 0;
|
||||
*buffer++ = '\0';
|
||||
if (!--maxlines)
|
||||
break;
|
||||
*++lines = buffer;
|
||||
} else
|
||||
*buffer++ = c;
|
||||
}
|
||||
/* ignore trailing whitespace and empty lines */
|
||||
while (c != EOF && isspace(c))
|
||||
c = getchar();
|
||||
if (c != EOF && !buff_size) /* buffer overflow, return -lines_read-1 */
|
||||
return fst_line - lines - 1;
|
||||
if (c != EOF && !maxlines) /* lines overflow, return maxlines+1 */
|
||||
return lines - fst_line + 2;
|
||||
return lines - fst_line + not_empty;
|
||||
}
|
||||
|
||||
/* ---------- string quicksort */
|
||||
#include <string.h>
|
||||
|
||||
void swap(char *v[], int i, int j);
|
||||
|
||||
/* qsort_string: sort v[left]...v[right] into increasing order */
|
||||
void qsort_string(char *v[], int left, int right)
|
||||
{
|
||||
int i, last;
|
||||
|
||||
if (left >= right) /* do nothing if array contains */
|
||||
return; /* fewer than two elements */
|
||||
swap(v, left, (left + right)/2); /* move partition elem */
|
||||
last = left; /* to v[0] */
|
||||
|
||||
for (i = left+1; i <= right; i++) /* partition */
|
||||
if (strcmp(v[i], v[left]) < 0)
|
||||
swap(v, ++last, i);
|
||||
swap(v, left, last); /* restore partition elem */
|
||||
|
||||
qsort_string(v, left, last-1);
|
||||
qsort_string(v, last+1, right);
|
||||
}
|
||||
|
||||
/* swap: swap v[i] and v[j] */
|
||||
void swap(char *v[], int i, int j)
|
||||
{
|
||||
char *temp = v[i];
|
||||
v[i] = v[j], v[j] = temp;
|
||||
}
|
||||
|
||||
|
|
@ -0,0 +1,68 @@
|
|||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#define HELP_STR "usage: name year [month] day"
|
||||
|
||||
int month_day(int year, int day, int *pmonth);
|
||||
int day_of_year(int year, int month, int day);
|
||||
|
||||
/* converts arguments year yearday to year month day or
|
||||
* year month day to year yearday */
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
int y, m, d, yd;
|
||||
if (argc == 3) { /* year day -> month day */
|
||||
y = atoi(argv[1]), yd = atoi(argv[2]);
|
||||
if ((d = month_day(y, yd, &m))) {
|
||||
printf("%d %d %d\n", y, m, d);
|
||||
return 0;
|
||||
}
|
||||
printf("error: invalid yearday %d\n", yd);
|
||||
} else if (argc == 4) { /* year month day -> year day */
|
||||
y = atoi(argv[1]), m = atoi(argv[2]), d = atoi(argv[3]);
|
||||
if ((yd = day_of_year(y, m, d))) {
|
||||
printf("%d %d\n", y, yd);
|
||||
return 0;
|
||||
}
|
||||
printf("error: invalid month %d or day %d\n", m, d);
|
||||
}
|
||||
puts(HELP_STR);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static char daytab[][13] = {
|
||||
{0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31},
|
||||
{0, 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}
|
||||
};
|
||||
|
||||
#define IS_LEAP(Y) (Y%4 == 0 && Y%100 != 0 || Y%400 == 0)
|
||||
#define IS_MONTH(M) (0 < M && M <= 12)
|
||||
#define IS_D_OF_M(LEAP, M, D) (0 < D && D <= daytab[LEAP][M])
|
||||
#define IS_YD_OF_Y(LEAP, YD) (0 < YD && YD <= 365+LEAP)
|
||||
|
||||
/* day_of_year: set day of year from month & day
|
||||
* return day of year or 0 on error */
|
||||
int day_of_year(int year, int month, int day)
|
||||
{
|
||||
int m, leap = IS_LEAP(year);
|
||||
if (!IS_MONTH(month) || !IS_D_OF_M(leap, month, day))
|
||||
/* validity check */
|
||||
return 0;
|
||||
for (m = 1; m < month; m++)
|
||||
day += daytab[leap][m];
|
||||
return day;
|
||||
}
|
||||
|
||||
/* month_day: set month, day from day of year
|
||||
* return day of month or 0 on error, set pmonth to month */
|
||||
int month_day(int year, int yearday, int *pmonth)
|
||||
{
|
||||
int m, leap = IS_LEAP(year);
|
||||
if (!IS_YD_OF_Y(leap, yearday)) /* validity check */
|
||||
return 0;
|
||||
for (m = 1; yearday > daytab[leap][m]; m++)
|
||||
yearday -= daytab[leap][m];
|
||||
*pmonth = m;
|
||||
return yearday;
|
||||
}
|
||||
|
|
@ -5,10 +5,12 @@
|
|||
|
||||
namespace Ad
|
||||
{
|
||||
namespace Constants
|
||||
namespace Consts
|
||||
{
|
||||
|
||||
constexpr std::int32_t EGO_VEHICLE_ID = -1;
|
||||
constexpr std::size_t VEHICLES_PER_LANE = 2;
|
||||
constexpr std::int8_t VISUALIZE_STEP = 20;
|
||||
|
||||
} // namespace Constants
|
||||
} // namespace Ad
|
||||
|
|
|
@ -1,6 +1,8 @@
|
|||
#include <cmath>
|
||||
#include <cstdint>
|
||||
#include <iostream>
|
||||
#include <random>
|
||||
#include <algorithm>
|
||||
|
||||
#include "AdConstants.h"
|
||||
#include "AdFunctions.h"
|
||||
|
@ -10,6 +12,7 @@ namespace Ad
|
|||
namespace Utils
|
||||
{
|
||||
|
||||
/* kph_to_mps: converts kmph to meters/second */
|
||||
constexpr float kph_to_mps(const float kph)
|
||||
{
|
||||
return 0.2778 * kph;
|
||||
|
@ -20,26 +23,131 @@ constexpr float kph_to_mps(const float kph)
|
|||
namespace Data
|
||||
{
|
||||
|
||||
/* init_ego_vehicle: initializes ego vehicle */
|
||||
Types::Vehicle init_ego_vehicle()
|
||||
{
|
||||
return Types::Vehicle{
|
||||
.id = Constants::EGO_VEHICLE_ID,
|
||||
.id = Consts::EGO_VEHICLE_ID,
|
||||
.lane = Types::Lane::Center,
|
||||
.speed_mps = Utils::kph_to_mps(135),
|
||||
.rel_distance_m = 0,
|
||||
.rel_dist_m = 0,
|
||||
};
|
||||
}
|
||||
|
||||
/* init_vehicle_array: initialize an array of vehicles */
|
||||
template <std::size_t N>
|
||||
static void init_vehicle_array(std::array<Types::Vehicle, N> &arr, int32_t start_id, Types::Lane lane)
|
||||
{
|
||||
/* init random generators */
|
||||
std::mt19937 rng(std::random_device{}());
|
||||
std::uniform_real_distribution<double> speed(-150, 150);
|
||||
std::uniform_real_distribution<double> dist_gen(0, Consts::VISUALIZE_STEP);
|
||||
|
||||
double dist = static_cast<double> (-Consts::VISUALIZE_STEP) * (arr.size() / 2 + 1);
|
||||
|
||||
for (int32_t i = 0; i < arr.size(); i++)
|
||||
arr[i] = Types::Vehicle{
|
||||
.id = start_id++,
|
||||
.lane = lane,
|
||||
.speed_mps = Utils::kph_to_mps(speed(rng)),
|
||||
.rel_dist_m = (dist += Consts::VISUALIZE_STEP + dist_gen(rng))
|
||||
};
|
||||
}
|
||||
|
||||
/* init_vehicles: initializes vehicles */
|
||||
Types::NeighborVehicles init_vehicles()
|
||||
{
|
||||
auto nv = Types::NeighborVehicles{};
|
||||
|
||||
int32_t id = 0;
|
||||
init_vehicle_array(nv.left_lane, id, Types::Lane::Left);
|
||||
init_vehicle_array(nv.center_lane, (id += nv.left_lane.size()), Types::Lane::Center);
|
||||
init_vehicle_array(nv.right_lane, (id += nv.right_lane.size()), Types::Lane::Right);
|
||||
|
||||
return nv;
|
||||
}
|
||||
|
||||
|
||||
|
||||
} // namespace Ad::Data
|
||||
|
||||
namespace Visualize
|
||||
{
|
||||
|
||||
void print_vehicle(const Types::Vehicle vehicle)
|
||||
/* print_lane: prints lane, helper function for print vehicle */
|
||||
void print_lane(const Types::Lane lane)
|
||||
{
|
||||
#define if_lane(LANE) if (lane == Types::Lane::LANE) std::cout << #LANE; else
|
||||
if_lane(Left)
|
||||
if_lane(Center)
|
||||
if_lane(Right)
|
||||
/* else */
|
||||
std::cout << "Unknown";
|
||||
}
|
||||
|
||||
/* print_vehicle: prints vehicle */
|
||||
void print_vehicle(const Types::Vehicle &vehicle)
|
||||
{
|
||||
std::cout << "Vehicle " << vehicle.id << '\n';
|
||||
std::cout << "Lane : ";
|
||||
print_lane(vehicle.lane);
|
||||
std::cout << '\n';
|
||||
std::cout << "speed : " << vehicle.speed_mps << " m/s\n";
|
||||
std::cout << "distance : " << vehicle.rel_distance_m << " m\n";
|
||||
std::cout << "distance : " << vehicle.rel_dist_m << " m\n";
|
||||
}
|
||||
|
||||
/* print_vehicle_array: helper function for print_neghbor_vehicles */
|
||||
template <size_t N>
|
||||
static void print_vehicle_array(const std::array<Types::Vehicle, N> &arr)
|
||||
{
|
||||
for (int32_t i = 0; i < arr.size(); i++) {
|
||||
print_vehicle(arr[i]);
|
||||
std::cout << '\n';
|
||||
}
|
||||
}
|
||||
|
||||
/* print_neghbor_vehicles: print neghbor vehicles information */
|
||||
void print_neighbor_vehicles(const Types::NeighborVehicles &vehicles)
|
||||
{
|
||||
print_vehicle_array(vehicles.left_lane);
|
||||
print_vehicle_array(vehicles.center_lane);
|
||||
print_vehicle_array(vehicles.right_lane);
|
||||
}
|
||||
|
||||
/* print_scene: prints scene
|
||||
* very rough implementation */
|
||||
void print_scene(const Types::Vehicle &ego_vehicle,
|
||||
const Types::NeighborVehicles &vehicles)
|
||||
{
|
||||
/* TODO : sort NeighborVehicles arrays */
|
||||
double min_dist_d = std::min({vehicles.left_lane[0].rel_dist_m,
|
||||
vehicles.center_lane[0].rel_dist_m,
|
||||
vehicles.right_lane[0].rel_dist_m});
|
||||
|
||||
double max_dist_d = std::max({vehicles.left_lane.back().rel_dist_m,
|
||||
vehicles.center_lane.back().rel_dist_m,
|
||||
vehicles.right_lane.back().rel_dist_m});
|
||||
|
||||
int32_t min_dist = std::floor(min_dist_d / Consts::VISUALIZE_STEP) * Consts::VISUALIZE_STEP;
|
||||
int32_t max_dist = std::ceil(max_dist_d / Consts::VISUALIZE_STEP) * Consts::VISUALIZE_STEP;
|
||||
|
||||
int32_t li, ci, ri, count;
|
||||
li = ci = ri = Consts::VEHICLES_PER_LANE - 1;
|
||||
std::cout << " L C R\n";
|
||||
for (int32_t dist = max_dist; dist >= min_dist; dist -= Consts::VISUALIZE_STEP) {
|
||||
printf("%8d| ", dist);
|
||||
char c;
|
||||
#define HANDLE_LANE(lane, li) \
|
||||
for (count = 0; li >= 0 && vehicles.lane[li].rel_dist_m >= dist-Consts::VISUALIZE_STEP; count++, li--) \
|
||||
; \
|
||||
c = !count ? ' ' : (count > 1) ? '0' + count : (vehicles.lane[li+1].speed_mps >= 0) ? 'v' : '^'; \
|
||||
std::cout << c << " | "
|
||||
HANDLE_LANE(left_lane, li);
|
||||
HANDLE_LANE(center_lane, ci);
|
||||
HANDLE_LANE(right_lane, ri);
|
||||
std::cout << '\n';
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
} // namespace Ad::Visualize
|
||||
|
|
|
@ -11,12 +11,18 @@ namespace Utils
|
|||
|
||||
namespace Data
|
||||
{
|
||||
Types::Vehicle init_ego_vehicle();
|
||||
Types::Vehicle init_ego_vehicle();
|
||||
Types::NeighborVehicles init_vehicles();
|
||||
} // namespace Ad::Data
|
||||
|
||||
namespace Visualize
|
||||
{
|
||||
void print_vehicle(const Types::Vehicle vehicle);
|
||||
} // namespace Ad::Visualize
|
||||
void print_vehicle(const Types::Vehicle &vehicle);
|
||||
|
||||
void print_neighbor_vehicles(const Types::NeighborVehicles &vehicles);
|
||||
|
||||
void print_scene(const Types::Vehicle &ego_vehicle,
|
||||
const Types::NeighborVehicles &vehicles);
|
||||
|
||||
} // namespace Ad::Visualize
|
||||
} // namespace Ad
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
#pragma once
|
||||
|
||||
#include <cstdint>
|
||||
#include <array>
|
||||
|
||||
#include "AdConstants.h"
|
||||
|
||||
|
@ -22,7 +23,14 @@ struct Vehicle
|
|||
std::int32_t id;
|
||||
Lane lane;
|
||||
double speed_mps;
|
||||
double rel_distance_m;
|
||||
double rel_dist_m;
|
||||
};
|
||||
|
||||
struct NeighborVehicles
|
||||
{
|
||||
std::array<Vehicle, Consts::VEHICLES_PER_LANE> left_lane;
|
||||
std::array<Vehicle, Consts::VEHICLES_PER_LANE> center_lane;
|
||||
std::array<Vehicle, Consts::VEHICLES_PER_LANE> right_lane;
|
||||
};
|
||||
|
||||
} // namespace Ad::Types
|
||||
|
|
|
@ -8,7 +8,14 @@
|
|||
int main()
|
||||
{
|
||||
auto ego_vehicle = Ad::Data::init_ego_vehicle();
|
||||
auto vehicles = Ad::Data::init_vehicles();
|
||||
|
||||
Ad::Visualize::print_vehicle(ego_vehicle);
|
||||
std::cout << '\n';
|
||||
|
||||
Ad::Visualize::print_neighbor_vehicles(vehicles);
|
||||
|
||||
Ad::Visualize::print_scene(ego_vehicle, vehicles);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue