feat:增加了对makefile valgrind gdb说明的链接

This commit is contained in:
LRache 2024-11-08 18:48:37 +08:00 committed by E1PsyCongroo
parent 3ecba7ea5b
commit 3f1183d4ff
27 changed files with 7 additions and 1221 deletions

View File

@ -1,8 +0,0 @@
#ifndef PWD_CHECKER_H
#define PWD_CHECKER_H
#include <stdbool.h>
bool check_password(const char *first_name, const char *last_name, const char *password);
#endif // PWD_CHECKER_H

View File

@ -1,95 +0,0 @@
#include "checker.h"
#include <assert.h>
#include <string.h>
/*
Password checker
Requirements:
- Password must be at least 10 characters
- Password must contain at least
- 1 upper case letter
- 1 lower case letter
- 1 number
- Password cannot contain the person's first name or last name (case sensitive)
For the simplicity of this exercise:
- This is not the most efficient way to implement this program
- These functions do not perform any error checking
- You can assume that the first and last name will never be the empty string
*/
/* Returns true if the length of PASSWORD is at least 10, false otherwise */
bool check_length(const char *password) {
int length = strlen(password);
bool meets_len_req = (length >= 10);
return meets_len_req;
}
/* Returns true if LETTER is in the range [LOWER, UPPER], false otherwise */
bool check_range(char letter, char lower, char upper) {
bool is_in_range = (letter >= lower && letter <= upper);
return is_in_range;
}
/* Returns true if PASSWORD contains at least one upper case letter, false
* otherwise */
bool check_upper(const char *password) {
while (*password != '\0') {
bool is_in_range = check_range(*password, 'A', 'Z');
if (is_in_range) {
return true;
}
++password;
}
return false;
}
/* Returns true if PASSWORD contains at least one lower case letter, false
* otherwise */
bool check_lower(const char *password) {
while (*password != '\0') {
bool is_in_range = check_range(*password, 'a', 'z');
if (is_in_range) {
return true;
}
++password;
}
return false;
}
/* Returns true if PASSWORD contains at least one number, false otherwise */
bool check_number(const char *password) {
while (*password != '\0') {
if (check_range(*password, '0', '9')) {
return true;
}
++password;
}
return false;
}
/* Returns true if the person's first and last name are NOT in the password,
* false otherwise */
bool check_name(const char *first_name, const char *last_name,
const char *password) {
/* Type "man strstr" in your terminal to learn what strstr does!
To exit the man pages, press 'q' */
/* Hint: a NULL pointer will evaluate to False in a logical statement while a
non-NULL pointer will evaluate to True */
const char *first = strstr(password, first_name);
const char *last = strstr(password, last_name);
return (!first && !last);
}
/* Returns true if PASSWORD meets the conditions specified above */
bool check_password(const char *first_name, const char *last_name,
const char *password) {
bool length, upper, lower, number, name;
lower = check_lower(password);
length = check_length(password);
name = check_name(first_name, last_name, password);
number = check_number(password);
upper = check_upper(password);
return (lower && length && name && upper && number);
}

View File

@ -1,52 +0,0 @@
#include "checker.h"
#include <assert.h>
#include <stdio.h>
int main() {
printf("Running tests...\n\n");
const char *test1_first = "Abraham";
const char *test1_last = "Garcia";
const char *test1_pwd = "qrtv?,mp!ltrA0b13rab4ham";
bool test1 = check_password(test1_first, test1_last, test1_pwd);
assert(test1);
const char *test2_first = "Anjali";
const char *test2_last = "Patel";
const char *test2_pwd = "Aj8r";
bool test2 = check_password(test2_first, test2_last, test2_pwd);
assert(!test2);
const char *test3_first = "Chantelle";
const char *test3_last = "Brown";
const char *test3_pwd = "QLRIOW815N";
bool test3 = check_password(test3_first, test3_last, test3_pwd);
assert(!test3);
const char *test4_first = "Wei";
const char *test4_last = "Zhang";
const char *test4_pwd = "pjkdihn!o901";
bool test4 = check_password(test4_first, test4_last, test4_pwd);
assert(!test4);
const char *test5_first = "John";
const char *test5_last = "Smith";
const char *test5_pwd = "ALKLIenhLq";
bool test5 = check_password(test5_first, test5_last, test5_pwd);
assert(!test5);
const char *test6_first = "Haeun";
const char *test6_last = "Kim";
const char *test6_pwd = "Ji9anjwHaeun";
bool test6 = check_password(test6_first, test6_last, test6_pwd);
assert(!test6);
const char *test7_first = "Adeline";
const char *test7_last = "DuBois";
const char *test7_pwd = "ALKLIDuBoisen3hLq";
bool test7 = check_password(test7_first, test7_last, test7_pwd);
assert(!test7);
printf("Congrats! You have passed all of the test cases!\n");
return 0;
}

