feat:增加了对makefile valgrind gdb说明的链接
This commit is contained in:
parent
3ecba7ea5b
commit
3f1183d4ff
|
@ -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
|
|
@ -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);
|
||||
}
|
|
@ -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;
|
||||
}
|
|
@ -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 */
|
||||
```
|
|
@ -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;
|
||||
}
|
|
@ -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;
|
||||
}
|
|
@ -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;
|
||||
}
|
|
@ -1,4 +0,0 @@
|
|||
#include "zuma.h"
|
||||
|
||||
void delete(zuma *node);
|
||||
void insert(zuma *node, zuma *new_node);
|
|
@ -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
|
|
@ -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)
|
|
@ -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;
|
||||
}
|
|
@ -1,12 +0,0 @@
|
|||
#include "zuma.h"
|
||||
|
||||
extern int K;
|
||||
|
||||
int main() {
|
||||
init();
|
||||
while (1) {
|
||||
K = 0;
|
||||
solve();
|
||||
}
|
||||
return 0;
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
|
|
@ -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)
|
Binary file not shown.
|
@ -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 错误与警告
|
||||
|
|
|
@ -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
|
|
@ -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);
|
||||
}
|
|
@ -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;
|
||||
}
|
|
@ -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;
|
||||
}
|
|
@ -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;
|
||||
}
|
|
@ -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;
|
||||
}
|
|
@ -1,4 +0,0 @@
|
|||
#include "zuma.h"
|
||||
|
||||
void delete(zuma *node);
|
||||
void insert(zuma *node, zuma *new_node);
|
|
@ -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();
|
|
@ -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;
|
||||
}
|
|
@ -1,12 +0,0 @@
|
|||
#include "zuma.h"
|
||||
|
||||
extern int K;
|
||||
|
||||
int main() {
|
||||
init();
|
||||
while (1) {
|
||||
K = 0;
|
||||
solve();
|
||||
}
|
||||
return 0;
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
|
Loading…
Reference in New Issue