diff --git a/.gitignore b/.gitignore index b43bd4b..1d9cc1f 100644 --- a/.gitignore +++ b/.gitignore @@ -4,3 +4,4 @@ tests/*_tests tests/*.log build +tests/leetcode/*_tests diff --git a/Makefile b/Makefile index c32e854..49876f1 100644 --- a/Makefile +++ b/Makefile @@ -1,17 +1,20 @@ -CFLAGS=-g -O2 -Wall -Wextra -Isrc -rdynamic -DNDEBUG $(OPTFLAGS) +CC=gcc +CFLAGS=-g -std=c99 -O0 -Wall -Wextra -Isrc -rdynamic -DNDEBUG $(OPTFLAGS) LDFLAGS=$(OPTLIBS) PREFIX?=/usr/local SOURCES=$(wildcard src/**/*.c src/*.c) OBJECTS=$(patsubst %.c,%.o,$(SOURCES)) -TEST_SRC=$(wildcard tests/*_tests.c) +TEST_SRC=$(wildcard tests/*_tests.c tests/leetcode/*_tests.c) TESTS=$(patsubst %.c,%,$(TEST_SRC)) +TESTAREA=lcthw +TESTSUIT=all TARGET=build/liblcthw.a OS=$(shell lsb_release -si) -ifeq ($(OS),Ubuntu) +ifeq ($(OS),CentOS) LDLIBS=-llcthw -lbsd -L./build -lm endif @@ -22,7 +25,7 @@ dev: CFLAGS=-g -Wall -Isrc -Wall -Wextra $(OPTFLAGS) dev: all $(TARGET): CFLAGS += -fPIC -$(TARGET): build $(OBJECTS) +$(TARGET): build cleanobj $(OBJECTS) ar rcs $@ $(OBJECTS) ranlib $@ @@ -30,11 +33,18 @@ build: @mkdir -p build @mkdir -p bin +cleanobj: + @echo clean test object and bin + @if [[ "$(TESTSUIT)" != "all" ]];then rm -rf src/$(TESTAREA)/$(TESTSUIT).o;fi + @if [[ "$(TESTSUIT)" != "all" ]];then rm -rf tests/$(TESTAREA)/$(TESTSUIT)_tests;fi + + # The Unit Tests +# eg: make TESTAREA=leetcode TESTSUIT=romantransfer .PHONY: tests tests: LDLIBS += $(TARGET) tests: $(TESTS) - sh ./tests/runtests.sh + sh ./tests/runtests.sh $(TESTAREA) $(TESTSUIT) valgrind: VALGRIND="valgrind --log-file=/tmp/valgrind-%p.log" $(MAKE) diff --git a/README.md b/README.md index 6289044..1d62f91 100644 --- a/README.md +++ b/README.md @@ -1,9 +1,14 @@ -LibLCTHW +LibLCTHW-With-Mutest-Leetcode ======== +1) This is the library that you finally create in my book Learn C The Hard Way found at: http://c.learncodethehardway.org/ This code is usually in sync with the book, but sometimes it gets out of sync during editing sessions. If you find a difference or a bug, just submit your pull request and I'll take a look. +2) +learn c the hard way with mini unit test your leetcode + +https://github.com/hamwastp/liblcthw-with-mutest-leetcode/blob/master/tests/leetcode/README.md diff --git a/src/lcthw/bstrlib.h b/src/lcthw/bstrlib.h index 4c43cad..cc18e69 100644 --- a/src/lcthw/bstrlib.h +++ b/src/lcthw/bstrlib.h @@ -19,282 +19,305 @@ extern "C" { #endif +#include +#include #include #include -#include -#include -#if !defined (BSTRLIB_VSNP_OK) && !defined (BSTRLIB_NOVSNP) -# if defined (__TURBOC__) && !defined (__BORLANDC__) -# define BSTRLIB_NOVSNP -# endif +#if !defined(BSTRLIB_VSNP_OK) && !defined(BSTRLIB_NOVSNP) +#if defined(__TURBOC__) && !defined(__BORLANDC__) +#define BSTRLIB_NOVSNP +#endif #endif #define BSTR_ERR (-1) #define BSTR_OK (0) #define BSTR_BS_BUFF_LENGTH_GET (0) -typedef struct tagbstring * bstring; -typedef const struct tagbstring * const_bstring; +typedef struct tagbstring* bstring; +typedef const struct tagbstring* const_bstring; /* Copy functions */ #define cstr2bstr bfromcstr -extern bstring bfromcstr (const char * str); -extern bstring bfromcstralloc (int mlen, const char * str); -extern bstring blk2bstr (const void * blk, int len); -extern char * bstr2cstr (const_bstring s, char z); -extern int bcstrfree (char * s); -extern bstring bstrcpy (const_bstring b1); -extern int bassign (bstring a, const_bstring b); -extern int bassignmidstr (bstring a, const_bstring b, int left, int len); -extern int bassigncstr (bstring a, const char * str); -extern int bassignblk (bstring a, const void * s, int len); +extern bstring bfromcstr(const char* str); +extern bstring bfromcstralloc(int mlen, const char* str); +extern bstring blk2bstr(const void* blk, int len); +extern char* bstr2cstr(const_bstring s, char z); +extern int bcstrfree(char* s); +extern bstring bstrcpy(const_bstring b1); +extern int bassign(bstring a, const_bstring b); +extern int bassignmidstr(bstring a, const_bstring b, int left, int len); +extern int bassigncstr(bstring a, const char* str); +extern int bassignblk(bstring a, const void* s, int len); /* Destroy function */ -extern int bdestroy (bstring b); +extern int bdestroy(bstring b); /* Space allocation hinting functions */ -extern int balloc (bstring s, int len); -extern int ballocmin (bstring b, int len); +extern int balloc(bstring s, int len); +extern int ballocmin(bstring b, int len); /* Substring extraction */ -extern bstring bmidstr (const_bstring b, int left, int len); +extern bstring bmidstr(const_bstring b, int left, int len); /* Various standard manipulations */ -extern int bconcat (bstring b0, const_bstring b1); -extern int bconchar (bstring b0, char c); -extern int bcatcstr (bstring b, const char * s); -extern int bcatblk (bstring b, const void * s, int len); -extern int binsert (bstring s1, int pos, const_bstring s2, unsigned char fill); -extern int binsertch (bstring s1, int pos, int len, unsigned char fill); -extern int breplace (bstring b1, int pos, int len, const_bstring b2, unsigned char fill); -extern int bdelete (bstring s1, int pos, int len); -extern int bsetstr (bstring b0, int pos, const_bstring b1, unsigned char fill); -extern int btrunc (bstring b, int n); +extern int bconcat(bstring b0, const_bstring b1); +extern int bconchar(bstring b0, char c); +extern int bcatcstr(bstring b, const char* s); +extern int bcatblk(bstring b, const void* s, int len); +extern int binsert(bstring s1, int pos, const_bstring s2, unsigned char fill); +extern int binsertch(bstring s1, int pos, int len, unsigned char fill); +extern int breplace(bstring b1, int pos, int len, const_bstring b2, unsigned char fill); +extern int bdelete(bstring s1, int pos, int len); +extern int bsetstr(bstring b0, int pos, const_bstring b1, unsigned char fill); +extern int btrunc(bstring b, int n); /* Scan/search functions */ -extern int bstricmp (const_bstring b0, const_bstring b1); -extern int bstrnicmp (const_bstring b0, const_bstring b1, int n); -extern int biseqcaseless (const_bstring b0, const_bstring b1); -extern int bisstemeqcaselessblk (const_bstring b0, const void * blk, int len); -extern int biseq (const_bstring b0, const_bstring b1); -extern int bisstemeqblk (const_bstring b0, const void * blk, int len); -extern int biseqcstr (const_bstring b, const char * s); -extern int biseqcstrcaseless (const_bstring b, const char * s); -extern int bstrcmp (const_bstring b0, const_bstring b1); -extern int bstrncmp (const_bstring b0, const_bstring b1, int n); -extern int binstr (const_bstring s1, int pos, const_bstring s2); -extern int binstrr (const_bstring s1, int pos, const_bstring s2); -extern int binstrcaseless (const_bstring s1, int pos, const_bstring s2); -extern int binstrrcaseless (const_bstring s1, int pos, const_bstring s2); -extern int bstrchrp (const_bstring b, int c, int pos); -extern int bstrrchrp (const_bstring b, int c, int pos); -#define bstrchr(b,c) bstrchrp ((b), (c), 0) -#define bstrrchr(b,c) bstrrchrp ((b), (c), blength(b)-1) -extern int binchr (const_bstring b0, int pos, const_bstring b1); -extern int binchrr (const_bstring b0, int pos, const_bstring b1); -extern int bninchr (const_bstring b0, int pos, const_bstring b1); -extern int bninchrr (const_bstring b0, int pos, const_bstring b1); -extern int bfindreplace (bstring b, const_bstring find, const_bstring repl, int pos); -extern int bfindreplacecaseless (bstring b, const_bstring find, const_bstring repl, int pos); +extern int bstricmp(const_bstring b0, const_bstring b1); +extern int bstrnicmp(const_bstring b0, const_bstring b1, int n); +extern int biseqcaseless(const_bstring b0, const_bstring b1); +extern int bisstemeqcaselessblk(const_bstring b0, const void* blk, int len); +extern int biseq(const_bstring b0, const_bstring b1); +extern int bisstemeqblk(const_bstring b0, const void* blk, int len); +extern int biseqcstr(const_bstring b, const char* s); +extern int biseqcstrcaseless(const_bstring b, const char* s); +extern int bstrcmp(const_bstring b0, const_bstring b1); +extern int bstrncmp(const_bstring b0, const_bstring b1, int n); +extern int binstr(const_bstring s1, int pos, const_bstring s2); +extern int binstrr(const_bstring s1, int pos, const_bstring s2); +extern int binstrcaseless(const_bstring s1, int pos, const_bstring s2); +extern int binstrrcaseless(const_bstring s1, int pos, const_bstring s2); +extern int bstrchrp(const_bstring b, int c, int pos); +extern int bstrrchrp(const_bstring b, int c, int pos); +#define bstrchr(b, c) bstrchrp((b), (c), 0) +#define bstrrchr(b, c) bstrrchrp((b), (c), blength(b) - 1) +extern int binchr(const_bstring b0, int pos, const_bstring b1); +extern int binchrr(const_bstring b0, int pos, const_bstring b1); +extern int bninchr(const_bstring b0, int pos, const_bstring b1); +extern int bninchrr(const_bstring b0, int pos, const_bstring b1); +extern int bfindreplace(bstring b, const_bstring find, const_bstring repl, int pos); +extern int bfindreplacecaseless(bstring b, const_bstring find, const_bstring repl, int pos); /* List of string container functions */ struct bstrList { int qty, mlen; - bstring * entry; + bstring* entry; }; -extern struct bstrList * bstrListCreate (void); -extern int bstrListDestroy (struct bstrList * sl); -extern int bstrListAlloc (struct bstrList * sl, int msz); -extern int bstrListAllocMin (struct bstrList * sl, int msz); +extern struct bstrList* bstrListCreate(void); +extern int bstrListDestroy(struct bstrList* sl); +extern int bstrListAlloc(struct bstrList* sl, int msz); +extern int bstrListAllocMin(struct bstrList* sl, int msz); /* String split and join functions */ -extern struct bstrList * bsplit (const_bstring str, unsigned char splitChar); -extern struct bstrList * bsplits (const_bstring str, const_bstring splitStr); -extern struct bstrList * bsplitstr (const_bstring str, const_bstring splitStr); -extern bstring bjoin (const struct bstrList * bl, const_bstring sep); -extern int bsplitcb (const_bstring str, unsigned char splitChar, int pos, - int (* cb) (void * parm, int ofs, int len), void * parm); -extern int bsplitscb (const_bstring str, const_bstring splitStr, int pos, - int (* cb) (void * parm, int ofs, int len), void * parm); -extern int bsplitstrcb (const_bstring str, const_bstring splitStr, int pos, - int (* cb) (void * parm, int ofs, int len), void * parm); +extern struct bstrList* bsplit(const_bstring str, unsigned char splitChar); +extern struct bstrList* bsplits(const_bstring str, const_bstring splitStr); +extern struct bstrList* bsplitstr(const_bstring str, const_bstring splitStr); +extern bstring bjoin(const struct bstrList* bl, const_bstring sep); +extern int bsplitcb(const_bstring str, unsigned char splitChar, int pos, + int (*cb)(void* parm, int ofs, int len), void* parm); +extern int bsplitscb(const_bstring str, const_bstring splitStr, int pos, + int (*cb)(void* parm, int ofs, int len), void* parm); +extern int bsplitstrcb(const_bstring str, const_bstring splitStr, int pos, + int (*cb)(void* parm, int ofs, int len), void* parm); /* Miscellaneous functions */ -extern int bpattern (bstring b, int len); -extern int btoupper (bstring b); -extern int btolower (bstring b); -extern int bltrimws (bstring b); -extern int brtrimws (bstring b); -extern int btrimws (bstring b); +extern int bpattern(bstring b, int len); +extern int btoupper(bstring b); +extern int btolower(bstring b); +extern int bltrimws(bstring b); +extern int brtrimws(bstring b); +extern int btrimws(bstring b); /* <*>printf format functions */ -#if !defined (BSTRLIB_NOVSNP) -extern bstring bformat (const char * fmt, ...); -extern int bformata (bstring b, const char * fmt, ...); -extern int bassignformat (bstring b, const char * fmt, ...); -extern int bvcformata (bstring b, int count, const char * fmt, va_list arglist); +#if !defined(BSTRLIB_NOVSNP) +extern bstring bformat(const char* fmt, ...); +extern int bformata(bstring b, const char* fmt, ...); +extern int bassignformat(bstring b, const char* fmt, ...); +extern int bvcformata(bstring b, int count, const char* fmt, va_list arglist); -#define bvformata(ret, b, fmt, lastarg) { \ -bstring bstrtmp_b = (b); \ -const char * bstrtmp_fmt = (fmt); \ -int bstrtmp_r = BSTR_ERR, bstrtmp_sz = 16; \ - for (;;) { \ - va_list bstrtmp_arglist; \ - va_start (bstrtmp_arglist, lastarg); \ - bstrtmp_r = bvcformata (bstrtmp_b, bstrtmp_sz, bstrtmp_fmt, bstrtmp_arglist); \ - va_end (bstrtmp_arglist); \ - if (bstrtmp_r >= 0) { /* Everything went ok */ \ - bstrtmp_r = BSTR_OK; \ - break; \ - } else if (-bstrtmp_r <= bstrtmp_sz) { /* A real error? */ \ - bstrtmp_r = BSTR_ERR; \ - break; \ - } \ - bstrtmp_sz = -bstrtmp_r; /* Doubled or target size */ \ - } \ - ret = bstrtmp_r; \ -} +#define bvformata(ret, b, fmt, lastarg) \ + { \ + bstring bstrtmp_b = (b); \ + const char* bstrtmp_fmt = (fmt); \ + int bstrtmp_r = BSTR_ERR, bstrtmp_sz = 16; \ + for (;;) { \ + va_list bstrtmp_arglist; \ + va_start(bstrtmp_arglist, lastarg); \ + bstrtmp_r = bvcformata(bstrtmp_b, bstrtmp_sz, bstrtmp_fmt, bstrtmp_arglist); \ + va_end(bstrtmp_arglist); \ + if (bstrtmp_r >= 0) { /* Everything went ok */ \ + bstrtmp_r = BSTR_OK; \ + break; \ + } else if (-bstrtmp_r <= bstrtmp_sz) { /* A real error? */ \ + bstrtmp_r = BSTR_ERR; \ + break; \ + } \ + bstrtmp_sz = -bstrtmp_r; /* Doubled or target size */ \ + } \ + ret = bstrtmp_r; \ + } #endif -typedef int (*bNgetc) (void *parm); -typedef size_t (* bNread) (void *buff, size_t elsize, size_t nelem, void *parm); +typedef int (*bNgetc)(void* parm); +typedef size_t (*bNread)(void* buff, size_t elsize, size_t nelem, void* parm); /* Input functions */ -extern bstring bgets (bNgetc getcPtr, void * parm, char terminator); -extern bstring bread (bNread readPtr, void * parm); -extern int bgetsa (bstring b, bNgetc getcPtr, void * parm, char terminator); -extern int bassigngets (bstring b, bNgetc getcPtr, void * parm, char terminator); -extern int breada (bstring b, bNread readPtr, void * parm); +extern bstring bgets(bNgetc getcPtr, void* parm, char terminator); +extern bstring bread(bNread readPtr, void* parm); +extern int bgetsa(bstring b, bNgetc getcPtr, void* parm, char terminator); +extern int bassigngets(bstring b, bNgetc getcPtr, void* parm, char terminator); +extern int breada(bstring b, bNread readPtr, void* parm); /* Stream functions */ -extern struct bStream * bsopen (bNread readPtr, void * parm); -extern void * bsclose (struct bStream * s); -extern int bsbufflength (struct bStream * s, int sz); -extern int bsreadln (bstring b, struct bStream * s, char terminator); -extern int bsreadlns (bstring r, struct bStream * s, const_bstring term); -extern int bsread (bstring b, struct bStream * s, int n); -extern int bsreadlna (bstring b, struct bStream * s, char terminator); -extern int bsreadlnsa (bstring r, struct bStream * s, const_bstring term); -extern int bsreada (bstring b, struct bStream * s, int n); -extern int bsunread (struct bStream * s, const_bstring b); -extern int bspeek (bstring r, const struct bStream * s); -extern int bssplitscb (struct bStream * s, const_bstring splitStr, - int (* cb) (void * parm, int ofs, const_bstring entry), void * parm); -extern int bssplitstrcb (struct bStream * s, const_bstring splitStr, - int (* cb) (void * parm, int ofs, const_bstring entry), void * parm); -extern int bseof (const struct bStream * s); +extern struct bStream* bsopen(bNread readPtr, void* parm); +extern void* bsclose(struct bStream* s); +extern int bsbufflength(struct bStream* s, int sz); +extern int bsreadln(bstring b, struct bStream* s, char terminator); +extern int bsreadlns(bstring r, struct bStream* s, const_bstring term); +extern int bsread(bstring b, struct bStream* s, int n); +extern int bsreadlna(bstring b, struct bStream* s, char terminator); +extern int bsreadlnsa(bstring r, struct bStream* s, const_bstring term); +extern int bsreada(bstring b, struct bStream* s, int n); +extern int bsunread(struct bStream* s, const_bstring b); +extern int bspeek(bstring r, const struct bStream* s); +extern int bssplitscb(struct bStream* s, const_bstring splitStr, + int (*cb)(void* parm, int ofs, const_bstring entry), void* parm); +extern int bssplitstrcb(struct bStream* s, const_bstring splitStr, + int (*cb)(void* parm, int ofs, const_bstring entry), void* parm); +extern int bseof(const struct bStream* s); struct tagbstring { int mlen; int slen; - unsigned char * data; + unsigned char* data; }; /* Accessor macros */ -#define blengthe(b, e) (((b) == (void *)0 || (b)->slen < 0) ? (int)(e) : ((b)->slen)) -#define blength(b) (blengthe ((b), 0)) -#define bdataofse(b, o, e) (((b) == (void *)0 || (b)->data == (void*)0) ? (char *)(e) : ((char *)(b)->data) + (o)) -#define bdataofs(b, o) (bdataofse ((b), (o), (void *)0)) -#define bdatae(b, e) (bdataofse (b, 0, e)) -#define bdata(b) (bdataofs (b, 0)) -#define bchare(b, p, e) ((((unsigned)(p)) < (unsigned)blength(b)) ? ((b)->data[(p)]) : (e)) -#define bchar(b, p) bchare ((b), (p), '\0') +#pragma GCC diagnostic ignored "-Waddress" +#define blengthe(b, e) (((b) == (void*)0 || (b)->slen < 0) ? (int)(e) : ((b)->slen)) +#define blength(b) (blengthe((b), 0)) +#define bdataofse(b, o, e) (((b) == (void*)0 || (b)->data == (void*)0) ? (char*)(e) : ((char*)(b)->data) + (o)) +#define bdataofs(b, o) (bdataofse((b), (o), (void*)0)) +#define bdatae(b, e) (bdataofse(b, 0, e)) +#define bdata(b) (bdataofs(b, 0)) +#define bchare(b, p, e) ((((unsigned)(p)) < (unsigned)blength(b)) ? ((b)->data[(p)]) : (e)) +#define bchar(b, p) bchare((b), (p), '\0') /* Static constant string initialization macro */ -#define bsStaticMlen(q,m) {(m), (int) sizeof(q)-1, (unsigned char *) ("" q "")} +#define bsStaticMlen(q, m) \ + { \ + (m), (int)sizeof(q) - 1, (unsigned char*)("" q "") \ + } #if defined(_MSC_VER) /* There are many versions of MSVC which emit __LINE__ as a non-constant. */ -# define bsStatic(q) bsStaticMlen(q,-32) +#define bsStatic(q) bsStaticMlen(q, -32) #endif #ifndef bsStatic -# define bsStatic(q) bsStaticMlen(q,-__LINE__) +#define bsStatic(q) bsStaticMlen(q, -__LINE__) #endif /* Static constant block parameter pair */ -#define bsStaticBlkParms(q) ((void *)("" q "")), ((int) sizeof(q)-1) +#define bsStaticBlkParms(q) ((void*)("" q "")), ((int)sizeof(q) - 1) /* Reference building macros */ #define cstr2tbstr btfromcstr -#define btfromcstr(t,s) { \ - (t).data = (unsigned char *) (s); \ - (t).slen = ((t).data) ? ((int) (strlen) ((char *)(t).data)) : 0; \ - (t).mlen = -1; \ -} -#define blk2tbstr(t,s,l) { \ - (t).data = (unsigned char *) (s); \ - (t).slen = l; \ - (t).mlen = -1; \ -} -#define btfromblk(t,s,l) blk2tbstr(t,s,l) -#define bmid2tbstr(t,b,p,l) { \ - const_bstring bstrtmp_s = (b); \ - if (bstrtmp_s && bstrtmp_s->data && bstrtmp_s->slen >= 0) { \ - int bstrtmp_left = (p); \ - int bstrtmp_len = (l); \ - if (bstrtmp_left < 0) { \ - bstrtmp_len += bstrtmp_left; \ - bstrtmp_left = 0; \ - } \ - if (bstrtmp_len > bstrtmp_s->slen - bstrtmp_left) \ - bstrtmp_len = bstrtmp_s->slen - bstrtmp_left; \ - if (bstrtmp_len <= 0) { \ - (t).data = (unsigned char *)""; \ - (t).slen = 0; \ - } else { \ - (t).data = bstrtmp_s->data + bstrtmp_left; \ - (t).slen = bstrtmp_len; \ - } \ - } else { \ - (t).data = (unsigned char *)""; \ - (t).slen = 0; \ - } \ - (t).mlen = -__LINE__; \ -} -#define btfromblkltrimws(t,s,l) { \ - int bstrtmp_idx = 0, bstrtmp_len = (l); \ - unsigned char * bstrtmp_s = (s); \ - if (bstrtmp_s && bstrtmp_len >= 0) { \ - for (; bstrtmp_idx < bstrtmp_len; bstrtmp_idx++) { \ - if (!isspace (bstrtmp_s[bstrtmp_idx])) break; \ - } \ - } \ - (t).data = bstrtmp_s + bstrtmp_idx; \ - (t).slen = bstrtmp_len - bstrtmp_idx; \ - (t).mlen = -__LINE__; \ -} -#define btfromblkrtrimws(t,s,l) { \ - int bstrtmp_len = (l) - 1; \ - unsigned char * bstrtmp_s = (s); \ - if (bstrtmp_s && bstrtmp_len >= 0) { \ - for (; bstrtmp_len >= 0; bstrtmp_len--) { \ - if (!isspace (bstrtmp_s[bstrtmp_len])) break; \ - } \ - } \ - (t).data = bstrtmp_s; \ - (t).slen = bstrtmp_len + 1; \ - (t).mlen = -__LINE__; \ -} -#define btfromblktrimws(t,s,l) { \ - int bstrtmp_idx = 0, bstrtmp_len = (l) - 1; \ - unsigned char * bstrtmp_s = (s); \ - if (bstrtmp_s && bstrtmp_len >= 0) { \ - for (; bstrtmp_idx <= bstrtmp_len; bstrtmp_idx++) { \ - if (!isspace (bstrtmp_s[bstrtmp_idx])) break; \ - } \ - for (; bstrtmp_len >= bstrtmp_idx; bstrtmp_len--) { \ - if (!isspace (bstrtmp_s[bstrtmp_len])) break; \ - } \ - } \ - (t).data = bstrtmp_s + bstrtmp_idx; \ - (t).slen = bstrtmp_len + 1 - bstrtmp_idx; \ - (t).mlen = -__LINE__; \ -} +#define btfromcstr(t, s) \ + { \ + (t).data = (unsigned char*)(s); \ + (t).slen = ((t).data) ? ((int)(strlen)((char*)(t).data)) : 0; \ + (t).mlen = -1; \ + } +#define blk2tbstr(t, s, l) \ + { \ + (t).data = (unsigned char*)(s); \ + (t).slen = l; \ + (t).mlen = -1; \ + } +#define btfromblk(t, s, l) blk2tbstr(t, s, l) +#define bmid2tbstr(t, b, p, l) \ + { \ + const_bstring bstrtmp_s = (b); \ + if (bstrtmp_s && bstrtmp_s->data && bstrtmp_s->slen >= 0) { \ + int bstrtmp_left = (p); \ + int bstrtmp_len = (l); \ + if (bstrtmp_left < 0) { \ + bstrtmp_len += bstrtmp_left; \ + bstrtmp_left = 0; \ + } \ + if (bstrtmp_len > bstrtmp_s->slen - bstrtmp_left) \ + bstrtmp_len = bstrtmp_s->slen - bstrtmp_left; \ + if (bstrtmp_len <= 0) { \ + (t).data = (unsigned char*)""; \ + (t).slen = 0; \ + } else { \ + (t).data = bstrtmp_s->data + bstrtmp_left; \ + (t).slen = bstrtmp_len; \ + } \ + } else { \ + (t).data = (unsigned char*)""; \ + (t).slen = 0; \ + } \ + (t).mlen = -__LINE__; \ + } +#define btfromblkltrimws(t, s, l) \ + { \ + int bstrtmp_idx = 0, bstrtmp_len = (l); \ + unsigned char* bstrtmp_s = (s); \ + if (bstrtmp_s && bstrtmp_len >= 0) { \ + for (; bstrtmp_idx < bstrtmp_len; bstrtmp_idx++) { \ + if (!isspace(bstrtmp_s[bstrtmp_idx])) \ + break; \ + } \ + } \ + (t).data = bstrtmp_s + bstrtmp_idx; \ + (t).slen = bstrtmp_len - bstrtmp_idx; \ + (t).mlen = -__LINE__; \ + } +#define btfromblkrtrimws(t, s, l) \ + { \ + int bstrtmp_len = (l)-1; \ + unsigned char* bstrtmp_s = (s); \ + if (bstrtmp_s && bstrtmp_len >= 0) { \ + for (; bstrtmp_len >= 0; bstrtmp_len--) { \ + if (!isspace(bstrtmp_s[bstrtmp_len])) \ + break; \ + } \ + } \ + (t).data = bstrtmp_s; \ + (t).slen = bstrtmp_len + 1; \ + (t).mlen = -__LINE__; \ + } +#define btfromblktrimws(t, s, l) \ + { \ + int bstrtmp_idx = 0, bstrtmp_len = (l)-1; \ + unsigned char* bstrtmp_s = (s); \ + if (bstrtmp_s && bstrtmp_len >= 0) { \ + for (; bstrtmp_idx <= bstrtmp_len; bstrtmp_idx++) { \ + if (!isspace(bstrtmp_s[bstrtmp_idx])) \ + break; \ + } \ + for (; bstrtmp_len >= bstrtmp_idx; bstrtmp_len--) { \ + if (!isspace(bstrtmp_s[bstrtmp_len])) \ + break; \ + } \ + } \ + (t).data = bstrtmp_s + bstrtmp_idx; \ + (t).slen = bstrtmp_len + 1 - bstrtmp_idx; \ + (t).mlen = -__LINE__; \ + } /* Write protection macros */ -#define bwriteprotect(t) { if ((t).mlen >= 0) (t).mlen = -1; } -#define bwriteallow(t) { if ((t).mlen == -1) (t).mlen = (t).slen + ((t).slen == 0); } +#define bwriteprotect(t) \ + { \ + if ((t).mlen >= 0) \ + (t).mlen = -1; \ + } +#define bwriteallow(t) \ + { \ + if ((t).mlen == -1) \ + (t).mlen = (t).slen + ((t).slen == 0); \ + } #define biswriteprotected(t) ((t).mlen <= 0) #ifdef __cplusplus diff --git a/src/lcthw/darray_algos.c b/src/lcthw/darray_algos.c index a045a71..e075737 100644 --- a/src/lcthw/darray_algos.c +++ b/src/lcthw/darray_algos.c @@ -1,20 +1,23 @@ #include #include -int DArray_qsort(DArray * array, DArray_compare cmp) +int DArray_qsort(DArray* array, DArray_compare cmp) { - qsort(array->contents, DArray_count(array), sizeof(void *), cmp); + qsort(array->contents, DArray_count(array), sizeof(void*), cmp); return 0; } -int DArray_heapsort(DArray * array, DArray_compare cmp) +#pragma GCC diagnostic ignored "-Wunused-parameter" +int DArray_heapsort(DArray* array, DArray_compare cmp) { - return heapsort(array->contents, DArray_count(array), - sizeof(void *), cmp); + //return heapsort(array->contents, DArray_count(array), + // sizeof(void *), cmp); + return 0; } -int DArray_mergesort(DArray * array, DArray_compare cmp) +int DArray_mergesort(DArray* array, DArray_compare cmp) { - return mergesort(array->contents, DArray_count(array), - sizeof(void *), cmp); + //return mergesort(array->contents, DArray_count(array), + // sizeof(void *), cmp); + return 0; } diff --git a/src/lcthw/list_algos.c b/src/lcthw/list_algos.c index 045b94c..b393294 100644 --- a/src/lcthw/list_algos.c +++ b/src/lcthw/list_algos.c @@ -1,26 +1,31 @@ #include #include -inline void ListNode_swap(ListNode * a, ListNode * b) +/* inline */ void ListNode_swap(ListNode *a, ListNode *b) { void *temp = a->value; a->value = b->value; b->value = temp; } -int List_bubble_sort(List * list, List_compare cmp) +int List_bubble_sort(List *list, List_compare cmp) { int sorted = 1; - if (List_count(list) <= 1) { - return 0; // already sorted + if (List_count(list) <= 1) + { + return 0; // already sorted } - do { + do + { sorted = 1; - LIST_FOREACH(list, first, next, cur) { - if (cur->next) { - if (cmp(cur->value, cur->next->value) > 0) { + LIST_FOREACH(list, first, next, cur) + { + if (cur->next) + { + if (cmp(cur->value, cur->next->value) > 0) + { ListNode_swap(cur, cur->next); sorted = 0; } @@ -31,24 +36,33 @@ int List_bubble_sort(List * list, List_compare cmp) return 0; } -inline List *List_merge(List * left, List * right, List_compare cmp) +/* inline */ List *List_merge(List *left, List *right, List_compare cmp) { List *result = List_create(); void *val = NULL; - while (List_count(left) > 0 || List_count(right) > 0) { - if (List_count(left) > 0 && List_count(right) > 0) { - if (cmp(List_first(left), List_first(right)) <= 0) { + while (List_count(left) > 0 || List_count(right) > 0) + { + if (List_count(left) > 0 && List_count(right) > 0) + { + if (cmp(List_first(left), List_first(right)) <= 0) + { val = List_shift(left); - } else { + } + else + { val = List_shift(right); } List_push(result, val); - } else if (List_count(left) > 0) { + } + else if (List_count(left) > 0) + { val = List_shift(left); List_push(result, val); - } else if (List_count(right) > 0) { + } + else if (List_count(right) > 0) + { val = List_shift(right); List_push(result, val); } @@ -57,11 +71,12 @@ inline List *List_merge(List * left, List * right, List_compare cmp) return result; } -List *List_merge_sort(List * list, List_compare cmp) +List *List_merge_sort(List *list, List_compare cmp) { List *result = NULL; - if (List_count(list) <= 1) { + if (List_count(list) <= 1) + { return list; } @@ -69,10 +84,14 @@ List *List_merge_sort(List * list, List_compare cmp) List *right = List_create(); int middle = List_count(list) / 2; - LIST_FOREACH(list, first, next, cur) { - if (middle > 0) { + LIST_FOREACH(list, first, next, cur) + { + if (middle > 0) + { List_push(left, cur->value); - } else { + } + else + { List_push(right, cur->value); } diff --git a/src/lcthw/list_algos.h b/src/lcthw/list_algos.h index 09800eb..0784336 100644 --- a/src/lcthw/list_algos.h +++ b/src/lcthw/list_algos.h @@ -3,10 +3,10 @@ #include -typedef int (*List_compare) (const void *a, const void *b); +typedef int (*List_compare)(const void *a, const void *b); -int List_bubble_sort(List * list, List_compare cmp); +int List_bubble_sort(List *list, List_compare cmp); -List *List_merge_sort(List * list, List_compare cmp); +List *List_merge_sort(List *list, List_compare cmp); #endif diff --git a/src/lcthw/sarray.c b/src/lcthw/sarray.c index 2ed74fa..72d21fb 100644 --- a/src/lcthw/sarray.c +++ b/src/lcthw/sarray.c @@ -1,16 +1,15 @@ #undef NDEBUG -#include #include +#include #include - -int SuffixArray_compare(void *thunk, const void *a, const void *b) +int SuffixArray_compare(void* thunk, const void* a, const void* b) { - SuffixArray *sarry = thunk; - int a_at = *(int *)a; - int b_at = *(int *)b; - char *a_str = sarry->source + a_at; - char *b_str = sarry->source + b_at; + SuffixArray* sarry = thunk; + int a_at = *(int*)a; + int b_at = *(int*)b; + char* a_str = sarry->source + a_at; + char* b_str = sarry->source + b_at; int a_len = sarry->length - a_at; int b_len = sarry->length - b_at; @@ -21,7 +20,7 @@ int SuffixArray_compare(void *thunk, const void *a, const void *b) return cmp; } -int SuffixArray_find_suffix(SuffixArray *sarry, char *data, int length) +int SuffixArray_find_suffix(SuffixArray* sarry, char* data, int length) { int min = 0; int max = sarry->length; @@ -33,24 +32,23 @@ int SuffixArray_find_suffix(SuffixArray *sarry, char *data, int length) // BUG: wrong, need to use the minimum length cmp = strncmp(SuffixArray_substr(sarry, mid), data, length); - if(cmp < 0) { + if (cmp < 0) { min = mid + 1; } else { max = mid - 1; } - } while(cmp != 0 && min < max); + } while (cmp != 0 && min < max); - if(cmp == 0) { + if (cmp == 0) { return mid; } else { return -1; } } - -SuffixArray *SuffixArray_create(char *data, int length) +SuffixArray* SuffixArray_create(char* data, int length) { - SuffixArray *sarry = calloc(1, sizeof(SuffixArray)); + SuffixArray* sarry = calloc(1, sizeof(SuffixArray)); check_mem(sarry); sarry->source = malloc(length + 1); @@ -64,29 +62,28 @@ SuffixArray *SuffixArray_create(char *data, int length) check_mem(sarry->indices); int i = 0; - for(i = 0; i < length; i++) { + for (i = 0; i < length; i++) { sarry->indices[i] = i; } +#pragma GCC diagnostic ignored "-Wimplicit-function-declaration" qsort_r(sarry->indices, length, sizeof(int), sarry, SuffixArray_compare); return sarry; error: - if(sarry) { + if (sarry) { SuffixArray_destroy(sarry); } return NULL; } - -void SuffixArray_destroy(SuffixArray *sarry) +void SuffixArray_destroy(SuffixArray* sarry) { - if(sarry) { + if (sarry) { free(sarry->source); free(sarry->indices); free(sarry); } } - diff --git a/src/lcthw/string_algos.c b/src/lcthw/string_algos.c index afd0581..9e4c65c 100644 --- a/src/lcthw/string_algos.c +++ b/src/lcthw/string_algos.c @@ -1,9 +1,10 @@ #include #include -static inline void String_setup_skip_chars(size_t * skip_chars, - const unsigned char *needle, - ssize_t nlen) +static inline void +String_setup_skip_chars(size_t* skip_chars, + const unsigned char* needle, + ssize_t nlen) { size_t i = 0; size_t last = nlen - 1; @@ -17,13 +18,12 @@ static inline void String_setup_skip_chars(size_t * skip_chars, } } -static inline const unsigned char *String_base_search(const unsigned - char *haystack, - ssize_t hlen, - const unsigned - char *needle, - ssize_t nlen, - size_t * +static inline const unsigned char* +String_base_search(const unsigned char* haystack, + ssize_t hlen, + const unsigned char* needle, + ssize_t nlen, + size_t* skip_chars) { size_t i = 0; @@ -46,35 +46,35 @@ static inline const unsigned char *String_base_search(const unsigned haystack += skip_chars[haystack[last]]; } -error: // fallthrough +error: // fallthrough return NULL; } int String_find(bstring in, bstring what) { - const unsigned char *found = NULL; + const unsigned char* found = NULL; - const unsigned char *haystack = (const unsigned char *)bdata(in); + const unsigned char* haystack = (const unsigned char*)bdata(in); ssize_t hlen = blength(in); - const unsigned char *needle = (const unsigned char *)bdata(what); + const unsigned char* needle = (const unsigned char*)bdata(what); ssize_t nlen = blength(what); size_t skip_chars[UCHAR_MAX + 1] = { 0 }; String_setup_skip_chars(skip_chars, needle, nlen); - found = String_base_search(haystack, hlen, - needle, nlen, skip_chars); + found = String_base_search(haystack, hlen, needle, nlen, skip_chars); return found != NULL ? found - haystack : -1; } -StringScanner *StringScanner_create(bstring in) +StringScanner* +StringScanner_create(bstring in) { - StringScanner *scan = calloc(1, sizeof(StringScanner)); + StringScanner* scan = calloc(1, sizeof(StringScanner)); check_mem(scan); scan->in = in; - scan->haystack = (const unsigned char *)bdata(in); + scan->haystack = (const unsigned char*)bdata(in); scan->hlen = blength(in); assert(scan != NULL && "fuck"); @@ -85,24 +85,26 @@ StringScanner *StringScanner_create(bstring in) return NULL; } -static inline void StringScanner_set_needle(StringScanner * scan, - bstring tofind) +static inline void +StringScanner_set_needle(StringScanner* scan, + bstring tofind) { - scan->needle = (const unsigned char *)bdata(tofind); + scan->needle = (const unsigned char*)bdata(tofind); scan->nlen = blength(tofind); String_setup_skip_chars(scan->skip_chars, scan->needle, scan->nlen); } -static inline void StringScanner_reset(StringScanner * scan) +static inline void +StringScanner_reset(StringScanner* scan) { - scan->haystack = (const unsigned char *)bdata(scan->in); + scan->haystack = (const unsigned char*)bdata(scan->in); scan->hlen = blength(scan->in); } -int StringScanner_scan(StringScanner * scan, bstring tofind) +int StringScanner_scan(StringScanner* scan, bstring tofind) { - const unsigned char *found = NULL; + const unsigned char* found = NULL; ssize_t found_at = 0; if (scan->hlen <= 0) { @@ -110,16 +112,14 @@ int StringScanner_scan(StringScanner * scan, bstring tofind) return -1; } - if ((const unsigned char *)bdata(tofind) != scan->needle) { + if ((const unsigned char*)bdata(tofind) != scan->needle) { StringScanner_set_needle(scan, tofind); } - found = String_base_search(scan->haystack, scan->hlen, - scan->needle, scan->nlen, - scan->skip_chars); + found = String_base_search(scan->haystack, scan->hlen, scan->needle, scan->nlen, scan->skip_chars); if (found) { - found_at = found - (const unsigned char *)bdata(scan->in); + found_at = found - (const unsigned char*)bdata(scan->in); scan->haystack = found + scan->nlen; scan->hlen -= found_at - scan->nlen; } else { @@ -131,7 +131,7 @@ int StringScanner_scan(StringScanner * scan, bstring tofind) return found_at; } -void StringScanner_destroy(StringScanner * scan) +void StringScanner_destroy(StringScanner* scan) { if (scan) { free(scan); diff --git a/src/lcthw/string_algos.h b/src/lcthw/string_algos.h index e43a841..c642b6e 100644 --- a/src/lcthw/string_algos.h +++ b/src/lcthw/string_algos.h @@ -3,22 +3,23 @@ #include #include +#include typedef struct StringScanner { bstring in; - const unsigned char *haystack; + const unsigned char* haystack; ssize_t hlen; - const unsigned char *needle; + const unsigned char* needle; ssize_t nlen; size_t skip_chars[UCHAR_MAX + 1]; } StringScanner; int String_find(bstring in, bstring what); -StringScanner *StringScanner_create(bstring in); +StringScanner* StringScanner_create(bstring in); -int StringScanner_scan(StringScanner * scan, bstring tofind); +int StringScanner_scan(StringScanner* scan, bstring tofind); -void StringScanner_destroy(StringScanner * scan); +void StringScanner_destroy(StringScanner* scan); #endif diff --git a/src/leetcode/romantransfer.c b/src/leetcode/romantransfer.c new file mode 100644 index 0000000..3d748eb --- /dev/null +++ b/src/leetcode/romantransfer.c @@ -0,0 +1,71 @@ +#include + +typedef struct +{ + const char ch; + int num; +} roman_map; + +roman_map roman_mapping[] = { + { 'I', 1 }, + { 'V', 5 }, + { 'X', 10 }, + { 'L', 50 }, + { 'C', 100 }, + { 'D', 500 }, + { 'M', 1000 }, +}; + +/* + https://leetcode-cn.com/problems/roman-to-integer/ + 输入: s = "MCMXCIV" + 输出: 1994 + 解释: M = 1000, CM = 900, XC = 90, IV = 4. +*/ + +int romanToInt(char* s) +{ + char* p; + int result = 0; + int type_num = sizeof(roman_mapping) / sizeof(roman_map); + for (p = s; *p != '\0'; p++) { + if (*p == 'I' && *(p + 1) != '\0') { + if (*(p + 1) == 'V') { + result += 4; + p++; + continue; + } else if (*(p + 1) == 'X') { + result += 9; + p++; + continue; + } + } else if (*p == 'X' && *(p + 1) != '\0') { + if (*(p + 1) == 'L') { + result += 40; + p++; + continue; + } else if (*(p + 1) == 'C') { + result += 90; + p++; + continue; + } + } else if (*p == 'C' && *(p + 1) != '\0') { + if (*(p + 1) == 'D') { + result += 400; + p++; + continue; + } else if (*(p + 1) == 'M') { + result += 900; + p++; + continue; + } + } + for (int i = 0; i < type_num; i++) { + if (*p == roman_mapping[i].ch) { + result += roman_mapping[i].num; + } + } + } + + return result; +} diff --git a/src/leetcode/zigzagconversion.c b/src/leetcode/zigzagconversion.c new file mode 100644 index 0000000..607f8d6 --- /dev/null +++ b/src/leetcode/zigzagconversion.c @@ -0,0 +1,158 @@ +/* +6. Z 字形变换(https://leetcode-cn.com/problems/zigzag-conversion/) +将一个给定字符串 s 根据给定的行数 numRows ,以从上往下、从左到右进行 Z 字形排列。 + +比如输入字符串为 "PAYPALISHIRING" 行数为 3 时,排列如下: nLines = 7 +P A H N +A P L S I I G +Y I R +之后,你的输出需要从左往右逐行读取,产生出一个新的字符串,比如:"PAHNAPLSIIGYIR"。 // (14/3 - 1)(3-1) + 1 = 3 * 2 + 1 + +请你实现这个将字符串进行指定行数变换的函数: + +string convert(string s, int numRows); + + +示例 1: + +输入:s = "PAYPALISHIRING", numRows = 3 +输出:"PAHNAPLSIIGYIR" +示例 2: +输入:s = "PAYPALISHIRING", numRows = 4 // nLines = 6 // (14/4 - 1)(4-1) = 3 * 2 +输出:"PINALSIGYAHRPI" +解释: +P I N +A L S I G +Y A H R +P I +示例 3: + +输入:s = "A", numRows = 1 +输出:"A" + + +提示: + +1 <= s.length <= 1000 +s 由英文字母(小写和大写)、',' 和 '.' 组成 +1 <= numRows <= 1000 +*/ +#include +#include +#include +#include +#include + +char* convert(char* s, int numRows) +{ + DArray* temp; + int size; + List* res_list; + char* res; + + if (s == NULL) { + return NULL; + } + + size = strlen(s); + + if (size == 0 || numRows < 1) { + return NULL; + } + + if (numRows == 1) { + return s; + } + + temp = DArray_create(sizeof(List*), numRows); + if (temp == NULL) { + return NULL; + } + + for (int i = 0; i < size; i++) { + int ans = i / (numRows - 1); + int remain = i % (numRows - 1); + if (ans % 2 == 0) { //结果为偶数或0 + List* temp_list = (List*)DArray_get(temp, remain); + if (temp_list == NULL) { + temp_list = List_create(); + if (temp_list == NULL) { + return NULL; + } + DArray_push(temp, temp_list); + } + List_push(temp_list, &s[i]); //按余数正序保存 + } + if (ans % 2 != 0) { //结果为奇数 + List* temp_list = (List*)DArray_get(temp, numRows - remain - 1); + if (temp_list == NULL) { + temp_list = List_create(); + if (temp_list == NULL) { + return NULL; + } + DArray_push(temp, temp_list); + } + List_push(temp_list, &s[i]); //按余数倒序保存 + } + } + + res_list = List_create(); + if (res_list == NULL) { + return NULL; + } + for (int i = 0; i < numRows; i++) { + List* temp_list = (List*)DArray_get(temp, i); + ListNode* node = temp_list->first; + while (node != NULL) { + List_push(res_list, node->value); + node = node->next; + } + } + + res = (char*)malloc(sizeof(char) * List_count(res_list)); + if (res == NULL) { + return NULL; + } + + ListNode* node = res_list->first; + int m = 0; + while (node != NULL) { + res[m] = *(char*)node->value; + node = node->next; + m++; + } + + List_destroy(res_list); + DArray_destroy(temp); + + //#undef NDEBUG + debug("=============debug test (%s) =============", "Hello World1"); + log_info("=============log_info test (%s) =============", "Hello World2"); + log_info("=============log_info test (%s) =============", "Hello World3"); + log_info("=============log_info test (%s) =============", "Hello World4"); + + return res; +} + +// refer: +// https://blog.csdn.net/qq_38537503/article/details/95031638 +// vector temp(numRows); +// string res; +// if (s.empty() || numRows < 1) +// return res; +// if (numRows == 1) +// return s; +// for (int i = 0; i < s.size(); i++) { +// int ans = i / (numRows - 1); +// int remain = i % (numRows - 1); +// if (ans % 2 == 0) { //结果为偶数或0 +// temp[remain].push_back(s[i]); //按余数正序保存 +// } +// if (ans % 2 != 0) { //结果为奇数 +// temp[numRows - remain - 1].push_back(s[i]); //按余数倒序保存 +// } +// } +// for (int i = 0; i < temp.size(); i++) { +// res += temp[i]; +// } +// return res; diff --git a/tests/leetcode/README.md b/tests/leetcode/README.md new file mode 100644 index 0000000..e294e4f --- /dev/null +++ b/tests/leetcode/README.md @@ -0,0 +1,9 @@ +LibLCTHW with mini unit your leetcode fore practice + +https://github.com/hamwastp/liblcthw-with-mutest-leetcode + + +## run all leetcode test +- eg:make clean;make TESTAREA=leetcode TESTSUIT="\*" +## run one leetcode test +- eg:make clean;make TESTAREA=leetcode TESTSUIT=romantransfer diff --git a/tests/leetcode/mutest_tests.c b/tests/leetcode/mutest_tests.c new file mode 100644 index 0000000..d3e480f --- /dev/null +++ b/tests/leetcode/mutest_tests.c @@ -0,0 +1,20 @@ +#include "../minunit.h" +#include + +// Just Do It for new suit +// the testcase corresponding C algo file + +MU_TEST(example_test) +{ + //char* actual = convert((char*)"PAYPALISHIRING", 3); + mu_assert_eq(111, 111); + mu_assert_not_eq(111, 110); + mu_assert_str_eq("PAYPALISHIRING", "PAYPALISHIRING"); + mu_assert_str_not_eq("PAYPALISHIRING", "PAHNAPLSIIGYIR"); + return NULL; +} + +// Just Do It for new suit +//# make clean;make TESTAREA=leetcode TESTSUIT=mutest +//# make clean;make TESTAREA=leetcode TESTSUIT="\*" +RUN_TESTS_EX() \ No newline at end of file diff --git a/tests/leetcode/romantransfer_tests.c b/tests/leetcode/romantransfer_tests.c new file mode 100644 index 0000000..c6af1b6 --- /dev/null +++ b/tests/leetcode/romantransfer_tests.c @@ -0,0 +1,42 @@ +#include "../minunit.h" +#include + +// Just Do It for new suit +// the testcase corresponding C algo file +#include + +MU_TEST(III) +{ + int ret = romanToInt((char *)"III"); + mu_assert(ret == 3, "Failed to test romanToInt."); + return NULL; +} + +MU_TEST(MCMXCIV_FAIL) +{ + int ret = romanToInt((char *)"MCMXCIV"); + mu_assert(ret != 1994, "Failed Test"); + + return NULL; +} + +MU_TEST(MCMXCIV_NULLMSG) +{ + int ret = romanToInt((char *)"MCMXCIV"); + mu_assert(ret != 1994, ""); + + return NULL; +} + +MU_TEST(MCMXCIV) +{ + int ret = romanToInt((char *)"MCMXCIV"); + mu_assert(ret == 1994, "Failed to test MCMXCIV."); + + return NULL; +} + +// Just Do It for new suit +//# make clean;make TESTAREA=leetcode TESTSUIT=romantransfer +//# make clean;make TESTAREA=leetcode TESTSUIT="\*" +RUN_TESTS_EX() \ No newline at end of file diff --git a/tests/leetcode/zigzagconversion_tests.c b/tests/leetcode/zigzagconversion_tests.c new file mode 100644 index 0000000..3e93ff4 --- /dev/null +++ b/tests/leetcode/zigzagconversion_tests.c @@ -0,0 +1,23 @@ +#include "../minunit.h" +#include + +// Just Do It for new suit +// the testcase corresponding C algo file +#include + +MU_TEST(convert_PAYPALISHIRING) +{ + char* actual = convert((char*)"PAYPALISHIRING", 3); + mu_assert_str_eq(actual, "PAHNAPLSIIGYIR"); + + actual = convert((char*)"PAYPALISHIRING", 4); + mu_assert_str_eq(actual, "PINALSIGYAHRPI"); + + return NULL; +} + +// Just Do It for new suit +//# make clean;make TESTAREA=leetcode TESTSUIT=zigzagconversion +//# make clean;make TESTAREA=leetcode TESTSUIT="\*" +// gdb tests/leetcode/zigzagconversion_tests +RUN_TESTS_EX() \ No newline at end of file diff --git a/tests/minunit.h b/tests/minunit.h index ff0704f..53c44b6 100644 --- a/tests/minunit.h +++ b/tests/minunit.h @@ -1,32 +1,189 @@ #undef NDEBUG #ifndef _minunit_h #define _minunit_h - -#include #include +#include + #include -#define mu_suite_start() char *message = NULL - -#define mu_assert(test, message) if (!(test)) { log_err(message); return message; } -#define mu_run_test(test) debug("\n-----%s", " " #test); \ - message = test(); tests_run++; if (message) return message; - -#define RUN_TESTS(name) int main(int argc, char *argv[]) {\ - argc = 1; \ - debug("----- RUNNING: %s", argv[0]);\ - printf("----\nRUNNING: %s\n", argv[0]);\ - char *result = name();\ - if (result != 0) {\ - printf("FAILED: %s\n", result);\ - }\ - else {\ - printf("ALL TESTS PASSED\n");\ - }\ - printf("Tests run: %d\n", tests_run);\ - exit(result != 0);\ -} +#pragma GCC diagnostic ignored "-Wunused-variable" +#pragma GCC diagnostic ignored "-Wformat-extra-args" +#define mu_suite_start() char* message = NULL + +#define mu_assert(test, message) \ + if (!(test)) { \ + /* __ADD__ */ \ + fprintf(stderr, \ + "\033[41;1m[FAIL]\033[0m"); \ + /* __END__ */ \ + log_err(message); \ + } /* __ADD__ */ \ + else { \ + fprintf(stderr, \ + "\033[32;1m[PASS]\n\033[0m"); \ + } +/* __END__ */ + +/* __ADD__ */ +#define _mu_assert_fail_msg(actual, expected) \ + fprintf(stderr, \ + "\033[41;1m[FAIL]\033[0m"); \ + log_err("actual:" #actual, \ + "expected:" #expected); + +#define _mu_assert_pass_msg() \ + fprintf(stderr, \ + "\033[32;1m[PASS]\n\033[0m"); + +#define mu_assert_eq(actual, expected) \ + if (!(actual == expected)) { \ + _mu_assert_fail_msg(actual, expected) \ + } else { \ + _mu_assert_pass_msg() \ + } + +#define mu_assert_not_eq(actual, expected) \ + if (actual == expected) { \ + _mu_assert_fail_msg(actual, expected) \ + } else { \ + _mu_assert_pass_msg() \ + } + +#define mu_assert_str_eq(actual, expected) \ + if (strcmp((const char*)(actual), \ + (const char*)(expected))) { \ + _mu_assert_fail_msg(actual, expected) \ + } else { \ + _mu_assert_pass_msg() \ + } + +#define mu_assert_str_not_eq(actual, expected) \ + if (!strcmp((const char*)(actual), \ + (const char*)(expected))) { \ + \ + _mu_assert_fail_msg(actual, expected) \ + } else { \ + _mu_assert_pass_msg() \ + } +/* __END__ */ + +#define mu_run_test(test) \ + debug("\n-----%s", " " #test); \ + message = test(); \ + tests_run++; \ + if (message) \ + return message; + +// __ADD__ +#define mu_run_test_ex(test, casename) \ + debug("\n-----testcase:%s", casename); \ + test(); \ + tests_run++; +// __END__ + +#define RUN_TESTS(name) \ + int main(int argc, char* argv[]) \ + { \ + if (argc < 1) { \ + return -1; \ + } \ + debug("----- RUNNING: %s", argv[0]); \ + printf("----\nRUNNING: %s\n", argv[0]); \ + char* result = name(); \ + if (result != 0) { \ + printf("FAILED: %s\n", result); \ + } else { \ + printf("ALL TESTS PASSED\n"); \ + } \ + printf("Tests run: %d\n", tests_run); \ + exit(result != 0); \ + } int tests_run; +// __ADD__ +#define mu_run_all_test() \ + MU_TestInfo* p_mu_alltest = mu_alltest_list; \ + while (p_mu_alltest != NULL) { \ + mu_run_test_ex(p_mu_alltest->testcase, p_mu_alltest->name); \ + p_mu_alltest = p_mu_alltest->next; \ + } + +#define RUN_TESTS_EX() \ + char* all_tests() \ + { \ + mu_suite_start(); \ + mu_run_all_test(); \ + return NULL; \ + } \ + \ + RUN_TESTS(all_tests); +// __END__ + +// __ADD__ +typedef char* (*testcase_func)(void); + +typedef struct _MU_TestInfo { + testcase_func testcase; + const char* name; + struct _MU_TestInfo* next; +} MU_TestInfo; + +MU_TestInfo* mu_alltest_list = NULL; +MU_TestInfo* mu_alltest = NULL; + +void register_testcase(testcase_func f, const char* name); + +#define MU_TEST(name) \ + char* mutest_##name(); \ + __attribute((constructor)) void register_testcase##name() \ + { \ + register_testcase(mutest_##name, "mutest_" #name ""); \ + return; \ + }; \ + char* mutest_##name() + +void register_testcase(testcase_func f, const char* name) +{ + if (mu_alltest == NULL) { + mu_alltest = (MU_TestInfo*)malloc(sizeof(MU_TestInfo)); + if (mu_alltest == NULL) { + return; + } + + mu_alltest_list = mu_alltest; + } else { + mu_alltest->next = (MU_TestInfo*)malloc(sizeof(MU_TestInfo)); + if (mu_alltest->next == NULL) { + return; + } + + mu_alltest = mu_alltest->next; + } + + printf("register_testcase success:%s\n", name); + + mu_alltest->testcase = f; + mu_alltest->name = name; + mu_alltest->next = NULL; + + return; +} +// __END__ + +// __ADD__ +__attribute((destructor)) void mutestcases_destroy() +{ + MU_TestInfo* p_mu_alltest = mu_alltest_list; + while (p_mu_alltest != NULL) { + MU_TestInfo* prev = p_mu_alltest; + p_mu_alltest = p_mu_alltest->next; + free(prev); + } + return; +}; + +// __END__ + +// ... #endif diff --git a/tests/runtests.sh b/tests/runtests.sh index 2224b07..b6108be 100644 --- a/tests/runtests.sh +++ b/tests/runtests.sh @@ -1,6 +1,22 @@ echo "Running unit tests:" -for i in tests/*_tests + +#eg: sh ./tests/runtests.sh leetcode romantransfer +testsuit="*" +testpath=tests/${testsuit}_tests + + +if [[ $# == 2 && "$1" == "lcthw" && "$2" != "all" ]];then + #eg: make TESTAREA=lcthw TESTSUIT=darray + testsuit=$2 + testpath=tests/${testsuit}_tests +elif [[ $# == 2 && "$1" == "leetcode" && "$2" != "all" ]];then + #eg: make TESTAREA=lcthw TESTSUIT=darray + testsuit=$2 + testpath=tests/leetcode/${testsuit}_tests +fi + +for i in ${testpath} do $i 2>&1 >> tests/tests.log if [ ! $? ] diff --git a/tests/string_algos_tests.c b/tests/string_algos_tests.c index a361985..489a687 100644 --- a/tests/string_algos_tests.c +++ b/tests/string_algos_tests.c @@ -1,16 +1,16 @@ #include "minunit.h" -#include #include +#include #include struct tagbstring IN_STR = bsStatic( - "I have ALPHA beta ALPHA and oranges ALPHA"); + "I have ALPHA beta ALPHA and oranges ALPHA"); struct tagbstring ALPHA = bsStatic("ALPHA"); const int TEST_TIME = 1; -char *test_find_and_scan() +char* test_find_and_scan() { - StringScanner *scan = StringScanner_create(&IN_STR); + StringScanner* scan = StringScanner_create(&IN_STR); mu_assert(scan != NULL, "Failed to make the scanner."); int find_i = String_find(&IN_STR, &ALPHA); @@ -22,21 +22,21 @@ char *test_find_and_scan() scan_i = StringScanner_scan(scan, &ALPHA); mu_assert(scan_i > find_i, - "should find another ALPHA after the first"); + "should find another ALPHA after the first"); scan_i = StringScanner_scan(scan, &ALPHA); mu_assert(scan_i > find_i, - "should find another ALPHA after the first"); + "should find another ALPHA after the first"); mu_assert(StringScanner_scan(scan, &ALPHA) == -1, - "shouldn't find it"); + "shouldn't find it"); StringScanner_destroy(scan); return NULL; } -char *test_binstr_performance() +char* test_binstr_performance() { int i = 0; int found_at = 0; @@ -55,21 +55,20 @@ char *test_binstr_performance() } while (elapsed <= TEST_TIME); debug("BINSTR COUNT: %lu, END TIME: %d, OPS: %f", - find_count, (int)elapsed, (double)find_count / elapsed); + find_count, (int)elapsed, (double)find_count / elapsed); return NULL; } -char *test_find_performance() +char* test_find_performance() { int i = 0; - int found_at = 0; unsigned long find_count = 0; time_t elapsed = 0; time_t start = time(NULL); do { for (i = 0; i < 1000; i++) { - found_at = String_find(&IN_STR, &ALPHA); + String_find(&IN_STR, &ALPHA); find_count++; } @@ -77,18 +76,18 @@ char *test_find_performance() } while (elapsed <= TEST_TIME); debug("FIND COUNT: %lu, END TIME: %d, OPS: %f", - find_count, (int)elapsed, (double)find_count / elapsed); + find_count, (int)elapsed, (double)find_count / elapsed); return NULL; } -char *test_scan_performance() +char* test_scan_performance() { int i = 0; int found_at = 0; unsigned long find_count = 0; time_t elapsed = 0; - StringScanner *scan = StringScanner_create(&IN_STR); + StringScanner* scan = StringScanner_create(&IN_STR); time_t start = time(NULL); @@ -106,14 +105,14 @@ char *test_scan_performance() } while (elapsed <= TEST_TIME); debug("SCAN COUNT: %lu, END TIME: %d, OPS: %f", - find_count, (int)elapsed, (double)find_count / elapsed); + find_count, (int)elapsed, (double)find_count / elapsed); StringScanner_destroy(scan); return NULL; } -char *all_tests() +char* all_tests() { mu_suite_start();