View File

@ -1,163 +0,0 @@
# Lab6 使用工具
## GCC、多文件编译和Makefile
### Task1
1. 使用命令`gcc ./task1.c -o ./task1 -Wall -Werror`编译,会看到两个错误。
2. 错误分别是将`char`赋值给`char*`和返回的`Cource **`与函数声明中的`Course *`不符。
3. 修改:
```patch
--- ./task1.c
+++ ./task1_solution.c
@@ -10,9 +10,9 @@
struct Course *make_course(int id, char *name) {
struct Course *new_course = malloc(sizeof(struct Course));
new_course->id = id;
- new_course->name = *name;
+ new_course->name = name;
- return &new_course;
+ return new_course;
}
int main() {
struct Course *cstart = make_course(0x001, "cstart");
```
### Task2
1. 在目录`./zuma`下使用命令`gcc -I./include ./src/linkedlist.c ./src/main.c ./src/zuma.c -o zuma`进行编译。
2. 错误是由引入了两次`zuma.h`头文件(在`zuma.c`的第一行,第一次引入,在第二行包含`linkedlist.h`的时候再次引入)造成的,多个变量被重复声明。
3. 解决办法:
方法一:
```patch
--- ./zuma/include/zuma.h
+++ ./zuma/include/zuma_solution.h
@@ -1,3 +1,5 @@
+#pragma once
+
#include <stdio.h>
#include <stdlib.h>
```
方法二:
```patch
--- ./zuma/include/zuma.h
+++ ./zuma/include/zuma_solution.h
@@ -1,3 +1,6 @@
+#ifndef __ZUMA_H__
+#define __ZUMA_H__
+
#include <stdio.h>
#include <stdlib.h>
@@ -17,4 +20,6 @@
void set_top(int k);
void init();
void solve();
-void print_all();
\ No newline at end of file
+void print_all();
+
+#endif
```
### Task3 Task4 Task5
见`./zuma/makefile`。
### Task6 Task7
见`./zuma/task67.mk`。这是一个复杂的脚本。基本思想是:
1. 为每个`.c`源文件生成一个`.o`的目标文件。
2. 每个目标文件`.o`的依赖由`gcc -MMD`生成。
一些细节:
1. 通过规则`$(BUILD_DIR)/%.o: ./src/%.c`为每一个`.c`文件生成一个`.o`文件,并且附带一个`.d`的依赖文件来表明依赖。
2. `-include $(DEPS)`用于引入`gcc`生成的依赖,你可以查看`build`目录下的`.d`文件来理解。
### Task8
使用`bear -- make`。
## 调试工具
### Task9
现在你学会了`assert`,尝试在你自己项目中进行防御性编程吧。
### Task10 Task11
错误有三个地方:
```patch
--- ./src/checker.c
+++ ./src/checker_solution.c
@@ -22,13 +22,13 @@
/* Returns true if the length of PASSWORD is at least 10, false otherwise */
bool check_length(const char *password) {
int length = strlen(password);
- bool meets_len_req = (length <= 10);
+ bool meets_len_req = (length >= 10);
return meets_len_req;
}
/* Returns true if LETTER is in the range [LOWER, UPPER], false otherwise */
bool check_range(char letter, char lower, char upper) {
- bool is_in_range = (letter > lower && letter < upper);
+ bool is_in_range = (letter >= lower && letter <= upper);
return is_in_range;
}
@@ -59,7 +59,7 @@
/* Returns true if PASSWORD contains at least one number, false otherwise */
bool check_number(const char *password) {
while (*password != '\0') {
- if (check_range(*password, 0, 9)) {
+ if (check_range(*password, '0', '9')) {
return true;
}
++password;
```
### Task12
问题在于对一个`NULL`解引用并且赋值。
```patch
--- ./task12.c
+++ ./task12_solution.c
@@ -11,8 +11,6 @@
}
void ben(int *arr, int size) {
- int *ptr = NULL;
- *ptr = 10;
jero(arr, size);
}
```
### Task13
问题在于`alloc_str`函数,它没有为字符串末尾的`'\0'`分配空间。
```patch
--- ./task13.c
+++ ./task13_solution.c
@@ -7,7 +7,9 @@
#include <string.h>
char *alloc_str(int len) {
- return malloc(len*sizeof(char));
+ char *p = (char *)malloc((len+1)*sizeof(char));
+ p[len] = '\0';
+ return p;
}
/* Str helper functions */
```

