done sortstrings

This commit is contained in:
Claudio Maggioni 2019-10-09 10:18:40 +02:00
parent 93c8c5f0d8
commit 7fb7197e75
6 changed files with 258 additions and 0 deletions

144
sortstrings/Makefile Normal file
View file

@ -0,0 +1,144 @@
OBJECTS = sortstrings.o
CFLAGS=-Wall -g
CXXFLAGS=-Wall -g
SHELL=/bin/bash
TIMEOUT=8
TESTS_DIR=tests
TESTS_SH:=$(wildcard $(TESTS_DIR)/*.sh)
TESTS_SH_NAMES:=$(patsubst $(TESTS_DIR)/%.sh, %, $(TESTS_SH))
TESTS_IO:=$(wildcard $(TESTS_DIR)/*.in)
TESTS_IO_NAMES:=$(patsubst $(TESTS_DIR)/%.in, %, $(TESTS_IO))
TESTS_C:=$(wildcard $(TESTS_DIR)/*.c)
TESTS_CXX:=$(wildcard $(TESTS_DIR)/*.cc)
TESTS_BIN:=$(patsubst $(TESTS_DIR)/%.c, $(TESTS_DIR)/%, $(TESTS_C)) \
$(patsubst $(TESTS_DIR)/%.cc, $(TESTS_DIR)/%, $(TESTS_CXX))
TESTS_BIN_NAMES:=$(patsubst $(TESTS_DIR)/%.c, %, $(TESTS_C)) $(patsubst $(TESTS_DIR)/%.cc, %, $(TESTS_CXX))
.PHONY: all
all: compile check
.PHONY: compile-program
compile: $(PROGRAMS) $(OBJECTS)
.PHONY: check
check: check-bin check-io-sh
.PHONY: check-io-sh
check-io-sh: compile $(TESTS_IO) $(TESTS_SH)
@exec 2> /dev/null; \
for p in $(foreach prog,$(PROGRAMS),$(dir $(prog))$(prog)); do \
echo "Testing $${p}:" ; \
for t in $(TESTS_IO_NAMES); do \
echo -n "Running test $$t..." ; \
"$$p" < "$(TESTS_DIR)/$$t.in" > "$$t.out" 2>&1 & \
prog_pid=$$!; \
( sleep $(TIMEOUT); kill $$prog_pid > /dev/null 2>&1 ) & \
killer_pid=$$!; \
wait $$prog_pid; \
res=$$?; \
if test $$res -gt 128; \
then \
case `kill -l $$(($$res - 128))` in \
ABRT ) echo "FAIL"; ;; \
TERM ) echo "TIME OUT"; ;; \
* ) echo "UNKNOWN ERROR"; ;; \
esac ; \
echo "see $(TESTS_DIR)/$$t.in" ;\
echo "you may run $$p < $(TESTS_DIR)/$$t.in" ;\
echo "to see what went wrong";\
rm -f "$$t.out" ;\
else \
kill $$killer_pid > /dev/null 2>&1 ;\
wait $$killer_pid; \
if cmp -s "$$t.out" "$(TESTS_DIR)/$$t.expected"; \
then \
echo "PASS" ;\
rm -f "$$t.out" ;\
else \
echo "FAIL" ;\
echo "see $(TESTS_DIR)/$$t.sh" ;\
echo "run diff $$t.out $(TESTS_DIR)/$$t.expected";\
echo "to see the difference between the actual and expected output";\
fi; \
fi; \
done; \
for t in $(TESTS_SH_NAMES); do \
echo -n "Running test $$t..." ; \
$(SHELL) "$(TESTS_DIR)/$$t.sh" "$$p" > "$$t.out" 2>&1 & \
prog_pid=$$!; \
( sleep $(TIMEOUT); kill $$prog_pid > /dev/null 2>&1 ) & \
killer_pid=$$!; \
wait $$prog_pid; \
res=$$?; \
if test $$res -gt 128; \
then \
case `kill -l $$(($$res - 128))` in \
ABRT ) echo "FAIL"; ;; \
TERM ) echo "TIME OUT"; ;; \
* ) echo "UNKNOWN ERROR"; ;; \
esac ; \
echo "see $(TESTS_DIR)/$$t.sh" ;\
echo "you may run $(TESTS_DIR)/$$t.sh $$p" ;\
echo "to see what went wrong";\
rm -f "$$t.out" ;\
else \
kill $$killer_pid > /dev/null 2>&1 ;\
wait $$killer_pid; \
if cmp -s "$$t.out" "$(TESTS_DIR)/$$t.expected"; \
then \
echo "PASS" ;\
rm -f "$$t.out" ;\
else \
echo "FAIL" ;\
echo "see $(TESTS_DIR)/$$t.sh" ;\
echo "run diff $$t.out $(TESTS_DIR)/$$t.expected";\
echo "to see the difference between the actual and expected output";\
fi; \
fi; \
done; \
done
$(TESTS_DIR)/%: $(TESTS_DIR)/%.c $(OBJECTS)
$(CC) $(CFLAGS) $(LDFLAGS) $(TESTS_DIR)/$*.c $(OBJECTS) -o $@
$(TESTS_DIR)/%: $(TESTS_DIR)/%.cc $(OBJECTS)
$(CXX) $(CXXFLAGS) $(LDFLAGS) $(TESTS_DIR)/$*.cc $(OBJECTS) -o $@
.PHONY: check-bin
check-bin: $(TESTS_BIN)
@exec 2> /dev/null; \
for t in $(TESTS_BIN_NAMES); do \
echo -n "Running test $$t..." ; \
"$(TESTS_DIR)/$$t" &\
prog_pid=$$!; \
( sleep $(TIMEOUT); kill $$prog_pid > /dev/null 2>&1 ) & \
killer_pid=$$!; \
wait $$prog_pid; \
res=$$?; \
if test $$res -gt 128; \
then \
case `kill -l $$(($$res - 128))` in \
ABRT ) echo "FAIL"; ;; \
TERM ) echo "TIME OUT"; ;; \
* ) echo "UNKNOWN ERROR"; ;; \
esac ; \
echo "you may run $(TESTS_DIR)/$$t to see what went wrong" ;\
else \
kill $$killer_pid > /dev/null 2>&1 ;\
wait $$killer_pid; \
echo "PASS" ;\
fi; \
done
.PHONY: clean
clean:
rm -f $(PROGRAMS) $(OBJECTS) tests/*.o $(TESTS_BIN)

30
sortstrings/sortstrings.c Normal file
View file

@ -0,0 +1,30 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MAX_N 1000
int compar(const void* string1, const void* string2) {
const char** s1 = (const char**) string1;
const char** s2 = (const char**) string2;
return strcmp(*s1, *s2);
}
void sort_strings(const char* input, const char* output, unsigned int n) {
const char* strings[MAX_N];
size_t i = 0;
size_t offset = 0;
for (i = 0; i < n; i++) {
strings[i] = input + offset;
offset += strlen(input + offset) + 1; // + 1 for NUL
}
qsort(strings, n, sizeof(const char*), &compar);
offset = 0;
for (i = 0; i < n; i++) {
const size_t len = strlen(strings[i]);
strncpy((char*) output + offset, (char*) strings[i], len + 1);
offset += len + 1;
}
}

11
sortstrings/tests/test0.c Normal file
View file

@ -0,0 +1,11 @@
#include <assert.h>
#include <string.h>
extern void sort_strings(const char * input, char * output, unsigned int n);
int main() {
char buf[100];
sort_strings("", buf, 1);
assert(memcmp(buf, "", 1) == 0);
return 0;
}

15
sortstrings/tests/test1.c Normal file
View file

@ -0,0 +1,15 @@
#include <assert.h>
#include <string.h>
extern void sort_strings(const char * input, char * output, unsigned int n);
int main() {
char buf[100];
sort_strings("ciao", buf, 1);
assert(memcmp(buf, "ciao", 5) == 0);
sort_strings("ciao\0blah", buf, 2);
assert(memcmp(buf, "blah\0ciao", 10) == 0);
return 0;
}

37
sortstrings/tests/test2.c Normal file
View file

@ -0,0 +1,37 @@
#include <assert.h>
#include <string.h>
extern void sort_strings(const char * input, char * output, unsigned int n);
int main() {
char buf[1000];
sort_strings("ciao\0ciao", buf, 2);
assert(memcmp(buf, "ciao\0ciao", 10) == 0);
sort_strings("a\0b", buf, 2);
assert(memcmp(buf, "a\0b", 4) == 0);
sort_strings("a\0b\0c", buf, 3);
assert(memcmp(buf, "a\0b\0c", 6) == 0);
sort_strings("b\0c\0a", buf, 3);
assert(memcmp(buf, "a\0b\0c", 6) == 0);
sort_strings("c\0a\0b", buf, 3);
assert(memcmp(buf, "a\0b\0c", 6) == 0);
sort_strings("c\0a\0b", buf, 1);
assert(memcmp(buf, "c", 2) == 0);
sort_strings("c\0a\0b", buf, 2);
assert(memcmp(buf, "a\0c", 2) == 0);
sort_strings("a\0a", buf, 2);
assert(memcmp(buf, "a\0a", 4) == 0);
sort_strings("b\0a\0a\0a\0b", buf, 5);
assert(memcmp(buf, "a\0a\0a\0b\0b", 10) == 0);
return 0;
}

21
sortstrings/tests/test4.c Normal file
View file

@ -0,0 +1,21 @@
#include <assert.h>
#include <string.h>
extern void sort_strings(const char * input, char * output, unsigned int n);
const char * S_sorted = "cfreq\0concatenate\0concatenate/tests\0coursesdb\0deletedigits\0deletedigits/tests\0findstrings\0flipline\0flipline/tests\0flipstream\0linkedlist\0redactdigits\0redactdigits/tests\0topcolor\0topcolor/tests\0volumes\0volumes/tests\0wordcount\0wordcount/tests";
const char * S = "concatenate/tests\0concatenate\0linkedlist\0topcolor/tests\0topcolor\0flipstream\0deletedigits/tests\0deletedigits\0coursesdb\0volumes/tests\0volumes\0cfreq\0wordcount/tests\0wordcount\0flipline/tests\0flipline\0findstrings\0redactdigits/tests\0redactdigits";
int main() {
char buf[1000];
sort_strings("ciao\0cia", buf, 2);
assert(memcmp(buf, "cia\0ciao", 9) == 0);
sort_strings(S, buf, 19);
assert(memcmp(buf, S_sorted, 239) == 0);
return 0;
}