2020q1 Homework1 (lab0)

tags: Linux, system programming

contributed by < Randy870819 >

ไฝœๆฅญ่ฆๆฑ‚

Makefile ๅˆ†ๆž

ๅฟซ่ฆๅฎŒๆˆไฝœๆฅญๅฏฆไฝœ่ˆ‡ๅฏฆ้ฉ—ๅพŒๆ‰็™ผ็พๆœ‰ไบ† Makefile ๆ‰่ฎ“ๆ•ดๅ€‹ๅฐˆๆกˆ้–‹็™ผๅฆ‚ๆญค้ †ๆšข๏ผŒไธ”็‚บไบ†ๅšๅฐˆๆกˆ็š„ไฟฎๆ”นๅฏฆ้ฉ—ไนŸ้œ€่ฆไฟฎๆ”น Makefile ๏ผŒๅ› ๆญคๅฐ‡ Makefile ็š„ๅˆ†ๆžๆๅ‰ๆ”พๅˆฐๆญค่™•๏ผŒไนŸๆ„Ÿ่ฌๅŒๅญธ KYG-yaya573142 ็š„ๅ…ฑ็ญ†ใ€‚

Makefile ่ชžๆณ•ๅœจ่€ๅธซๆไพ›็š„ Makefile ่ชžๆณ•ๅ’Œ็คบ็ฏ„ ๅทฒๆœ‰่ฉณ็›ก็š„ไป‹็ดน๏ผŒ lab0/Makefile ใ€‚

  • ไธ€้–‹ๅง‹ๅ…ˆๅฐๅธธ็”จๆˆ–ๆ˜ฏๅ†—้•ท็š„ ่ฎŠๆ•ธ(ๅทจ้›†) ๅšๅฎš็พฉใ€‚

    โ€‹โ€‹โ€‹โ€‹CC = gcc
    โ€‹โ€‹โ€‹โ€‹CFLAGS = -O1 -g -Wall -Werror -Idudect -I.
    
    โ€‹โ€‹โ€‹โ€‹GIT_HOOKS := .git/hooks/applied
    โ€‹โ€‹โ€‹โ€‹DUT_DIR := dudect
    
  • ็ฌฌไธ€ๆฌกๅŸท่กŒ make ๆœƒๅ…ˆ่กŒๅฎ‰่ฃ Git Hooks:
    ๅŸท่กŒ make ๅพŒ๏ผŒmake ๆœƒๅœจ makefile ไธญๆ‰พๅฐ‹็ฌฌไธ€ๅ€‹็›ฎๆจ™ (target) ๏ผŒไบฆๅณๅฐ‡ all ้ ่จญ็‚บๆœ€็ต‚ๅปบๅˆถ็›ฎๆจ™๏ผŒๅ› ๆญค้™คไบ†็ทจ่ญฏ qtest ๅค–๏ผŒ้‚„ๆœƒๅฎ‰่ฃ Git Hooks ใ€‚

    โ€‹โ€‹โ€‹โ€‹all: $(GIT_HOOKS) qtest
    
    โ€‹โ€‹โ€‹โ€‹$(GIT_HOOKS):
    โ€‹โ€‹โ€‹โ€‹    @scripts/install-git-hooks
    โ€‹โ€‹โ€‹โ€‹    @echo
    
  • ๅƒๆ•ธ่จญๅฎš๏ผš VERBOSE and SANITIZER

    • ็•ถๅŸท่กŒ make ไธฆ้™„ๅŠ  VERBOSE=1 ๆœƒ่ฎ“้กฏ็คบ่ฉณ็ดฐ็ทจ่ญฏ็š„้Ž็จ‹:
      • Q: @ ๅŠ ๅœจๆŒ‡ไปคๅ‰๏ผŒๆœƒ่ฎ“ๆŒ‡ไปคไธ้กฏ็คบ๏ผŒๅ› ๆญคๅˆฉ็”จ Macro ้™„ๅŠ ๅœจไน‹ๅพŒๆœƒๅŸท่กŒ็š„ๆŒ‡ไปคๅ‰๏ผŒไพฟ่ƒฝ่ผ•ๆ˜“ๆŽงๅˆถๆ˜ฏๅฆ้กฏ็คบใ€‚
      • VECHO: @true ่ƒฝ่ฟฝๅŠ ่ฉฒ่กŒๆŒ‡ไปค็›ดๆŽฅ่ขซ่ฆ–็‚บๆˆๅŠŸ็š„ไฝœ็”จ๏ผŒ @printf ๅ‰‡ๅฏไปฅๅฐๅ‡บ็›ธๅฐๆ‡‰ๅญ—ไธฒใ€‚
    • ็•ถๅŸท่กŒ make ไธฆ้™„ๅŠ  SANITIZER=1 ๅ‰‡ๆœƒๅฐ็ทจ่ญฏๅƒๆ•ธๅšไฟฎๆ”นใ€‚
    โ€‹โ€‹โ€‹โ€‹# Control the build verbosity
    โ€‹โ€‹โ€‹โ€‹ifeq ("$(VERBOSE)","1")
    โ€‹โ€‹โ€‹โ€‹    Q :=
    โ€‹โ€‹โ€‹โ€‹    VECHO = @true
    โ€‹โ€‹โ€‹โ€‹else
    โ€‹โ€‹โ€‹โ€‹    Q := @
    โ€‹โ€‹โ€‹โ€‹    VECHO = @printf
    โ€‹โ€‹โ€‹โ€‹endif
    
    โ€‹โ€‹โ€‹โ€‹# Enable sanitizer(s) or not
    โ€‹โ€‹โ€‹โ€‹ifeq ("$(SANITIZER)","1")
    โ€‹โ€‹โ€‹โ€‹    # https://github.com/google/sanitizers/wiki/AddressSanitizerFlags
    โ€‹โ€‹โ€‹โ€‹    CFLAGS += -fsanitize=address -fno-omit-frame-pointer -fno-common
    โ€‹โ€‹โ€‹โ€‹    LDFLAGS += -fsanitize=address
    โ€‹โ€‹โ€‹โ€‹endif
    
  • Objects and Dependencies: ้€™้‚Šไฝฟ็”จไบ† Auto-Dependency Generation ไพ†่งฃๆฑบ dependency ็š„ๅ•้กŒใ€‚

    • Line 3: deps := $(OBJS:%.o=.%.o.d) ไฝฟ็”จ่ฌ็”จๅญ—ๅ…ƒ % ้…ไธŠไน‹ๅ‰ๅปบ็ซ‹็š„่ฎŠๆ•ธ๏ผŒ็‚บๆ‰€ๆœ‰ objective file ่จญ็ซ‹ๅฅฝๅฎƒ dependency file ็š„ๆช”ๅ๏ผŒไปฅๅ‚™ไน‹ๅพŒ include ใ€‚
    • Line 8: ๆŽฅไธ‹ไพ†ๅฐฑๆ˜ฏๅœจ็‚บๆฏๅ€‹ .c ๆช”็ทจ่ญฏๅปบ็ซ‹ object file ็š„ๅŒๆ™‚ไนŸๅปบ็ซ‹ dependency file ๏ผŒ็•ถ็„ถ้€™ไบ› dependency file ่ฆ่ˆ‡ๅ…ˆๅ‰่ฎŠๆ•ธ deps ่จญๅฎšไธ€ๆจฃ๏ผŒๆŽฅไธ‹ไพ†ๆ‰่ƒฝ้ †ๅˆฉไฝฟ็”จใ€‚ ( ่จป๏ผšๅปบ็ซ‹ dependency file ๆ˜ฏ็ทจ่ญฏๅ™จไธญ pre-processor ็š„ๅทฅไฝœ )
    • Line 10: ๆœ€ๅพŒไนŸๆœ€้‡่ฆ็š„ไธ€ๆญฅ๏ผŒๅฐฑๆ˜ฏ include ๆ‰€ๆœ‰ dependency file ใ€‚

    ็•ถไธ€ๅ€‹็›ฎๆจ™ (target) ๆฏ”ๅ…ถ่‡ชๅทฑ็š„็›ธไพ้ …็›ฎ (dependency) ๆ›ดๆ–ฐๆ™‚้–“้‚„่ฆๆ—ฉๆ™‚๏ผŒไปฃ่กจๅ…ถ็›ธไพ้ …็›ฎๅทฒ่ขซไฟฎๆ”น๏ผŒ่ฆ้‡ๆ–ฐๅปบ็ซ‹็›ฎๆจ™๏ผŒไฝ†ไธ€ๅ€‹ๅฐˆๆกˆๅพ€ๅพ€ๆœƒๆœ‰็œพๅคš dependency file ๏ผŒ่€ŒๅˆไปฅไธŠๆต็จ‹๏ผŒๅฐฑๆ˜ฏไปฃๆ›ฟๆˆ‘ๅ€‘ๅฎŒๆˆๅปบ็ซ‹็›ธไพๆ€ง็š„่ค‡้›œๅทฅไฝœ๏ผ

    โ€‹โ€‹โ€‹โ€‹OBJS := qtest.o report.o console.o harness.o queue.o \
    โ€‹โ€‹โ€‹โ€‹        random.o dudect/constant.o dudect/fixture.o dudect/ttest.o
    โ€‹โ€‹โ€‹โ€‹deps := $(OBJS:%.o=.%.o.d)
    
    โ€‹โ€‹โ€‹โ€‹%.o: %.c
    โ€‹โ€‹โ€‹โ€‹    @mkdir -p .$(DUT_DIR)
    โ€‹โ€‹โ€‹โ€‹    $(VECHO) "  CC\t$@\n"
    โ€‹โ€‹โ€‹โ€‹    $(Q)$(CC) -o $@ $(CFLAGS) -c -MMD -MF .$@.d $<
    
    โ€‹โ€‹โ€‹โ€‹-include $(deps)
    
  • Valgrind ๆ”ฏๆด

    • valgrind_existence: ๆชขๆŸฅไฝœๆฅญ็ณป็ตฑๆœ‰็„กๅฎ‰่ฃ Valgrind ใ€‚

      • ไธ€้–‹ๅง‹ไธๆ‡‚ which ๆ˜ฏไป€้บผๆฒ’้—œไฟ‚๏ผŒๆ‰“้–‹ Terminal ่ผธๅ…ฅ man which
        โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹$ man which
        โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹NAME: which - locate a command
        โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹DESCRIPTION: which returns the pathnames of the files (or links) which would be executed in the current environment
        
        which ๆŒ‡ไปค่ฎ“ไฝฟ็”จ่€…ๅพ—็ŸฅๆŸไธ€ command ๅŸท่กŒ็š„่ทฏๅพ‘ใ€‚
      • 2>&1 ๅ‰‡ๆ˜ฏไปฃ่กจๅฐ‡ stderr ๅฐŽๅ…ฅ stdout ใ€‚ (From: Stack Overflow)
      • /dev/null ๆ˜ฏ NULL Device ๏ผŒๆœƒๅ›žๅ ฑไธŸๅ…ฅ่ณ‡ๆ–™ๆ˜ฏๅฆๆˆๅŠŸ๏ผŒไฝฟ็”จไปฅไธ‹่ผธๅ…ฅๅฆ‚ๆžœ้›ป่…ฆไธญๅทฒๆœ‰ๅฎ‰่ฃ Valgrind ๅ‰‡ๆœƒๅพ—ๅˆฐ yes ่ผธๅ‡บๅ–”ใ€‚
        โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹$ if which valgrind 2>&1 > /dev/null 
        โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹> then echo yes
        โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹> else echo no
        โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹> fi
        โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹yes
        
      • || ไปฃ่กจ่‹ฅๅทฆ้‚ŠๅŸท่กŒๅ‡บ้Œฏ๏ผŒๅฐฑๅŸท่กŒๅณ้‚Š็š„ๅ…งๅฎนใ€‚
      • ๅ› ๆญคๆœ€ๅพŒๆ•ด่กŒ็š„ๆŒ‡ไปคไนŸ้กฏ่€Œๆ˜“่ฆ‹ไบ†ๅง๏ผ๏ผ
    • valgrind

      • $(MAKE) ็‚บ Recursive make commands ๏ผŒๆ‰€ไปฅ่ฆๅฐๅฟƒไธ่ฆๅ†ๆฌกๅŸท่กŒ make ๅปบ็ซ‹ๅŒๆจฃ็š„็›ฎๆจ™๏ผŒๆœƒ้€ ๆˆ็„ก้™่ฟดๅœˆใ€‚ Manual
      • $(eval expression) ๅ‰‡ๆ˜ฏๆœƒๅฐ‡ๅณ้‚Š expression ๅฑ•้–‹ไธฆ็•ถไฝœ Makefile ๆŒ‡ไปคๅŸท่กŒใ€‚ Manual
      • sed -i "s/alarm/isnan/g" $(patched_file): ๅ…ถไธญ "s/alarm/isnan/g" ไธฆ้ž่ทฏๅพ‘๏ผŒ่€Œๆ˜ฏ sed (stream editor) ๆ›ฟๆ›ๅญ—ไธฒ็š„่ชžๆณ•๏ผŒๅœจๆญคๆ˜ฏๅฐ‡ $(patched_file) ไธญ็š„ๆ‰€ๆœ‰็š„ "alarm" ๆ›ฟๆ›็‚บ "iasnan" ใ€‚

      ็™ผ็พๅŒๅญธ frankchang0125 ่งฃ้‡‹็š„ๆ›ด็‚บๆธ…ๆฅšใ€‚

    โ€‹โ€‹โ€‹โ€‹valgrind_existence:
    โ€‹โ€‹โ€‹โ€‹    @which valgrind 2>&1 > /dev/null || (echo "FATAL: valgrind not found"; exit 1)
    
    โ€‹โ€‹โ€‹โ€‹valgrind: valgrind_existence
    โ€‹โ€‹โ€‹โ€‹    # Explicitly disable sanitizer(s)
    โ€‹โ€‹โ€‹โ€‹    $(MAKE) clean SANITIZER=0 qtest
    โ€‹โ€‹โ€‹โ€‹    $(eval patched_file := $(shell mktemp /tmp/qtest.XXXXXX))
    โ€‹โ€‹โ€‹โ€‹    cp qtest $(patched_file)
    โ€‹โ€‹โ€‹โ€‹    chmod u+x $(patched_file)
    โ€‹โ€‹โ€‹โ€‹    sed -i "s/alarm/isnan/g" $(patched_file)
    โ€‹โ€‹โ€‹โ€‹    scripts/driver.py -p $(patched_file) --valgrind
    โ€‹โ€‹โ€‹โ€‹    @echo
    โ€‹โ€‹โ€‹โ€‹    @echo "Test with specific case by running command:" 
    โ€‹โ€‹โ€‹โ€‹    @echo "scripts/driver.py -p $(patched_file) --valgrind -t <tid>"
    