View File

@ -1,23 +0,0 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
struct Course {
int id;
char *name;
};
struct Course *make_course(int id, char *name) {
struct Course *new_course = malloc(sizeof(struct Course));
new_course->id = id;
new_course->name = name;
return new_course;
}
int main() {
struct Course *cstart = make_course(0x001, "cstart");
printf("Welcome to CS%d: %s!\n", cstart->id, cstart->name);
free(cstart);
return 0;
}

View File

@ -1,31 +0,0 @@
#include <stdlib.h>
void jedi(int *arr, int size);
void ben(int *arr, int size);
void jero(int *arr, int size);
void jedi(int *arr, int size) {
for (int i = 0; i < size; ++i) {
arr[i] = i * 10;
}
}
void ben(int *arr, int size) { jero(arr, size); }
void jero(int *arr, int size) {
int *new_arr = (int *)malloc(size * sizeof(int));
if (new_arr == NULL) {
return;
}
for (int i = 0; i < size; ++i) {
new_arr[i] = arr[i];
}
jedi(new_arr, size);
free(new_arr);
}
int main() {
int arr[10];
ben(arr, 10);
return 0;
}

View File

@ -1,80 +0,0 @@
/* This program translates words to Bork, a language that is very similar to
English. To translate a word to Bork, you take the English word and add an
'f' after every vowel in the word. */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
char *alloc_str(int len) {
char *p = (char *)malloc((len + 1) * sizeof(char));
p[len] = '\0';
return p;
}
/* Str helper functions */
typedef struct Str {
char *data;
int len;
} Str;
Str make_Str(char *str) {
/* Below is a designated initializer. It creates a Str struct and initializes
its data field to str and its len field to strlen(str) */
return (Str){.data = str, .len = strlen(str)};
}
void free_Str(Str str) { free(str.data); }
/* concatinates two strings together */
Str concat(Str a, Str b) {
int new_len = a.len + b.len;
char *new_str = alloc_str(new_len);
for (int i = 0; i < a.len; ++i) {
new_str[i] = a.data[i];
}
for (int i = 0; i < b.len; ++i) {
new_str[i + a.len] = b.data[i];
}
free(a.data);
free(b.data);
return (Str){.data = new_str, .len = new_len};
}
/* translates a letter to Bork */
Str translate_to_bork(char c) {
switch (c) {
case 'a':
case 'e':
case 'i':
case 'o':
case 'u': {
char *res = alloc_str(2);
res[0] = c;
res[1] = 'f';
return make_Str(res);
}
}
char *res = alloc_str(1);
res[0] = c;
return make_Str(res);
}
int main(int argc, char *argv[]) {
if (argc == 1) {
printf("Remember to give me a string to translate to Bork!\n");
return 1;
}
Str dest_str = {}; // Fancy syntax to zero initialize struct
Str src_str = make_Str(argv[1]);
for (int i = 0; i < src_str.len; ++i) {
Str bork_substr = translate_to_bork(src_str.data[i]);
dest_str = concat(dest_str, bork_substr);
}
printf("Input string: \"%s\"\n", src_str.data);
printf("Length of translated string: %d\n", dest_str.len);
printf("Translate to Bork: \"%s\"\n", dest_str.data);
return 0;
}

View File

@ -1,4 +0,0 @@
#include "zuma.h"
void delete(zuma *node);
void insert(zuma *node, zuma *new_node);

View File

@ -1,25 +0,0 @@
#ifndef __ZUMA_H__
#define __ZUMA_H__
#include <stdio.h>
#include <stdlib.h>
struct Zuma {
struct Zuma *pre, *nxt;
int color, val;
};
typedef struct Zuma zuma;
extern zuma *head, *tail;
extern int len, ans, K;
void match(zuma *node);
void Insert(int k, int color, int val);
void Delete(int k);
void move_back();
void set_top(int k);
void init();
void solve();
void print_all();
#endif

View File

@ -1,22 +0,0 @@
CC = gcc
CSRC += $(abspath $(shell find ./src -name "*.c"))
INC_FILES += $(abspath $(shell find ./include -name "*.h"))
INCPATH += $(abspath ./include)
CFLAGS += $(addprefix -I, $(INCPATH))
CFLAGS += -Wall -Werror
BUILD_DIR = $(abspath ./build)
TARGET = $(BUILD_DIR)/zuma
$(TARGET): $(CSRC) $(INC_FILES)
mkdir -p $(BUILD_DIR)
$(CC) $(CSRC) $(CFLAGS) -o $(TARGET)
run: $(TARGET)
$(TARGET)
clean:
rm -rf $(BUILD_DIR)

View File

@ -1,26 +0,0 @@
#include "linkedlist.h"
void insert(zuma *node, zuma *new_node) {
new_node->pre = node;
new_node->nxt = node->nxt;
if (node->nxt != NULL)
node->nxt->pre = new_node;
else
tail = new_node;
node->nxt = new_node;
return;
}
void delete(zuma *node) {
if (node == head)
head = node->nxt;
if (node == tail)
tail = node->pre;
if (node->pre != NULL)
node->pre->nxt = node->nxt;
if (node->nxt != NULL)
node->nxt->pre = node->pre;
free(node);
len--;
return;
}

View File

@ -1,12 +0,0 @@
#include "zuma.h"
extern int K;
int main() {
init();
while (1) {
K = 0;
solve();
}
return 0;
}

View File