้–‹็™ผ็ด€้Œ„

queue.h๏ผšqueue structure

็‚บไบ†่ฎ“ q_insert_tail() ่ทŸ q_size() ๅŸท่กŒๆ™‚้”ๅˆฐ

O(1) ็š„ๆ™‚้–“่ค‡้›œๅบฆ๏ผŒๅขžๅŠ ไบ†่ฎŠๆ•ธ size ่ˆ‡ tail ๆŒ‡ๆจ™ไพฟๆ–ผๅญ˜ๅ–ใ€‚

/* Queue structure */
typedef struct {
    list_ele_t *head, *tail; /* Linked list of elements */
    int size;                /* Memorizing the size of queue */
} queue_t;

q_new

ๅปบ็ซ‹ไธ€ๅ€‹ๆ–ฐ็š„ queue_t ็ตๆง‹๏ผŒไธฆๅฐๅ…ถๅˆๅง‹ๅŒ–๏ผŒ่‹ฅ malloc() ๅ›žๅ‚ณ NULL ๏ผŒไปฃ่กจ้…็ฝฎ่จ˜ๆ†ถ้ซ”ๅคฑๆ•—๏ผŒๅ›žๅ‚ณ NULL ใ€‚

queue_t *q_new()
{
    queue_t *q = malloc(sizeof(queue_t));
    if (!q)
        return NULL;
    q->head = q->tail = NULL;
    q->size = 0;
    return q;
}