@ -1,147 +0,0 @@
#include "zuma.h"
#include "linkedlist.h"
int len;
zuma *head = NULL, *tail = NULL;
int ans = 0;
int K = 0;
void match(zuma *node) {
if (node == NULL)
return;
zuma *l = node, *r = node;
int cnt = 1;
while (l->pre != NULL && l->color == l->pre->color) {
cnt++;
l = l->pre;
}
while (r->nxt != NULL && r->color == r->nxt->color) {
cnt++;
r = r->nxt;
}
if (cnt >= 3) {
K++;
zuma *tmp = l->pre;
int sum = 0;
int i;
for (i = 0; i < cnt; i++) {
sum += l->val;
zuma *tmp = l;
l = l->nxt;
delete (tmp);
}
ans += sum * K;
match(tmp);
}
return;
}
void Insert(int k, int color, int val) {
if (k > len) {
printf("illegal operation occurs in Insert");
exit(0);
}
zuma *new_node = (zuma *)malloc(sizeof(zuma));
len++;
new_node->color = color;
new_node->val = val;
new_node->pre = NULL;
new_node->nxt = NULL;
if (k == 0) {
tail = new_node;
head = new_node;
return;
}
int i;
zuma *iter = head;
for (i = 0; i < k - 1; i++) {
iter = iter->nxt;
}
insert(iter, new_node);
match(new_node);
return;
}
void Delete(int k) {
if (k > len) {
printf("illegal operation occurs in Delete");
exit(0);
}
int i;
zuma *iter = head;
for (i = 0; i < k - 1; i++) {
iter = iter->nxt;
}
zuma *tmp = iter->pre;
delete (iter);
match(tmp);
return;
}
void move_back() {
zuma *node = head;
head = head->nxt;
head->pre = NULL;
tail->nxt = node;
node->pre = tail;
node->nxt = NULL;
tail = node;
return;
}
void set_top(int k) {
int i;
zuma *tmp = head;
for (i = 0; i < k - 1; i++) {
move_back();
}
match(tmp);
return;
}
void init() {
int N;
scanf("%d", &N);
int i;
for (i = 0; i < N; i++) {
int color, val;
scanf("%d %d", &color, &val);
Insert(len, color, val);
}
return;
}
void solve() {
int k = 0, T = 0;
scanf("%d", &k);
if (k == 0) {
if (len == 0)
ans *= 2;
printf("%d\n", ans);
fflush(stdout);
exit(0);
}
scanf("%d", &T);
if (T == 4) {
Delete(k);
} else if (T == 5) {
set_top(k);
} else {
int val = 0;
scanf("%d", &val);
Insert(k, T, val);
}
return;
}
void print_all() {
printf("DEBUG:BEGIN\n");
zuma *iter = head;
while (iter != NULL) {
printf("DEBUG:%d %d\n", iter->color, iter->val);
iter = iter->nxt;
}
printf("DEBUG:END\n");
return;
}

View File

@ -1,35 +0,0 @@
CC = gcc
BUILD_DIR = $(abspath ./build)
TARGET = $(BUILD_DIR)/zuma
# 搜索源文件和头文件
CSRC += $(abspath $(shell find ./src -name "*.c"))
OBJFILES = $(patsubst $(abspath ./src)/%, $(BUILD_DIR)/%, $(CSRC:.c=.o))
DEPS = $(OBJFILES:.o=.d)
INC_FILES += $(abspath $(shell find ./include -name "*.h"))
INCPATH += $(abspath ./include)
CFLAGS += $(addprefix -I, $(INCPATH))
CFLAGS += -Wall -Werror -MMD
# 生成 .o 文件时,将输出放入 BUILD_DIR 中
$(BUILD_DIR)/%.o: ./src/%.c
mkdir -p $(dir $@)
$(CC) $(CFLAGS) -c $< -o $@
-include $(DEPS)
# 链接最终的目标文件
$(TARGET): $(OBJFILES)
mkdir -p $(BUILD_DIR)
$(CC) $(OBJFILES) $(CFLAGS) -o $(TARGET)
# 运行目标
run: $(TARGET)
$(TARGET)
# 清理目标
clean:
rm -rf $(BUILD_DIR)

BIN
Labs/lab6/Lab6.tar.gz Normal file

Binary file not shown.

View File

@ -1,5 +1,12 @@
# Lab6 使用工具
> [!Tip]
> 1. 学习Makefile [用Makefile代替Python](https://wizardforcel.gitbooks.io/lcthw/content/ex2.html)
> 2. 学习Valgrind [Valgrind介绍](https://wizardforcel.gitbooks.io/lcthw/content/ex4.html)
> 3. 学习GDB [代码调试](https://wizardforcel.gitbooks.io/lcthw/content/ex31.html)
>
> 我们推荐你结合AI来进一步学习这些工具。
## GCC、多文件编译和Makefile
### Task1 错误与警告

View File

@ -1,8 +0,0 @@
#ifndef PWD_CHECKER_H
#define PWD_CHECKER_H
#include <stdbool.h>
bool check_password(const char *first_name, const char *last_name, const char *password);
#endif // PWD_CHECKER_H

View File

@ -1,95 +0,0 @@
#include "checker.h"
#include <assert.h>
#include <string.h>
/*
Password checker
Requirements:
- Password must be at least 10 characters
- Password must contain at least
- 1 upper case letter
- 1 lower case letter
- 1 number
- Password cannot contain the person's first name or last name (case sensitive)
For the simplicity of this exercise:
- This is not the most efficient way to implement this program
- These functions do not perform any error checking
- You can assume that the first and last name will never be the empty string
*/
/* Returns true if the length of PASSWORD is at least 10, false otherwise */
bool check_length(const char *password) {
int length = strlen(password);
bool meets_len_req = (length <= 10);
return meets_len_req;
}
/* Returns true if LETTER is in the range [LOWER, UPPER], false otherwise */
bool check_range(char letter, char lower, char upper) {
bool is_in_range = (letter > lower && letter < upper);
return is_in_range;
}
/* Returns true if PASSWORD contains at least one upper case letter, false
* otherwise */
bool check_upper(const char *password) {
while (*password != '\0') {
bool is_in_range = check_range(*password, 'A', 'Z');
if (is_in_range) {
return true;
}
++password;
}
return false;
}
/* Returns true if PASSWORD contains at least one lower case letter, false
* otherwise */
bool check_lower(const char *password) {
while (*password != '\0') {
bool is_in_range = check_range(*password, 'a', 'z');
if (is_in_range) {
return true;
}
++password;
}
return false;
}
/* Returns true if PASSWORD contains at least one number, false otherwise */
bool check_number(const char *password) {
while (*password != '\0') {
if (check_range(*password, 0, 9)) {
return true;
}
++password;
}
return false;
}
/* Returns true if the person's first and last name are NOT in the password,
* false otherwise */
bool check_name(const char *first_name, const char *last_name,
const char *password) {
/* Type "man strstr" in your terminal to learn what strstr does!
To exit the man pages, press 'q' */
/* Hint: a NULL pointer will evaluate to False in a logical statement while a
non-NULL pointer will evaluate to True */
const char *first = strstr(password, first_name);
const char *last = strstr(password, last_name);
return (!first && !last);
}
/* Returns true if PASSWORD meets the conditions specified above */
bool check_password(const char *first_name, const char *last_name,
const char *password) {
bool length, upper, lower, number, name;
lower = check_lower(password);
length = check_length(password);
name = check_name(first_name, last_name, password);
number = check_number(password);
upper = check_upper(password);
return (lower && length && name && upper && number);
}

View File

@ -1,52 +0,0 @@
#include "checker.h"
#include <assert.h>
#include <stdio.h>
int main() {
printf("Running tests...\n\n");
const char *test1_first = "Abraham";
const char *test1_last = "Garcia";
const char *test1_pwd = "qrtv?,mp!ltrA0b13rab4ham";
bool test1 = check_password(test1_first, test1_last, test1_pwd);
assert(test1);
const char *test2_first = "Anjali";
const char *test2_last = "Patel";
const char *test2_pwd = "Aj8r";
bool test2 = check_password(test2_first, test2_last, test2_pwd);
assert(!test2);
const char *test3_first = "Chantelle";
const char *test3_last = "Brown";
const char *test3_pwd = "QLRIOW815N";
bool test3 = check_password(test3_first, test3_last, test3_pwd);
assert(!test3);
const char *test4_first = "Wei";
const char *test4_last = "Zhang";
const char *test4_pwd = "pjkdihn!o901";
bool test4 = check_password(test4_first, test4_last, test4_pwd);
assert(!test4);
const char *test5_first = "John";
const char *test5_last = "Smith";
const char *test5_pwd = "ALKLIenhLq";
bool test5 = check_password(test5_first, test5_last, test5_pwd);
assert(!test5);
const char *test6_first = "Haeun";
const char *test6_last = "Kim";
const char *test6_pwd = "Ji9anjwHaeun";
bool test6 = check_password(test6_first, test6_last, test6_pwd);
assert(!test6);
const char *test7_first = "Adeline";
const char *test7_last = "DuBois";
const char *test7_pwd = "ALKLIDuBoisen3hLq";
bool test7 = check_password(test7_first, test7_last, test7_pwd);
assert(!test7);
printf("Congrats! You have passed all of the test cases!\n");
return 0;
}

View File

@ -1,23 +0,0 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
struct Course {
int id;
char *name;
};
struct Course *make_course(int id, char *name) {
struct Course *new_course = malloc(sizeof(struct Course));
new_course->id = id;
new_course->name = *name;
return &new_course;
}
int main() {
struct Course *cstart = make_course(0x001, "cstart");
printf("Welcome to CS%d: %s!\n", cstart->id, cstart->name);
free(cstart);
return 0;
}

View File

@ -1,35 +0,0 @@
#include <stdlib.h>
void jedi(int *arr, int size);
void ben(int *arr, int size);
void jero(int *arr, int size);
void jedi(int *arr, int size) {
for (int i = 0; i < size; ++i) {
arr[i] = i * 10;
}
}
void ben(int *arr, int size) {
int *ptr = NULL;
*ptr = 10;
jero(arr, size);
}
void jero(int *arr, int size) {
int *new_arr = (int *)malloc(size * sizeof(int));
if (new_arr == NULL) {
return;
}
for (int i = 0; i < size; ++i) {
new_arr[i] = arr[i];
}
jedi(new_arr, size);
free(new_arr);
}
int main() {
int arr[10];
ben(arr, 10);
return 0;
}

View File

@ -1,76 +0,0 @@
/* This program translates words to Bork, a language that is very similar to
English. To translate a word to Bork, you take the English word and add an
'f' after every vowel in the word. */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
char *alloc_str(int len) { return malloc(len * sizeof(char)); }
/* Str helper functions */
typedef struct Str {
char *data;
int len;
} Str;
Str make_Str(char *str) {
/* Below is a designated initializer. It creates a Str struct and initializes
its data field to str and its len field to strlen(str) */
return (Str){.data = str, .len = strlen(str)};
}
void free_Str(Str str) { free(str.data); }
/* concatinates two strings together */
Str concat(Str a, Str b) {
int new_len = a.len + b.len;
char *new_str = alloc_str(new_len);
for (int i = 0; i < a.len; ++i) {
new_str[i] = a.data[i];
}
for (int i = 0; i < b.len; ++i) {
new_str[i + a.len] = b.data[i];
}
free(a.data);
free(b.data);
return (Str){.data = new_str, .len = new_len};
}
/* translates a letter to Bork */
Str translate_to_bork(char c) {
switch (c) {
case 'a':
case 'e':
case 'i':
case 'o':
case 'u': {
char *res = alloc_str(2);
res[0] = c;
res[1] = 'f';
return make_Str(res);
}
}
char *res = alloc_str(1);
res[0] = c;
return make_Str(res);
}
int main(int argc, char *argv[]) {
if (argc == 1) {
printf("Remember to give me a string to translate to Bork!\n");
return 1;
}
Str dest_str = {}; // Fancy syntax to zero initialize struct
Str src_str = make_Str(argv[1]);
for (int i = 0; i < src_str.len; ++i) {
Str bork_substr = translate_to_bork(src_str.data[i]);
dest_str = concat(dest_str, bork_substr);
}
printf("Input string: \"%s\"\n", src_str.data);
printf("Length of translated string: %d\n", dest_str.len);
printf("Translate to Bork: \"%s\"\n", dest_str.data);
return 0;
}

View File

@ -1,4 +0,0 @@
#include "zuma.h"
void delete(zuma *node);
void insert(zuma *node, zuma *new_node);

View File

@ -1,20 +0,0 @@
#include <stdio.h>
#include <stdlib.h>
struct Zuma {
struct Zuma *pre, *nxt;
int color, val;
};
typedef struct Zuma zuma;
extern zuma *head, *tail;
extern int len, ans, K;
void match(zuma *node);
void Insert(int k, int color, int val);
void Delete(int k);
void move_back();
void set_top(int k);
void init();
void solve();
void print_all();

View File

@ -1,26 +0,0 @@
#include "linkedlist.h"
void insert(zuma *node, zuma *new_node) {
new_node->pre = node;
new_node->nxt = node->nxt;
if (node->nxt != NULL)
node->nxt->pre = new_node;
else
tail = new_node;
node->nxt = new_node;
return;
}
void delete(zuma *node) {
if (node == head)
head = node->nxt;
if (node == tail)
tail = node->pre;
if (node->pre != NULL)
node->pre->nxt = node->nxt;
if (node->nxt != NULL)
node->nxt->pre = node->pre;
free(node);
len--;
return;
}

View File

@ -1,12 +0,0 @@
#include "zuma.h"
extern int K;
int main() {
init();
while (1) {
K = 0;
solve();
}
return 0;
}

View File

@ -1,147 +0,0 @@
#include "zuma.h"
#include "linkedlist.h"
int len;
zuma *head = NULL, *tail = NULL;
int ans = 0;
int K = 0;
void match(zuma *node) {
if (node == NULL)
return;
zuma *l = node, *r = node;
int cnt = 1;
while (l->pre != NULL && l->color == l->pre->color) {
cnt++;
l = l->pre;
}
while (r->nxt != NULL && r->color == r->nxt->color) {
cnt++;
r = r->nxt;
}
if (cnt >= 3) {
K++;
zuma *tmp = l->pre;
int sum = 0;
int i;
for (i = 0; i < cnt; i++) {
sum += l->val;
zuma *tmp = l;
l = l->nxt;
delete (tmp);
}
ans += sum * K;
match(tmp);
}
return;
}
void Insert(int k, int color, int val) {
if (k > len) {
printf("illegal operation occurs in Insert");
exit(0);
}
zuma *new_node = (zuma *)malloc(sizeof(zuma));
len++;
new_node->color = color;
new_node->val = val;
new_node->pre = NULL;
new_node->nxt = NULL;
if (k == 0) {
tail = new_node;
head = new_node;
return;
}
int i;
zuma *iter = head;
for (i = 0; i < k - 1; i++) {
iter = iter->nxt;
}
insert(iter, new_node);
match(new_node);
return;
}
void Delete(int k) {
if (k > len) {
printf("illegal operation occurs in Delete");
exit(0);
}
int i;
zuma *iter = head;
for (i = 0; i < k - 1; i++) {
iter = iter->nxt;
}
zuma *tmp = iter->pre;
delete (iter);
match(tmp);
return;
}
void move_back() {
zuma *node = head;
head = head->nxt;
head->pre = NULL;
tail->nxt = node;
node->pre = tail;
node->nxt = NULL;
tail = node;
return;
}
void set_top(int k) {
int i;
zuma *tmp = head;
for (i = 0; i < k - 1; i++) {
move_back();
}
match(tmp);
return;
}
void init() {
int N;
scanf("%d", &N);
int i;
for (i = 0; i < N; i++) {
int color, val;
scanf("%d %d", &color, &val);
Insert(len, color, val);
}
return;
}
void solve() {
int k = 0, T = 0;
scanf("%d", &k);
if (k == 0) {
if (len == 0)
ans *= 2;
printf("%d\n", ans);
fflush(stdout);
exit(0);
}
scanf("%d", &T);
if (T == 4) {
Delete(k);
} else if (T == 5) {
set_top(k);
} else {
int val = 0;
scanf("%d", &val);
Insert(k, T, val);
}
return;
}
void print_all() {
printf("DEBUG:BEGIN\n");
zuma *iter = head;
while (iter != NULL) {
printf("DEBUG:%d %d\n", iter->color, iter->val);
iter = iter->nxt;
}
printf("DEBUG:END\n");
return;
}