q_free

ไธ€้–‹ไฝฟๅ…ˆๅฐๆฒ’ๆœ‰ queue ็š„็‰นๅฎšๆƒ…ๆณๅš่™•็†๏ผ›ๅœจ queue ่ขซๅปบ็ซ‹็š„ๆƒ…ๆณไธ‹๏ผŒ่ตฐ่จชๆ•ดๅ€‹ linked list ๅˆฉ็”จ pre ๆŒ‡ๆจ™ๆŒ‡ๅ‘ๅ‰ไธ€ๅ€‹ list element ๅœจๅฐๅ…ถๆŒ‡ๅˆฐ็š„่จ˜ๆ†ถ้ซ”ๅš deallocation ๏ผŒๆœ€ๅพŒๅ†ๆธ…้™ค queue ็ตๆง‹ใ€‚

void q_free(queue_t *q)
{
    if (!q)
        return;
    list_ele_t *tmp = q->head, *pre = NULL;
    while (tmp) {
        pre = tmp;
        tmp = tmp->next;
        if (pre->value)
            free(pre->value);
        free(pre);
    }
    free(q);
}

่€ƒๆ…ฎไปฅไธ‹่ฎŠๆ›ด:

@@ -2,12 +2,11 @@
 {
     if (!q)
         return;
-    list_ele_t *tmp = q->head, *pre = NULL;
-    while (tmp) {
-        pre = tmp;
-        tmp = tmp->next;
-        if (pre->value)
-            free(pre->value);
+
+    list_ele_t *front = NULL;
+    for (list_ele_t *tmp = q->head; tmp; tmp = front) {
+        front = tmp->next;
+        free(pre->value);
         free(pre);
     }
     free(q);

่ฆ้ปž:

  1. ็ธฎๆธ› list_ele_t *pre ็š„ scope;
  2. ๅฐ‡ while ๆ”นๅฏซ็‚บ for ่ฟดๅœˆ๏ผŒๆ›ดๅฅฝ้–ฑ่ฎ€ไธ”็จ‹ๅผ็ขผ็ธฎๆธ›;
  3. ๆณจๆ„ free ็š„ไฝฟ็”จ๏ผŒ็•ถ่ผธๅ…ฅๅƒๆ•ธ็‚บ NULL ๆ™‚๏ผŒ่ฉฒๅ‡ฝๅผ็„กไฝœ็”จ๏ผŒๆ–ผๆ˜ฏๅฐฑๅฏๅˆฉ็”จๆญค็‰นๆ€งๆธ›ๅฐ‘ไธ€ๅ€‹ if ๆ•˜่ฟฐ;

Image Not Showing Possible Reasons
  • The image file may be corrupted
  • The server hosting the image is unavailable
  • The image path is incorrect
  • The image format is not supported
Learn More โ†’
jserv

q_insert_head

ไธ€้–‹ไฝฟๅ…ˆๅฐๆฒ’ๆœ‰ queue ็š„็‰นๅฎšๆƒ…ๆณๅš่™•็†๏ผŒๅ†ไพๅบๆ–ฐๅขž list_ele_t ่ˆ‡ๅญ—ไธฒ๏ผŒ่ฆๆณจๆ„็š„ๆ˜ฏๅฆ‚ๆžœๅ…ถไธญๆŸไธ€็’ฐ็ฏ€ๅ‡บ้Œฏ๏ผŒๅฟ…้ ˆๅฐ‡ๅœจ้€™ๅ‡ฝๅผไธญๆ–ฐๅขž็š„่จ˜ๆ†ถ้ซ”ไฝ็ฝฎ้ƒฝ้‡‹ๆ”พๆމใ€‚

ๆŽฅไธ‹ไพ†ไฝฟ็”จ strncpy() ๅฐ‡่ผธๅ…ฅๅญ—ไธฒ่ค‡่ฃฝๅˆฐๆ–ฐๅขž็š„ๅญ—ไธฒไธญ๏ผŒ่ฆๆณจๆ„็š„ๆ˜ฏ strncpy() ๅชๆœƒ่ค‡่ฃฝๆŒ‡ๅฎš้•ทๅบฆ

n ๅ€‹ๅญ—ๅ…ƒ๏ผŒๅฟ…้ ˆ่‡ช่กŒๆณจๆ„ๅญ—ไธฒ็ตๅฐพๆœ‰ๆฒ’ๆœ‰ null character ('\0') ๏ผš

The strncpy() function is similar, except that at most n bytes of src are copied. Warning: If there is no null byte among the first n bytes of src, the string placed in dest will not be null-terminated. Linux man page

ๆœ€ๅพŒๆ’ๅ…ฅๅˆฐ้ ญ็ซฏๅพŒ่ฆ็‰นๅˆฅๆณจๆ„ linked list ้•ทๅบฆ็”ฑ 0 ่ฎŠ 1 ็š„ๆƒ…ๆณ๏ผŒๆญคๆ™‚้ ญ่ˆ‡ๅฐพ็ซฏๆ˜ฏๆŒ‡ๅ‘ๅŒไธ€ๅ€‹ list node ใ€‚

bool q_insert_head(queue_t *q, char *s)
{
    if (!q)
        return false;
    list_ele_t *newh = malloc(sizeof(list_ele_t));
    /* Don't forget to allocate space for the string and copy it */
    /* What if either call to malloc returns NULL? */
    if (!newh)
        return false;
    newh->value = malloc(sizeof(char) * (strlen(s) + 1));
    if (!newh->value) {
        free(newh);
        return false;
    }
    strncpy(newh->value, s, strlen(s));
    *(newh->value + strlen(s)) = '\0';
    newh->next = q->head;
    q->head = newh;
    // Insert to empty queue, we have to update both head and tail pointer.
    if (++(q->size) == 1) {
        q->tail = newh;
    }
    return true;
}

q_insert_tail

ๆญคๅฏฆๅš่ทŸ q_insert_head() ๅนพไนŽไธ€่‡ด๏ผŒๆœ€ๅพŒๆ’ๅ…ฅๅˆฐๅฐพ็ซฏๅพŒไนŸ่ฆ็‰นๅˆฅๆณจๆ„ linked list ้•ทๅบฆ็”ฑ 0 ่ฎŠ 1 ็š„ๆƒ…ๆณ๏ผŒๆญคๆ™‚้ ญ่ˆ‡ๅฐพ็ซฏๆ˜ฏๆŒ‡ๅ‘ๅŒไธ€ๅ€‹ list node ใ€‚

bool q_insert_tail(queue_t *q, char *s)
{
    if (!q)
        return false;
    list_ele_t *newh = malloc(sizeof(list_ele_t));
    /* Don't forget to allocate space for the string and copy it */
    /* What if either call to malloc returns NULL? */
    if (!newh)
        return false;
    newh->value = malloc(sizeof(char) * (strlen(s) + 1));
    if (!newh->value) {
        free(newh);
        return false;
    }
    strncpy(newh->value, s, strlen(s));
    *(newh->value + strlen(s)) = '\0';
    newh->next = NULL;
    if (q->tail)
        q->tail->next = newh;
    q->tail = newh;
    // Insert to empty queue, we have to update both head and tail pointer.
    if (++(q->size) == 1) {
        q->head = newh;
    }
    return true;
}

q_remove_head

ๅ†่™•็†ๅฎŒๆฒ’ๆœ‰ queue ๆˆ–ๆ˜ฏ queue ็‚บ็ฉบ็š„ๆƒ…ๆณๅพŒ๏ผŒไพฟ่ƒฝไฝฟ็”จ strncpy() ่ค‡่ฃฝ๏ผŒไธฆๅœจๅญ—ไธฒๅฐพ็ซฏๅŠ ไธŠ null character ('\0') ใ€‚

ๆŽฅไธ‹ไพ†็งป้™ค้ ญ็ซฏ list node ่ฆๆณจๆ„ๅฟ…้ ˆ็ขบๅฏฆๅฐ‡้…็ฝฎๅœจ่ฉฒ list node ไธŠ็š„่จ˜ๆ†ถ้ซ”ๆธ…้™ค๏ผŒไบฆๅณๆธ…้™คๅฎŒๅญ—ไธฒๅพŒ๏ผŒๅ†ๅฐ‡ list node ๆธ…้™ค๏ผ›ๆœ€ๅพŒๅœจๆ›ดๆ–ฐ list size ๆ™‚ไนŸ่ฆๆณจๆ„็•ถ linked list ้•ทๅบฆ็”ฑ 1 ่ฎŠ 0 ๏ผŒๆˆ‘ๅ€‘่ฆๅฐ‡ queue ไธญ้ ญ็ซฏ่ˆ‡ๅฐพ็ซฏ็š„ๆŒ‡ๆจ™ๆ›ดๆ–ฐ็‚บ NULL ๏ผŒ้ฟๅ…ไน‹ๅพŒๅˆๅญ˜ๅ–ๅทฒๆธ…้™ค็š„่จ˜ๆ†ถ้ซ”้€ ๆˆ Segmentation fault ใ€‚

bool q_remove_head(queue_t *q, char *sp, size_t bufsize)
{
    if (!q || !q->head)
        return false;
    if (sp && bufsize > 0 && q->head->value) {
        strncpy(sp, q->head->value, bufsize - 1);
        *(sp + bufsize - 1) = '\0';
    }
    list_ele_t *tmp = q->head;
    q->head = q->head->next;
    if (tmp->value) {
        free(tmp->value);
    }
    free(tmp);
    // Remove element from queue with size 1,
    // we have to update both head and tail pointer.
    if (--(q->size) == 0) {
        q->head = q->tail = NULL;
    }
    return true;
}

q_size

ๆชขๆŸฅๅฎŒ queue ๅฐšๆœช่ขซๅปบ็ซ‹็š„ๆƒ…ๆณๅพŒ๏ผŒไพฟ็›ดๆŽฅๅ›žๅ‚ณ size ใ€‚

/*
 * Return number of elements in queue.
 * Return 0 if q is NULL or empty
 */
int q_size(queue_t *q)
{
    if (!q)
        return 0;
    return q->size;
}

ๅฏๆ”นๅฏซ็‚บไปฅไธ‹:

int q_size(queue_t *q)
{
    return q ? q->size : 0;
}

็ฐกๆฝ”ๅˆๆธ…ๆ™ฐ๏ผ

Image Not Showing Possible Reasons
  • The image file may be corrupted
  • The server hosting the image is unavailable
  • The image path is incorrect
  • The image format is not supported
Learn More โ†’
jserv

q_reverse

ไธ€้–‹ไฝฟๅ…ˆๅฐๆฒ’ๆœ‰ queue ๆˆ–ๆ˜ฏ linked list ๅ…งๅชๆœ‰ไธ€็ญ†่ณ‡ๆ–™็š„็‰นๅฎšๆƒ…ๆณๅš่™•็†ใ€‚
ๅ†ๅˆฉ็”จไปฅไธ‹3ๅ€‹ๆŒ‡ๆจ™ๆŒ็บŒ่ตฐ่จช linked list ไธฆๅ่ฝ‰ๅ…ถ้€ฃ็ตๆ–นๅ‘๏ผš

  1. pointer pre: ๆŒ‡ๅ‘ๅ‰ไธ€ๅ€‹ list node ๏ผŒๅฐๆ–ผ linked list ็š„้ ญ ( ็ฌฌไธ€ๅ€‹ element ) ไพ†่ชช๏ผŒไธฆๆฒ’ๆœ‰ๅ‰ไธ€ๅ€‹ list node ๏ผŒๅ› ๆญคๅˆๅง‹็‚บ NULL ใ€‚
  2. pointer cur: ๆŒ‡ๅ‘็พๅœจๆญฃ่ฆๅ่ฝ‰้€ฃ็ตๆ–นๅ‘็š„ list node ใ€‚
  3. pointer nex: ๆŒ‡ๅ‘ๅŽŸๆœฌ linked list ็š„ไธ‹ไธ€ๅ€‹ list node ๏ผŒ้ฟๅ…้บๅคฑไธ‹ไธ€ๅ€‹่ฆ่™•็† list node ็š„ไฝๅ€ใ€‚

ๅˆฉ็”จไปฅไธŠ 3 ๅ€‹ๆŒ‡ๆจ™๏ผŒๅœจ่ตฐ่จช linked list ไพๅบๅนณ็งปไธฆๅฐ‡ linked list ๅ่ฝ‰ใ€‚

void q_reverse(queue_t *q)
{
    if (!q || q->size <= 1)
        return;
    list_ele_t *pre = NULL, *cur = q->head, *nex = q->head->next;
    while (nex) {
        cur->next = pre;
        pre = cur;
        cur = nex;
        nex = cur->next;
    }
    cur->next = pre;
    cur = q->head;
    q->head = q->tail;
    q->tail = cur;
}

TODO: ็”จ for ๆ”นๅฏซไธฆ็ธฎๆธ› scope

Image Not Showing Possible Reasons
  • The image file may be corrupted
  • The server hosting the image is unavailable
  • The image path is incorrect
  • The image format is not supported
Learn More โ†’
jserv

q_sort

  • q_sort: Top level interface.
    ๅƒ่€ƒ Linked List Sort ๅ…ถไธญ็š„ Merge sort ใ€‚
    ไปค q_sort() ็‚บๆŽ’ๅบ็š„ Top level interface ๏ผŒ้™คไบ†ๆชขๆŸฅๆฒ’ๆœ‰ queue ๆˆ–ๆ˜ฏ้•ทๅบฆ็‚บ 1 ไธ้œ€่ฆๆŽ’ๅบ็š„ๆƒ…ๆณ๏ผŒไพฟ้€ฒๅˆฐ Merge sort ๆŽ’ๅบ๏ผŒไฝ†ๆŽ’ๅบๅพŒๆœƒๅคฑๅŽป linked list ๅฐพ็ซฏ็š„่ณ‡่จŠ๏ผŒๅ› ๆญค้œ€่ฆ้‡ๆ–ฐ่ตฐ่จช linked list ๆ‰พๅ›žๅฐพ็ซฏๆŒ‡ๆจ™ใ€‚
void q_sort(queue_t *q)
{
    if (!q || q->size <= 1)
        return;
    q->tail = q->head = merge_sort(q->head);
    // After merge sort, the pointer q->tail would no longer point
    // to the tail of queue anymore.
    while (q->tail->next) {
        q->tail = q->tail->next;
    }
}
  • merge_sort: Recursive merge sort (Divide and Conquer).
    ๅˆฉ็”จ้พœๅ…”่ณฝ่ท‘็š„ๆฆ‚ๅฟต๏ผŒไธ€ๅ€‹ๆŒ‡ๆจ™ไธ€ๆฌกๅ‰้€ฒไธ€ๆ ผ๏ผŒๅฆไธ€ๅ€‹ๆŒ‡ๆจ™ๅ‰‡ๆ˜ฏไธ€ๆฌกๅ‰้€ฒๅ…ฉๆ ผ๏ผŒไพฟ่ƒฝ้ †ๅˆฉ็š„ๆ‰พๅˆฐ linked list ็š„ไธญ้ปž๏ผŒไฝ†ๆ‰พๅˆฐไธญ้ปžๅพŒ่ฆๆณจๆ„็š„ๆ˜ฏๅฟ…้ ˆๅฐ‡ linked list ไธ€ๅˆ†็‚บไบŒ๏ผŒๆ‰่ƒฝๆŽฅไธ‹ๅŽป้ž่ฟดๅ‘ผๅซ๏ผŒๅˆ†ๅˆฅๆŽ’ๅบๅฅฝๅทฆๅณ partition ็š„ linked list ๏ผŒๅ†้€ฒๅˆฐๅˆไฝตไธฆๅ›žๅ‚ณ้ ญ็ซฏๆŒ‡ๆจ™ใ€‚
list_ele_t *merge_sort(list_ele_t *head)
{
    if (!head || !head->next)
        return head;
    list_ele_t *fast = head->next;
    list_ele_t *slow = head;
    // Find the cutting point.
    while (fast && fast->next) {
        slow = slow->next;
        fast = fast->next->next;
    }
    // Redirect the pointer to the right partition and split the linked list.
    fast = slow->next;
    slow->next = NULL;
    // Recursive call to sort the sub-lists.
    head = merge_sort(head);
    fast = merge_sort(fast);

    return merge(head, fast);
}
  • merge: Merge 2 linked list according to natural ordering.
    ไธ€้–‹ๅง‹ๅ…ˆๅฎš็พฉไธ€ๅ€‹ๆŒ‡ๅ‘ list_ele_t ็š„ๆŒ‡ๆจ™ head ๆŒ‡ๅ‘ NULL ๏ผŒ ๅ†ๅฆๅค–ไฝฟ็”จไธ€ๅ€‹ double pointer (pointer to pointer) cursor ไพ†่จ˜ไธ‹็›ฎๅ‰ๅˆไฝต linked list ้€ฒ่กŒๅˆฐ็š„ไฝ็ฝฎ๏ผŒๆŽฅไธ‹ไพ†ไพฟ่ƒฝ่ตฐ่จชๅ…ฉๅ€‹ linked list ๏ผŒไพๆ“šๅฎš็พฉๅฅฝ็š„ ordering ๅšๅˆไฝต๏ผŒๅˆฉ็”จ cursor ๆ›ดๆ–ฐ็›ฎๅ‰ๅฐพ็ซฏ็š„ list element ็š„ๆŒ‡ๆจ™๏ผ›ๆœ€ๅพŒ็•ถๆŸไธ€ๅ€‹ list ๅทฒ็ถ“่ตฐๅฎŒ๏ผŒๅ› ็‚บๅ…ฉๅ€‹ linked list ๆ—ฉๅทฒๅšๅฎŒๆŽ’ๅบ๏ผŒไพฟ่ƒฝ็›ดๆŽฅๅฆไธ€ๅ€‹ list ้™„ๅŠ ๅˆฐๅฐพ็ซฏ๏ผŒ็ตๆŸๅˆไฝต๏ผŒๅ†ๅ›žๅ‚ณๅˆไฝตๅพŒ็š„้ ญ็ซฏๆŒ‡ๆจ™ใ€‚
list_ele_t *merge(list_ele_t *p1, list_ele_t *p2)
{
    list_ele_t *head = NULL;
    list_ele_t **cursor = &head;
    // Merge 2 list according to their Lexicographical order.
    while (p1 && p2) {
        if (str_cmp(p1->value, p2->value) >= 0) {
            *cursor = p2;
            p2 = p2->next;
            cursor = &((*cursor)->next);
        } else {
            *cursor = p1;
            p1 = p1->next;
            cursor = &((*cursor)->next);
        }
    }
    // Append the last remaining list to the end of merged list.
    if (p1) {
        *cursor = p1;
    } else {
        *cursor = p2;
    }
    return head;
}
  • str_cmp:
    ๅˆฉ็”จๅ…ฉๅ€‹ pointer ๅŽปๅญ˜ๅ–ๅญ—ๅ…ƒๅšๆฏ”่ผƒ๏ผŒ่ทณๅ‡บ่ฟดๅœˆๅ‰‡ๆ˜ฏ้‡ๅˆฐๅฐพ็ซฏ๏ผŒๆˆ–ๆ˜ฏ้‡ๅˆฐ็ฌฌไธ€ๅ€‹ๅญ—ๅ…ƒไธๅŒ็š„ๆƒ…ๆณ๏ผŒๆœ€ๅพŒๅ›žๅ‚ณๅญ—ๅ…ธๅบ็š„ๅคงๅฐ๏ผŒๅœจ็ฐกๅŒ–ๆต็จ‹ไน‹ๅพŒไนŸ่ฆๆณจๆ„็•ถๅ…ฉๅ€‹ๅญ—ไธฒไธ€ๆจฃ๏ผŒ่ฆ่€ƒๆ…ฎๅ…ฉๅ€‹ pointer ๆœ€ๅพŒ้ƒฝๆŒ‡ๅ‘ null character ('\0') ็š„ๆƒ…ๆณใ€‚
int str_cmp(const char *s1, const char *s2)
{
    // Skip the same prefix of 2 given string
    // After leaving while loop, either pointer s1 and s2 would point
    // to the first distinct character or both of them point to '\0'.
    while (*s1 != '\0' && *s2 != '\0' && *s1 == *s2) {
        ++s1, ++s2;
    }
    // Consider their Lexicographical order (also cover the case of eqivalence).
    return (*s1 > *s2) * (1) + (*s1 < *s2) * (-1);
}

Old version of my q_sort() (2/23)

ไธ€้–‹ๅง‹็œ‹ๅฎŒ Linked List Sort ็š„ไป‹็ดนๅ…ถไธญ็š„ๅœ–็‰‡ไพฟ่‘—ๆ‰‹้–‹ๅง‹ๅฏฆ็พๆฒ’ๆœ‰้ž่ฟดๅ‘ผๅซ็š„ merge sort ๏ผŒไฝฟ็”จ Bottom-up ็š„ๆ–นๅผ๏ผŒ for ่ฟดๅœˆ็ฌฌไธ€ๆฌก iteration ็‚บๆฏๅ€‹้•ทๅบฆ็‚บ 2 ็š„ sub-list ๅฎŒๆˆๆŽ’ๅบ๏ผŒ็ฌฌไบŒๆฌก iteration ็‚บๆฏๅ€‹้•ทๅบฆ็‚บ 4 ็š„ sub-list ๅฎŒๆˆๆŽ’ๅบ๏ผŒไพๆญค้กžๆŽจ (ๅณ for ่ฟดๅœˆไธญ k*=2 )ใ€‚

Bottom-up merge sort
From: Linked List Sort

ไฝ†ๆ˜ฏ่ง€ๅฏŸไปฅไธ‹็จ‹ๅผ็ขผไพฟๆœƒ็™ผ็พๅœจๆŽ’ๅบๅฐ่ฑกๆ˜ฏ linked list ่€Œ้žไธ€่ˆฌ้™ฃๅˆ—็š„ๆ™‚ๅ€™๏ผŒๆœƒๅœจๆ‰พๅฐ‹ๅทฆๅณ่ฆๅˆไฝต็š„ partition ไธญ่Šฑๅพˆๅคง็š„ๅŠŸๅคซ๏ผŒไธฆไธ”ๆŽ’ๅบ็”Ÿๆˆ็š„ๆจน็‹€ๅœ–ๅฝขๆœƒๅฆ‚ๅŒไธŠๅœ–่ˆฌ็‚บไธ€ๆฃตไธๅนณ่กก็š„ๆจน๏ผŒๅœจๆ™‚้–“่ค‡้›œๅบฆไธŠๆœƒๅคšไธ€ไบ› lower order ็š„้ …ๆฌก๏ผŒ่€Œไธ”็จ‹ๅผ็ขผ้‚„ๆฏ”่ผƒ่ค‡้›œ (ๆœฌ่บซๅŠŸๅŠ›ไธ่ถณไนŸๆœ‰้—œไฟ‚ QQ )ใ€‚

ๅ› ๆญคๆœ€ๅพŒ้‚„ๆ˜ฏๅฅฝๅฅฝ็š„ๅˆฉ็”จ้ž่ฟด๏ผŒๅฐ‡ merge sort ไพๅ„้ƒจๅŠŸ่ƒฝๅฏฆ็พใ€‚

void q_sort(queue_t *q)
{
    if (!q || q->size <= 1)
        return;

    for (int k = 1; k < q->size; k *= 2) {
        list_ele_t **cursor = &(q->head);  // storing point
        list_ele_t *point = q->head;       // processing point
        list_ele_t *left = point, *right = point;
        int t = k;
        while (t && right) {
            --t;
            right = right->next;
        }
        point = right;
        t = k;
        while (t && point) {
            --t;
            point = point->next;
        }
        while (right) {
            int left_size = k;
            while (left_size && right != point) {
                if (str_cmp(left->value, right->value) >= 0) {
                    *cursor = right;
                    right = right->next;
                    cursor = &((*cursor)->next);
                } else {
                    *cursor = left;
                    left = left->next;
                    cursor = &((*cursor)->next);
                    --left_size;
                }
            }
            while (left_size) {
                *cursor = left;
                q->tail = left;
                left = left->next;
                cursor = &((*cursor)->next);
                --left_size;
            }
            while (right != point) {
                *cursor = right;
                q->tail = right;
                right = right->next;
                cursor = &((*cursor)->next);
            }
            *cursor = point;
            left = right = point;
            t = k;
            while (t && right) {
                --t;
                right = right->next;
            }
            point = right;
            t = k;
            while (t && point) {
                --t;
                point = point->next;
            }
        }
    }
}

Natural sort

ๆŽก็”จ Natural Sort ไพ†็‚บๅญ—ไธฒ้€ฒ่กŒๆŽ’ๅบ (้€ฃ็ตๅ…งๅทฒๆœ‰่ฉณ็ดฐๆ•˜่ฟฐ) ใ€‚

  1. ๅฐ‡ strnatcmp.c ่ˆ‡ strnatcmp.h ๅŠ ๅ…ฅๅฐˆๆกˆใ€‚

  2. ไฟฎๆ”น Makefile ๏ผŒๅŠ ๅ…ฅ strnatcmp.o ้€ฒ $(OBJS) ไปฅไพฟๅฐˆๆกˆๅปบๅˆถใ€‚

    โ€‹โ€‹โ€‹โ€‹OBJS := qtest.o report.o console.o harness.o queue.o \
    โ€‹โ€‹โ€‹โ€‹        random.o dudect/constant.o dudect/fixture.o dudect/ttest.o \
    โ€‹โ€‹โ€‹โ€‹        strnatcmp.o
    
  3. ๆŽฅไธ‹ไพ†ๅฐฑๅฏไปฅๅœจๅฐˆๆกˆไธญ็š„ queue.c ๅผ•็”จ strnatcmp.h ไธฆไฝฟ็”จๅ…ถๅ‡ฝๆ•ธๅ›‰๏ผŒๆœ‰่ถฃ็š„ๆ˜ฏๅœจ strnatcmp.c ไธญๆœ‰ๅ…ฉ็จฎๆฏ”่ผƒ Natural ordering ็š„ๅ‡ฝๅผๅˆ†ๅˆฅ็‚บ strnatcmp() ่ˆ‡ strnatcasecmp() ๏ผŒๆทฑๅ…ฅๅŽป็œ‹ๅฏไปฅ็™ผ็พ strnatcasecmp() ๅ…ถๅฏฆๆ˜ฏๆŠŠๅญ—ๅ…ƒ่ฝ‰ๆ›็‚บๅคงๅฏซ (uppercase) ๅพŒๅ†ๅšๆฏ”่ผƒ๏ผŒๅ› ๆญคๅƒๆ˜ฏๅบ•็ทš _ ้€™ๅ€‹ๅธธ็”จๅœจๆช”ๅ็š„ๅญ—ๅ…ƒ่ˆ‡ไธ€่ˆฌ่‹ฑๆ–‡ๅญ—ๆฏๆฏ”่ผƒ๏ผŒๅ„ชๅ…ˆๅบฆๅฐฑๆœƒไฝŽ๏ผŒๅœจ้€™้‚Šๆˆ‘ๅ€‘ๅฐฑๆŽก็”จ strnatcasecmp() ใ€‚

    โ€‹โ€‹โ€‹โ€‹/*
    โ€‹โ€‹โ€‹โ€‹ * Merge 2 linked list into 1 linked list in ascending order.
    โ€‹โ€‹โ€‹โ€‹ */
    โ€‹โ€‹โ€‹โ€‹list_ele_t *merge(list_ele_t *p1, list_ele_t *p2)
    โ€‹โ€‹โ€‹โ€‹{
    โ€‹โ€‹โ€‹โ€‹    list_ele_t *head = NULL;
    โ€‹โ€‹โ€‹โ€‹    list_ele_t **cursor = &head;
    โ€‹โ€‹โ€‹โ€‹    // Merge 2 list according to their Lexicographical order.
    โ€‹โ€‹โ€‹โ€‹    while (p1 && p2) {
    โ€‹โ€‹โ€‹โ€‹        // if (str_cmp(p1->value, p2->value) >= 0) {
    โ€‹โ€‹โ€‹โ€‹        if (strnatcasecmp(p1->value, p2->value) >= 0) {
    โ€‹โ€‹โ€‹โ€‹            *cursor = p2;
    โ€‹โ€‹โ€‹โ€‹            p2 = p2->next;
    โ€‹โ€‹โ€‹โ€‹            cursor = &((*cursor)->next);
    โ€‹โ€‹โ€‹โ€‹        } else {
    โ€‹โ€‹โ€‹โ€‹            *cursor = p1;
    โ€‹โ€‹โ€‹โ€‹            p1 = p1->next;
    โ€‹โ€‹โ€‹โ€‹            cursor = &((*cursor)->next);
    โ€‹โ€‹โ€‹โ€‹        }
    โ€‹โ€‹โ€‹โ€‹    }
    โ€‹โ€‹โ€‹โ€‹    // Append the last remaining list to the end of merged list.
    โ€‹โ€‹โ€‹โ€‹    if (p1) {
    โ€‹โ€‹โ€‹โ€‹        *cursor = p1;
    โ€‹โ€‹โ€‹โ€‹    } else {
    โ€‹โ€‹โ€‹โ€‹        *cursor = p2;
    โ€‹โ€‹โ€‹โ€‹    }
    โ€‹โ€‹โ€‹โ€‹    return head;
    โ€‹โ€‹โ€‹โ€‹}
    
  4. ๆŽฅไธ‹ไพ†ๆˆ‘ๅ€‘ๅฏไปฅ็‚บ Natural Sort ่ฃกๆไพ›็š„ๆธฌ่ณ‡ๅ‰ตๅปบๆ–ฐ็š„ๆธฌ่ณ‡ๆช”ๆกˆไธฆๅœจ driver.py ไธญๅŠ ๅ…ฅ็›ธๅฐๆ‡‰็š„ๆช”ๅ่ˆ‡ๅˆ†ๆ•ธ็ญ‰ใ€‚

    โ€‹โ€‹โ€‹โ€‹    traceDict = {
    โ€‹โ€‹โ€‹โ€‹        # ...
    โ€‹โ€‹โ€‹โ€‹        16: "trace-16-perf",
    โ€‹โ€‹โ€‹โ€‹        17: "trace-17-complexity",
    โ€‹โ€‹โ€‹โ€‹        # Natural sort testing data
    โ€‹โ€‹โ€‹โ€‹        18: "trace-18-test-dates",
    โ€‹โ€‹โ€‹โ€‹        19: "trace-19-test-debs",
    โ€‹โ€‹โ€‹โ€‹        20: "trace-20-test-debvers",
    โ€‹โ€‹โ€‹โ€‹        21: "trace-21-test-fractions",
    โ€‹โ€‹โ€‹โ€‹        22: "trace-22-test-versions",
    โ€‹โ€‹โ€‹โ€‹        23: "trace-23-test-words"
    โ€‹โ€‹โ€‹โ€‹    }
    
    โ€‹โ€‹โ€‹โ€‹ traceProbs = { โ€‹โ€‹โ€‹โ€‹ # ... โ€‹โ€‹โ€‹โ€‹ 17: "Trace-17", โ€‹โ€‹โ€‹โ€‹ # Natural sort testing data โ€‹โ€‹โ€‹โ€‹ 18: "Trace-18", โ€‹โ€‹โ€‹โ€‹ 19: "Trace-19", โ€‹โ€‹โ€‹โ€‹ 20: "Trace-20", โ€‹โ€‹โ€‹โ€‹ 21: "Trace-21", โ€‹โ€‹โ€‹โ€‹ 22: "Trace-22", โ€‹โ€‹โ€‹โ€‹ 23: "Trace-23" โ€‹โ€‹โ€‹โ€‹}
    โ€‹โ€‹โ€‹โ€‹    maxScores = [0, 6, 6, 6, 6, 5, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 
    โ€‹โ€‹โ€‹โ€‹                5, 6, 6, 6, 6, 6, 6]
    
  5. ๅฆๅค–่ฆๆณจๆ„ๆœ‰ๆธฌ่ณ‡ๆช”ๅพŒ๏ผŒ้‚„ๅฟ…้ ˆ่ฆไฟฎๆ”น qtest.c ไธญ็‚บ sorting ็ตๆžœๅšๆชขๆŸฅ็š„้ƒจไปฝ๏ผŒๅ› ็‚บไธ€้–‹ๅง‹ๆ˜ฏไฝฟ็”จ strcasecmp() ่€Œ้ž strnatcasecmp() ใ€‚

    โ€‹โ€‹โ€‹โ€‹// ... โ€‹โ€‹โ€‹โ€‹bool ok = true; โ€‹โ€‹โ€‹โ€‹if (q) { โ€‹โ€‹โ€‹โ€‹ for (list_ele_t *e = q->head; e && --cnt; e = e->next) { โ€‹โ€‹โ€‹โ€‹ /* Ensure each element in ascending order */ โ€‹โ€‹โ€‹โ€‹ /* FIXME: add an option to specify sorting order */ โ€‹โ€‹โ€‹โ€‹ // if (strcasecmp(e->value, e->next->value) > 0) { โ€‹โ€‹โ€‹โ€‹ if (strnatcasecmp(e->value, e->next->value) > 0) { โ€‹โ€‹โ€‹โ€‹ report(1, "ERROR: Not sorted in ascending order"); โ€‹โ€‹โ€‹โ€‹ ok = false; โ€‹โ€‹โ€‹โ€‹ break; โ€‹โ€‹โ€‹โ€‹ } โ€‹โ€‹โ€‹โ€‹ } โ€‹โ€‹โ€‹โ€‹}
  6. ๆœ€ๅพŒไพฟ่ƒฝ้ †ๅˆฉไฝฟ็”จ Natural sort ๅšๆธฌ่ฉฆใ€‚

    โ€‹โ€‹โ€‹โ€‹$ make test
    โ€‹โ€‹โ€‹โ€‹scripts/driver.py -c
    โ€‹โ€‹โ€‹โ€‹---     Trace           Points
    โ€‹โ€‹โ€‹โ€‹+++ TESTING trace trace-01-ops:
    โ€‹โ€‹โ€‹โ€‹# Test of insert_head and remove_head
    โ€‹โ€‹โ€‹โ€‹---     trace-01-ops    6/6
    โ€‹โ€‹โ€‹โ€‹+++ TESTING trace trace-02-ops:
    โ€‹โ€‹โ€‹โ€‹# Test of insert_head, insert_tail, and remove_head
    โ€‹โ€‹โ€‹โ€‹---     trace-02-ops    6/6
    โ€‹โ€‹โ€‹โ€‹+++ TESTING trace trace-03-ops:
    โ€‹โ€‹โ€‹โ€‹# Test of insert_head, insert_tail, reverse, and remove_head
    โ€‹โ€‹โ€‹โ€‹---     trace-03-ops    6/6
    โ€‹โ€‹โ€‹โ€‹+++ TESTING trace trace-04-ops:
    โ€‹โ€‹โ€‹โ€‹# Test of insert_head, insert_tail, size, and sort
    โ€‹โ€‹โ€‹โ€‹---     trace-04-ops    6/6
    โ€‹โ€‹โ€‹โ€‹+++ TESTING trace trace-05-ops:
    โ€‹โ€‹โ€‹โ€‹# Test of insert_head, insert_tail, remove_head, reverse, size, and sort
    โ€‹โ€‹โ€‹โ€‹---     trace-05-ops    5/5
    โ€‹โ€‹โ€‹โ€‹+++ TESTING trace trace-06-string:
    โ€‹โ€‹โ€‹โ€‹# Test of truncated strings
    โ€‹โ€‹โ€‹โ€‹---     trace-06-string 6/6
    โ€‹โ€‹โ€‹โ€‹+++ TESTING trace trace-07-robust:
    โ€‹โ€‹โ€‹โ€‹# Test operations on NULL queue
    โ€‹โ€‹โ€‹โ€‹---     trace-07-robust 6/6
    โ€‹โ€‹โ€‹โ€‹+++ TESTING trace trace-08-robust:
    โ€‹โ€‹โ€‹โ€‹# Test operations on empty queue
    โ€‹โ€‹โ€‹โ€‹---     trace-08-robust 6/6
    โ€‹โ€‹โ€‹โ€‹+++ TESTING trace trace-09-robust:
    โ€‹โ€‹โ€‹โ€‹# Test remove_head with NULL argument
    โ€‹โ€‹โ€‹โ€‹---     trace-09-robust 6/6
    โ€‹โ€‹โ€‹โ€‹+++ TESTING trace trace-10-malloc:
    โ€‹โ€‹โ€‹โ€‹# Test of malloc failure on new
    โ€‹โ€‹โ€‹โ€‹---     trace-10-malloc 6/6
    โ€‹โ€‹โ€‹โ€‹+++ TESTING trace trace-11-malloc:
    โ€‹โ€‹โ€‹โ€‹# Test of malloc failure on insert_head
    โ€‹โ€‹โ€‹โ€‹---     trace-11-malloc 6/6
    โ€‹โ€‹โ€‹โ€‹+++ TESTING trace trace-12-malloc:
    โ€‹โ€‹โ€‹โ€‹# Test of malloc failure on insert_tail
    โ€‹โ€‹โ€‹โ€‹---     trace-12-malloc 6/6
    โ€‹โ€‹โ€‹โ€‹+++ TESTING trace trace-13-perf:
    โ€‹โ€‹โ€‹โ€‹# Test performance of insert_tail
    โ€‹โ€‹โ€‹โ€‹---     trace-13-perf   6/6
    โ€‹โ€‹โ€‹โ€‹+++ TESTING trace trace-14-perf:
    โ€‹โ€‹โ€‹โ€‹# Test performance of size
    โ€‹โ€‹โ€‹โ€‹---     trace-14-perf   6/6
    โ€‹โ€‹โ€‹โ€‹+++ TESTING trace trace-15-perf:
    โ€‹โ€‹โ€‹โ€‹# Test performance of insert_tail, size, reverse, and sort
    โ€‹โ€‹โ€‹โ€‹ERROR: Time limit exceeded.  Either you are in an infinite loop, or your code is too inefficient
    โ€‹โ€‹โ€‹โ€‹---     trace-15-perf   0/6
    โ€‹โ€‹โ€‹โ€‹+++ TESTING trace trace-16-perf:
    โ€‹โ€‹โ€‹โ€‹# Test performance of sort with random and descending orders
    โ€‹โ€‹โ€‹โ€‹# 10000: all correct sorting algorithms are expected pass
    โ€‹โ€‹โ€‹โ€‹# 50000: sorting algorithms with O(n^2) time complexity are expected failed
    โ€‹โ€‹โ€‹โ€‹# 100000: sorting algorithms with O(nlogn) time complexity are expected pass
    โ€‹โ€‹โ€‹โ€‹---     trace-16-perf   6/6
    โ€‹โ€‹โ€‹โ€‹+++ TESTING trace trace-17-complexity:
    โ€‹โ€‹โ€‹โ€‹# Test if q_insert_tail and q_size is constant time complexity
    โ€‹โ€‹โ€‹โ€‹Probably constant time
    โ€‹โ€‹โ€‹โ€‹Probably constant time
    โ€‹โ€‹โ€‹โ€‹---     trace-17-complexity     5/5
    โ€‹โ€‹โ€‹โ€‹+++ TESTING trace trace-18-test-dates:
    โ€‹โ€‹โ€‹โ€‹---     trace-18-test-dates     6/6
    โ€‹โ€‹โ€‹โ€‹+++ TESTING trace trace-19-test-debs:
    โ€‹โ€‹โ€‹โ€‹---     trace-19-test-debs      6/6
    โ€‹โ€‹โ€‹โ€‹+++ TESTING trace trace-20-test-debvers:
    โ€‹โ€‹โ€‹โ€‹---     trace-20-test-debvers   6/6
    โ€‹โ€‹โ€‹โ€‹+++ TESTING trace trace-21-test-fractions:
    โ€‹โ€‹โ€‹โ€‹# Fractional release numbers
    โ€‹โ€‹โ€‹โ€‹---     trace-21-test-fractions 6/6
    โ€‹โ€‹โ€‹โ€‹+++ TESTING trace trace-22-test-versions:
    โ€‹โ€‹โ€‹โ€‹---     trace-22-test-versions  6/6
    โ€‹โ€‹โ€‹โ€‹+++ TESTING trace trace-23-test-words:
    โ€‹โ€‹โ€‹โ€‹---     trace-23-test-words     6/6
    โ€‹โ€‹โ€‹โ€‹---     TOTAL           130/136
    

    ไฝ†ๆ˜ฏ็›ฎๅ‰้‚„ๆ˜ฏๆœ‰ไธ€ๅ€‹ๅ•้กŒๆœช่งฃๆฑบ๏ผŒๅฐฑๆ˜ฏๆŽก็”จ Natural Sort ๅพŒๆœƒ่ฎ“ๆธฌ่ฉฆ้ …็›ฎ็ทจ่™Ÿ 15 trace-15-perf TLE ๏ผŒๅŽป้™คๆމไธ€่ˆฌๅญ—ๅ…ƒๆฏ”่ผƒ็š„้ƒจไปฝ๏ผŒๅฏ่ƒฝ็š„ๅŽŸๅ› ๆ˜ฏๅšๅฎŒไธ€่ˆฌๅญ—ๅ…ƒ prefix ๆชขๆŸฅๅพŒ๏ผŒไพฟ้ ˆ่ฆๅฐๅ‰ฉ้ค˜็š„ๆ•ธๅญ—ๅญ—ไธฒ (digits) ๅšๅคงๅฐ็š„ๆฏ”่ผƒ๏ผŒๅ› ๆญคๆญค่™•ไนŸๆ˜ฏไน‹ๅพŒๅฏไปฅๅŠ ๅผท็š„้ƒจไปฝใ€‚

    TODO:
    ็ ”็ฉถๆ˜ฏๅฆ่ƒฝๅ†ๆๅ‡ Natural Sort ็š„ๆ•ˆ็އใ€‚

Valgrind & Massif

ไฝฟ็”จ Valgrind ๆŽ’้™คๅฏฆไฝœ็š„่จ˜ๆ†ถ้ซ”้Œฏ่ชค

ไฝฟ็”จไปฅไธ‹ๆŒ‡ไปค้‹็”จ Valgrind ๆ‰พๅฐ‹ๅ‡บ้Œฏ็š„ๅœฐๆ–น๏ผŒๅˆฐ็ฌฌ3็ญ†ๆธฌ่ณ‡ trace-03-ops ๆ™‚้‡ๅˆฐ๏ผš

$ make valgrind

+++ TESTING trace trace-03-ops:
# Test of insert_head, insert_tail, reverse, and remove_head
==12439== Invalid read of size 8
==12439==    at 0x10CDA9: q_reverse (queue.c:161)
==12439==    by 0x109D92: do_reverse (qtest.c:463)
==12439==    by 0x10B90B: interpret_cmda (console.c:220)
==12439==    by 0x10BE83: interpret_cmd (console.c:243)
==12439==    by 0x10C440: cmd_select (console.c:571)
==12439==    by 0x10C66F: run_console (console.c:630)
==12439==    by 0x10ADA7: main (qtest.c:770)
==12439==  Address 0x8 is not stack'd, malloc'd or (recently) free'd
==12439== 
ERROR: Segmentation fault occurred.  You dereferenced a NULL or invalid pointer

ๅ›ž่ฟฝ่‡ณ q_reverse() ็™ผ็พๆ˜ฏๅœจๅ่ฝ‰ linked list ๆœ€ๅพŒ้‚„ๆœƒๅŽปๅฐๅฐพ็ซฏ็ฏ€้ปž็š„ๆŒ‡ๆจ™ next ๆœƒๆŒ‡ๅ‘ NULL ๆˆ‘ๅป้‚„ๅŽปๅญ˜ๅ–้€ ๆˆ Segmentation fault ใ€‚

void q_reverse(queue_t *q) { if (!q || q->size <= 1) return; list_ele_t *pre = NULL, *cur = q->head, *nex = q->head->next; while (cur) { cur->next = pre; pre = cur; cur = nex; nex = cur->next; } cur = q->head; q->head = q->tail; q->tail = cur; }

็ถ“้Žไบ›ๅพฎไฟฎๆ”น่งฃๆฑบ่จ˜ๆ†ถ้ซ”ๅญ˜ๅ–็š„ๅ•้กŒใ€‚

void q_reverse(queue_t *q) { if (!q || q->size <= 1) return; list_ele_t *pre = NULL, *cur = q->head, *nex = q->head->next; while (nex) { cur->next = pre; pre = cur; cur = nex; nex = cur->next; } cur->next = pre; cur = q->head; q->head = q->tail; q->tail = cur; }

TODO: ็”จ diff (HackMD ๆ”ฏๆด่ฉฒ่ชžๆณ•ๆจ™็คบ) ไพ†ๅฑ•็พ็จ‹ๅผ็ขผไน‹้–“็š„ๅทฎ็•ฐ

Image Not Showing Possible Reasons
  • The image file may be corrupted
  • The server hosting the image is unavailable
  • The image path is incorrect
  • The image format is not supported
Learn More โ†’
jserv

ๅˆฉ็”จ Massif ่ฆ–่ฆบๅŒ–่จ˜ๆ†ถ้ซ”็š„ไฝฟ็”จ

้–‹ๅ•Ÿ stack flag ่ง€ๅฏŸ merge sort!?

Paper reading

System of Select

Reference

Appendix of interesting information

XOR Linked List: ๅˆฉ็”จ exclusive or ็š„็‰นๆ€ง๏ผŒๆˆ‘ๅ€‘ๅฏไปฅ้”ๅˆฐ็”จ single pointer ้™คๅญ˜ double pointer ็š„ๆ•ˆๆžœ๏ผŒ็ผบ้ปžๆ˜ฏๅฟ…้ ˆ่ฆๆœ‰ๅพ—็Ÿฅๅ…ฉๅ€‹็›ธ้„ฐ็š„ list node ๆ‰่ƒฝ็นผ็บŒๆŽจ็† (inferencing) ไน‹ๅพŒ็š„ list node ไฝๅ€ใ€‚