提交以前完成的内容,不包括习题33

This commit is contained in:
Wang Bo Yang 2025-04-19 17:24:58 +08:00
parent d6bbef323b
commit c96f3a6d48
141 changed files with 6453 additions and 0 deletions

View File

@ -0,0 +1,235 @@
{
"cells": [
{
"cell_type": "code",
"execution_count": 1,
"id": "ef4fb02d-b70b-40f3-be0f-434711ed87b4",
"metadata": {},
"outputs": [],
"source": [
"stack = [3, 4, 5]"
]
},
{
"cell_type": "code",
"execution_count": 2,
"id": "4fe740fe-162e-4763-8592-be87b412d26c",
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"[3, 4, 5, 6, 7]"
]
},
"execution_count": 2,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"stack.append(6)\n",
"stack.append(7)\n",
"stack"
]
},
{
"cell_type": "code",
"execution_count": 3,
"id": "411d9f9d-ccaf-415c-b858-0601deb058d5",
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"7"
]
},
"execution_count": 3,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"stack.pop()"
]
},
{
"cell_type": "code",
"execution_count": 4,
"id": "caf7d327-1f51-4e64-bb2e-5ae73e03a14b",
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"[3, 4, 5, 6]"
]
},
"execution_count": 4,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"stack"
]
},
{
"cell_type": "code",
"execution_count": 5,
"id": "8bad3ba9-6a5e-4c4e-a7f3-09349cb7ab3e",
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"6"
]
},
"execution_count": 5,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"stack.pop()"
]
},
{
"cell_type": "code",
"execution_count": 6,
"id": "797f814d-b722-4bc2-8321-2055d3b35ba5",
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"5"
]
},
"execution_count": 6,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"stack.pop()"
]
},
{
"cell_type": "code",
"execution_count": 7,
"id": "530dcc1e-032d-4eb8-9081-a49aa7c502ee",
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"[3, 4]"
]
},
"execution_count": 7,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"stack"
]
},
{
"cell_type": "code",
"execution_count": 8,
"id": "8596fc1a-c27a-41d7-9ed2-06d1065fe028",
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"4"
]
},
"execution_count": 8,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"stack.pop()"
]
},
{
"cell_type": "code",
"execution_count": 9,
"id": "086f3233-5106-477a-8419-0889afbb96fb",
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"3"
]
},
"execution_count": 9,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"stack.pop()"
]
},
{
"cell_type": "code",
"execution_count": 10,
"id": "2c7a7eb0-4831-48bd-8479-f89b1eafae3d",
"metadata": {},
"outputs": [
{
"ename": "IndexError",
"evalue": "pop from empty list",
"output_type": "error",
"traceback": [
"\u001b[0;31m---------------------------------------------------------------------------\u001b[0m",
"\u001b[0;31mIndexError\u001b[0m Traceback (most recent call last)",
"Cell \u001b[0;32mIn[10], line 1\u001b[0m\n\u001b[0;32m----> 1\u001b[0m \u001b[43mstack\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mpop\u001b[49m\u001b[43m(\u001b[49m\u001b[43m)\u001b[49m\n",
"\u001b[0;31mIndexError\u001b[0m: pop from empty list"
]
}
],
"source": [
"stack.pop()"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "a63b26d3-d21d-4258-ab34-26870d562318",
"metadata": {},
"outputs": [],
"source": []
}
],
"metadata": {
"kernelspec": {
"display_name": "Python 3 (ipykernel)",
"language": "python",
"name": "python3"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.9.1"
}
},
"nbformat": 4,
"nbformat_minor": 5
}

6
ex17/Makefile Normal file
View File

@ -0,0 +1,6 @@
CFLAGS=-Wall -g
all: ex17 ex17_test ex17v2 stack
clean:
rm -f ex17 ex17_test ex17v2 stack

235
ex17/PythonStack.ipynb Normal file
View File

@ -0,0 +1,235 @@
{
"cells": [
{
"cell_type": "code",
"execution_count": 1,
"id": "ef4fb02d-b70b-40f3-be0f-434711ed87b4",
"metadata": {},
"outputs": [],
"source": [
"stack = [3, 4, 5]"
]
},
{
"cell_type": "code",
"execution_count": 2,
"id": "4fe740fe-162e-4763-8592-be87b412d26c",
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"[3, 4, 5, 6, 7]"
]
},
"execution_count": 2,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"stack.append(6)\n",
"stack.append(7)\n",
"stack"
]
},
{
"cell_type": "code",
"execution_count": 3,
"id": "411d9f9d-ccaf-415c-b858-0601deb058d5",
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"7"
]
},
"execution_count": 3,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"stack.pop()"
]
},
{
"cell_type": "code",
"execution_count": 4,
"id": "caf7d327-1f51-4e64-bb2e-5ae73e03a14b",
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"[3, 4, 5, 6]"
]
},
"execution_count": 4,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"stack"
]
},
{
"cell_type": "code",
"execution_count": 5,
"id": "8bad3ba9-6a5e-4c4e-a7f3-09349cb7ab3e",
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"6"
]
},
"execution_count": 5,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"stack.pop()"
]
},
{
"cell_type": "code",
"execution_count": 6,
"id": "797f814d-b722-4bc2-8321-2055d3b35ba5",
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"5"
]
},
"execution_count": 6,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"stack.pop()"
]
},
{
"cell_type": "code",
"execution_count": 7,
"id": "530dcc1e-032d-4eb8-9081-a49aa7c502ee",
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"[3, 4]"
]
},
"execution_count": 7,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"stack"
]
},
{
"cell_type": "code",
"execution_count": 8,
"id": "8596fc1a-c27a-41d7-9ed2-06d1065fe028",
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"4"
]
},
"execution_count": 8,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"stack.pop()"
]
},
{
"cell_type": "code",
"execution_count": 9,
"id": "086f3233-5106-477a-8419-0889afbb96fb",
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"3"
]
},
"execution_count": 9,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"stack.pop()"
]
},
{
"cell_type": "code",
"execution_count": 10,
"id": "2c7a7eb0-4831-48bd-8479-f89b1eafae3d",
"metadata": {},
"outputs": [
{
"ename": "IndexError",
"evalue": "pop from empty list",
"output_type": "error",
"traceback": [
"\u001b[0;31m---------------------------------------------------------------------------\u001b[0m",
"\u001b[0;31mIndexError\u001b[0m Traceback (most recent call last)",
"Cell \u001b[0;32mIn[10], line 1\u001b[0m\n\u001b[0;32m----> 1\u001b[0m \u001b[43mstack\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mpop\u001b[49m\u001b[43m(\u001b[49m\u001b[43m)\u001b[49m\n",
"\u001b[0;31mIndexError\u001b[0m: pop from empty list"
]
}
],
"source": [
"stack.pop()"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "a63b26d3-d21d-4258-ab34-26870d562318",
"metadata": {},
"outputs": [],
"source": []
}
],
"metadata": {
"kernelspec": {
"display_name": "Python 3 (ipykernel)",
"language": "python",
"name": "python3"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.9.1"
}
},
"nbformat": 4,
"nbformat_minor": 5
}

BIN
ex17/db.bat Executable file

Binary file not shown.

264
ex17/ex17.c Normal file
View File

@ -0,0 +1,264 @@
#include <stdio.h>
#include <assert.h>
#include <stdlib.h>
#include <errno.h>
#include <string.h>
#define MAX_DATA 512
#define MAX_ROWS 100
struct Address {
int id;
int set;
char name[MAX_DATA];
char email[MAX_DATA];
};
struct Database {
struct Address rows[MAX_ROWS];
};
struct Connection {
FILE *file;
struct Database *db;
};
void die(const char *message)
{
if (errno)
{
perror(message);
}
else
{
printf("ERROR: %s\n", message);
}
exit(1);
}
void Address_print(struct Address *addr)
{
printf("%d %s %s\n", addr->id, addr->name, addr->email);
}
void Database_load(struct Connection *conn)
{
int rc = fread(conn->db, sizeof(struct Database), 1, conn->file);
if (rc != 1 )
{
die("Failed to load database.");
}
}
struct Connection *Database_open(const char *filename, char mode)
{
struct Connection *conn = malloc(sizeof(struct Connection));
if (!conn)
{
die("Memory error");
}
conn->db = malloc(sizeof(struct Database));
if (!conn->db)
{
die("Memory error");
}
if (mode == 'c')
{
conn->file = fopen(filename, "w");
}
else
{
conn->file = fopen(filename, "r+");
if (conn->file)
{
Database_load(conn);
}
}
if (!conn->file)
{
die("Failed to open the file");
}
return conn;
};
void Database_close(struct Connection *conn)
{
if (conn)
{
if (conn->file)
{
fclose(conn->file);
}
if (conn->db)
{
free(conn->db);
}
free(conn);
}
}
void Database_write(struct Connection *conn)
{
rewind(conn->file);
int rc = fwrite(conn->db, sizeof(struct Database), 1, conn->file);
if (rc != 1)
{
die("Failed to write database.");
}
rc = fflush(conn->file);
if (rc == -1)
{
die("Cannot flush database.");
}
}
void Database_create(struct Connection *conn)
{
int i = 0;
for (i = 0; i < MAX_ROWS; i++)
{
// make a prototype to initialize it
struct Address addr = {.id = i, .set = 0};
// then just assign it
conn->db->rows[i] = addr;
}
}
void Database_set(struct Connection *conn, int id, const char *name, const char *email)
{
struct Address *addr = &conn->db->rows[id];
if (addr->set)
{
die("Already set, delete it first");
}
addr->set = 1;
// WARNING: bug, read the "How To Break It" and fix this
char *res = strncpy(addr->name, name, MAX_DATA);
// demonstrate the strncpy bug
if (!res)
{
die("Name copy failed");
}
res = strncpy(addr->email, email, MAX_DATA);
if (!res)
{
die("Email copy failed");
}
}
void Database_get(struct Connection *conn, int id)
{
struct Address *addr = &conn->db->rows[id];
if (addr->set)
{
Address_print(addr);
}
else
{
die("ID is not set");
}
}
void Database_delete(struct Connection *conn, int id)
{
struct Address addr = {.id = id, .set = 0};
conn->db->rows[id] = addr;
}
void Database_list(struct Connection *conn)
{
int i = 0;
struct Database *db = conn->db;
for (i = 0; i < MAX_ROWS; i++)
{
struct Address *cur = &db->rows[i];
if (cur->set)
{
Address_print(cur);
}
}
}
int main(int argc, char *argv[])
{
if (argc < 3)
{
die("USAGE: ex17 <dbfile><action> [action params]");
}
char *filename = argv[1];
char action = argv[2][0];
struct Connection *conn = Database_open(filename, action);
int id = 0;
if (argc > 3)
{
id = atoi(argv[3]);
}
if (id >= MAX_ROWS)
{
die("There's not that many records.");
}
switch(action)
{
case 'c':
Database_create(conn);
Database_write(conn);
break;
case 'g':
if (argc != 4)
{
die("Need an id to get");
}
Database_get(conn, id);
break;
case 's':
if (argc != 6)
{
die("Need id, name, email to set");
}
Database_set(conn, id, argv[4], argv[5]);
Database_write(conn);
break;
case 'd':
if (argc != 4)
{
die("Need id to delete");
}
Database_delete(conn, id);
Database_write(conn);
break;
case 'l':
Database_list(conn);
break;
default:
die("Invalid action: c=create, g=get, s=set, l=list");
}
Database_close(conn);
return 0;
}

334
ex17/ex17_test.c Normal file
View File

@ -0,0 +1,334 @@
#include <stdio.h>
#include <assert.h>
#include <stdlib.h>
#include <errno.h>
#include <string.h>
#define MAX_DATA 512
#define MAX_ROWS 100
struct Address {
int id;
int set;
char name[MAX_DATA];
char email[MAX_DATA];
int height;
};
struct Database {
struct Address rows[MAX_ROWS];
};
struct Connection {
FILE *file;
struct Database *db;
};
// void die(const char *message)
void die(const char *message, struct Connection *conn)
{
if (errno)
{
perror(message);
}
else
{
printf("ERROR: %s\n", message);
}
if (conn)
{
if (conn->file)
{
fclose(conn->file);
}
if (conn->db)
{
free(conn->db);
}
free(conn);
}
exit(1);
}
void Address_print(struct Address *addr)
{
// printf("%d %s %s\n", addr->id, addr->name, addr->email);
printf("%d %s %s %d\n", addr->id, addr->name, addr->email, addr->height);
}
void Database_load(struct Connection *conn)
{
int rc = fread(conn->db, sizeof(struct Database), 1, conn->file);
if (rc != 1 )
{
die("Failed to load database.", conn);
}
}
struct Connection *Database_open(const char *filename, char mode)
{
struct Connection *conn = malloc(sizeof(struct Connection));
if (!conn)
{
die("Memory error", conn);
}
conn->db = malloc(sizeof(struct Database));
if (!conn->db)
{
die("Memory error", conn);
}
if (mode == 'c')
{
conn->file = fopen(filename, "w");
}
else
{
conn->file = fopen(filename, "r+");
if (conn->file)
{
Database_load(conn);
}
}
if (!conn->file)
{
die("Failed to open the file", conn);
}
return conn;
};
void Database_close(struct Connection *conn)
{
if (conn)
{
if (conn->file)
{
fclose(conn->file);
}
if (conn->db)
{
free(conn->db);
}
free(conn);
}
}
void Database_write(struct Connection *conn)
{
rewind(conn->file);
int rc = fwrite(conn->db, sizeof(struct Database), 1, conn->file);
if (rc != 1)
{
die("Failed to write database.", conn);
}
rc = fflush(conn->file);
if (rc == -1)
{
die("Cannot flush database.", conn);
}
}
void Database_create(struct Connection *conn)
{
int i = 0;
for (i = 0; i < MAX_ROWS; i++)
{
// make a prototype to initialize it
struct Address addr = {.id = i, .set = 0};
// then just assign it
conn->db->rows[i] = addr;
}
}
// void Database_set(struct Connection *conn, int id, const char *name, const char *email)
void Database_set(struct Connection *conn, int id, const char *name,
const char *email, int height)
{
struct Address *addr = &conn->db->rows[id];
if (addr->set)
{
die("Already set, delete it first", conn);
}
addr->set = 1;
addr->height = height;
// WARNING: bug, read the "How To Break It" and fix this
char *res = strncpy(addr->name, name, MAX_DATA);
addr->name[MAX_DATA - 1] = '\0';
// demonstrate the strncpy bug
if (!res)
{
die("Name copy failed", conn);
}
res = strncpy(addr->email, email, MAX_DATA);
addr->email[MAX_DATA - 1] = '\0';
if (!res)
{
die("Email copy failed", conn);
}
}
void Database_get(struct Connection *conn, int id)
{
struct Address *addr = &conn->db->rows[id];
if (addr->set)
{
Address_print(addr);
}
else
{
die("ID is not set", conn);
}
}
void Database_delete(struct Connection *conn, int id)
{
struct Address addr = {.id = id, .set = 0};
conn->db->rows[id] = addr;
}
void Database_list(struct Connection *conn)
{
int i = 0;
struct Database *db = conn->db;
for (i = 0; i < MAX_ROWS; i++)
{
struct Address *cur = &db->rows[i];
if (cur->set)
{
Address_print(cur);
}
}
}
void Database_find(struct Connection *conn, const char *name)
{
int i = 0;
struct Database *db = conn->db;
for (i = 0; i < MAX_ROWS; i++)
{
struct Address *cur = &db->rows[i];
// printf("%s v.s. %s\n", cur->name, name);
if ((cur->set)&&(!strcmp(cur->name, name)))
{
printf("%d\n", i);
}
}
}
int main(int argc, char *argv[])
{
struct Connection *conn = NULL;
if (argc < 3)
{
die("USAGE: ex17 <dbfile><action> [action params]", conn);
}
char *filename = argv[1];
char action = argv[2][0];
// struct Connection *conn = Database_open(filename, action);
conn = Database_open(filename, action);
int id = 0;
char name[MAX_DATA];
// int i = 0;
int height = 0;
printf("size: %ld\n", sizeof(struct Database));
if (argc > 3)
{
id = atoi(argv[3]);
height = atoi(argv[6]);
}
if (id >= MAX_ROWS)
{
die("There's not that many records.", conn);
}
switch(action)
{
case 'c':
Database_create(conn);
Database_write(conn);
break;
case 'g':
if (argc != 4)
{
die("Need an id to get", conn);
}
Database_get(conn, id);
break;
case 'f':
if (argc != 4)
{
die("Nedd a name to find", conn);
}
// WARNING: no boundary check, the length of argv[3] may longer than MAX_DATA
int i = 0;
for (i = 0; argv[3][i] != '\0'; ++i)
{
name[i] = argv[3][i];
}
name[i] = '\0';
Database_find(conn, name);
break;
case 's':
// if (argc != 6)
if (argc != 7)
{
// die("Need id, name, email to set", conn);
die("Need id, name, email, height to set", conn);
}
// Database_set(conn, id, argv[4], argv[5]);
Database_set(conn, id, argv[4], argv[5], height);
Database_write(conn);
break;
case 'd':
if (argc != 4)
{
die("Need id to delete", conn);
}
Database_delete(conn, id);
Database_write(conn);
break;
case 'l':
Database_list(conn);
break;
default:
die("Invalid action: c=create, g=get, s=set, l=list", conn);
}
Database_close(conn);
return 0;
}

379
ex17/ex17v2.c Normal file
View File

@ -0,0 +1,379 @@
#include <stdio.h>
#include <assert.h>
#include <stdlib.h>
#include <errno.h>
#include <string.h>
#define MAX_DATA 512
#define MAX_ROWS 100
struct Connection *conn = NULL;
struct Address {
int id;
int set;
char name[MAX_DATA];
char email[MAX_DATA];
int height;
};
struct Database {
struct Address rows[MAX_ROWS];
};
struct Connection {
FILE *file;
struct Database *db;
};
// void die(const char *message)
// void die(const char *message, struct Connection *conn)
void die(const char *message)
{
if (errno)
{
perror(message);
}
else
{
printf("ERROR: %s\n", message);
}
if (conn)
{
if (conn->file)
{
fclose(conn->file);
}
if (conn->db)
{
free(conn->db);
}
free(conn);
}
exit(1);
}
void Address_print(struct Address *addr)
{
// printf("%d %s %s\n", addr->id, addr->name, addr->email);
printf("%d %s %s %d\n", addr->id, addr->name, addr->email, addr->height);
}
// void Database_load(struct Connection *conn)
void Database_load(struct Connection *thisConn)
{
// printf("hello123%ld", sizeof(struct Database));
int rc = fread(thisConn->db, sizeof(struct Database), 1, thisConn->file);
if (rc != 1 )
{
// die("Failed to load database.", conn);
die("Failed to load database.");
}
}
struct Connection *Database_open(const char *filename, char mode)
{
struct Connection *conn = malloc(sizeof(struct Connection));
if (!conn)
{
// die("Memory error", conn);
die("Memory error");
}
conn->db = malloc(sizeof(struct Database));
if (!conn->db)
{
// die("Memory error", conn);
die("Memory error");
}
if (mode == 'c')
{
conn->file = fopen(filename, "w");
}
else
{
conn->file = fopen(filename, "r+");
if (conn->file)
{
Database_load(conn);
}
}
if (!conn->file)
{
// die("Failed to open the file", conn);
die("Failed to open the file");
}
return conn;
};
// void Database_close(struct Connection *conn)
void Database_close()
{
if (conn)
{
if (conn->file)
{
fclose(conn->file);
}
if (conn->db)
{
free(conn->db);
}
free(conn);
}
}
// void Database_write(struct Connection *conn)
void Database_write()
{
rewind(conn->file);
int rc = fwrite(conn->db, sizeof(struct Database), 1, conn->file);
if (rc != 1)
{
// die("Failed to write database.", conn);
die("Failed to write database");
}
rc = fflush(conn->file);
if (rc == -1)
{
// die("Cannot flush database.", conn);
die("Cannot flush database.");
}
}
// void Database_create(struct Connection *conn)
void Database_create()
{
int i = 0;
for (i = 0; i < MAX_ROWS; i++)
{
// make a prototype to initialize it
struct Address addr = {.id = i, .set = 0};
// then just assign it
conn->db->rows[i] = addr;
}
}
// void Database_set(struct Connection *conn, int id, const char *name, const char *email)
// void Database_set(struct Connection *conn, int id, const char *name,
// const char *email, int height)
void Database_set(int id, const char *name, const char *email, int height)
{
printf("hello");
struct Address *addr = &conn->db->rows[id];
if (addr->set)
{
// die("Already set, delete it first", conn);
die("Already set, delete it first");
}
addr->set = 1;
addr->height = height;
// WARNING: bug, read the "How To Break It" and fix this
char *res = strncpy(addr->name, name, MAX_DATA);
addr->name[MAX_DATA - 1] = '\0';
// demonstrate the strncpy bug
if (!res)
{
// die("Name copy failed", conn);
die("Name copy failed");
}
res = strncpy(addr->email, email, MAX_DATA);
addr->email[MAX_DATA - 1] = '\0';
if (!res)
{
// die("Email copy failed", conn);
die("Eamil copy failed");
}
}
// void Database_get(struct Connection *conn, int id)
void Database_get(int id)
{
struct Address *addr = &conn->db->rows[id];
if (addr->set)
{
Address_print(addr);
}
else
{
// die("ID is not set", conn);
die("ID is not set");
}
}
// void Database_delete(struct Connection *conn, int id)
void Database_delete(int id)
{
struct Address addr = {.id = id, .set = 0};
conn->db->rows[id] = addr;
}
// void Database_list(struct Connection *conn)
void Database_list()
{
int i = 0;
struct Database *db = conn->db;
for (i = 0; i < MAX_ROWS; i++)
{
struct Address *cur = &db->rows[i];
if (cur->set)
{
Address_print(cur);
}
}
}
// void Database_find(struct Connection *conn, const char *name)
void Database_find(const char *name)
{
int i = 0;
struct Database *db = conn->db;
for (i = 0; i < MAX_ROWS; i++)
{
struct Address *cur = &db->rows[i];
// printf("%s v.s. %s\n", cur->name, name);
if ((cur->set)&&(!strcmp(cur->name, name)))
{
printf("%d\n", i);
}
}
}
int main(int argc, char *argv[])
{
// struct Connection *conn = NULL;
if (argc < 3)
{
// die("USAGE: ex17 <dbfile><action> [action params]", conn);
die("USAGE: ex17 <dbfile><action> [action params]");
}
char *filename = argv[1];
char action = argv[2][0];
// struct Connection *conn = Database_open(filename, action);
conn = Database_open(filename, action);
int id = 0;
char name[MAX_DATA];
// int i = 0;
int height = 0;
printf("size: %ld\n", sizeof(struct Database));
if (argc > 3)
{
id = atoi(argv[3]);
height = atoi(argv[6]);
}
if (id >= MAX_ROWS)
{
// die("There's not that many records.", conn);
die("There's not that many records.");
}
switch(action)
{
case 'c':
// Database_create(conn);
Database_create();
// Database_write(conn);
Database_write();
break;
case 'g':
if (argc != 4)
{
// die("Need an id to get", conn);
die("Need an id to get");
}
// Database_get(conn, id);
Database_get(id);
break;
case 'f':
if (argc != 4)
{
// die("Nedd a name to find", conn);
die("Need a name to find");
}
// WARNING: no boundary check, the length of argv[3] may longer than MAX_DATA
int i = 0;
for (i = 0; argv[3][i] != '\0'; ++i)
{
name[i] = argv[3][i];
}
name[i] = '\0';
// Database_find(conn, name);
Database_find(name);
break;
case 's':
// if (argc != 6)
if (argc != 7)
{
// die("Need id, name, email to set", conn);
// die("Need id, name, email, height to set", conn);
die("Need id, name, email, height to set");
}
printf("hello");
// Database_set(conn, id, argv[4], argv[5]);
// Database_set(conn, id, argv[4], argv[5], height);
Database_set(id, argv[4], argv[5], height);
// Database_write(conn);
Database_write();
break;
case 'd':
if (argc != 4)
{
// die("Need id to delete", conn);
die("Need id to delete");
}
// Database_delete(conn, id);
Database_delete(id);
// Database_write(conn);
Database_write();
break;
case 'l':
// Database_list(conn);
Database_list();
break;
default:
// die("Invalid action: c=create, g=get, s=set, l=list", conn);
die("Invalid action: c=create, g=get, s=set, l=list");
}
// Database_close(conn);
Database_close();
return 0;
}

BIN
ex17/stack Normal file

Binary file not shown.

95
ex17/stack.c Normal file
View File

@ -0,0 +1,95 @@
#include <stdio.h>
#include <stdlib.h>
#define MAX_STACK_SIZE 4
int push(int top, int stack_array[]);
int pop(int top, int stack_array[]);
int show(int top, int stack_array[]);
int main(void)
{
int choice = 0;
int top = -1;
int stack_array[MAX_STACK_SIZE] = {0};
while (choice != 4)
{
printf("\nPerform operations on the stack:");
printf("\n1. Push the element\n2. Pop the element\n3. Show\n4. End");
printf("\n\nEnter the choice: ");
scanf("%d", &choice);
switch(choice)
{
case 1:
top = push(top, stack_array);
break;
case 2:
top = pop(top, stack_array);
break;
case 3:
top = show(top, stack_array);
break;
case 4:
break;
default:
printf("\nInvalid choice!");
}
}
return 0;
}
int push(int top, int stack_array[])
{
int x = 0;
if (top == MAX_STACK_SIZE - 1)
{
printf("\nOverflow!");
}
else
{
printf("\nEnter the element to be added onto the stack:");
scanf("%d", &x);
top = top + 1;
stack_array[top] = x;
}
return top;
}
int pop(int top, int stack_array[])
{
if (-1 == top)
{
printf("\nUnderflow!");
}
else
{
printf("\nPopped element: %d", stack_array[top]);
top = top - 1;
}
return top;
}
int show(int top, int stack_array[])
{
if (-1 == top)
{
printf("\nStack is empty!");
}
else
{
printf("\nElements present in the stack: \n");
for (int i = top; i >= 0; --i)
{
printf("%d\n", stack_array[i]);
}
}
return 0;
}

14
ex17/test.sh Normal file
View File

@ -0,0 +1,14 @@
#!/usr/bin/env bash
set -e
make clean
make ex17_test
./ex17_test db.dat c
./ex17_test db.dat s 1 zed zed@zedshaw.com 167
./ex17_test db.dat s 2 frank frank@zedshaw.com 177
./ex17_test db.dat s 3 joe joe@zedshaw.com 187
./ex17_test db.dat l
./ex17_test db.dat g 3

14
ex17/test2.sh Normal file
View File

@ -0,0 +1,14 @@
#!/usr/bin/env bash
set -e
make clean
make ex17v2
./ex17v2 db.dat c
./ex17v2 db.dat s 1 zed zed@zedshaw.com 167
./ex17v2 db.dat s 2 frank frank@zedshaw.com 177
./ex17v2 db.dat s 3 joe joe@zedshaw.com 187
./ex17v2 db.dat l
./ex17v2 db.dat g 3

6
ex18/Makefile Normal file
View File

@ -0,0 +1,6 @@
CFLAGS=-Wall -g
all: ex18 ex18_test
clean:
rm -f ex18 ex18_test

126
ex18/ex18.c Normal file
View File

@ -0,0 +1,126 @@
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <string.h>
// Our old friend die from ex17.
void die(const char *message)
{
if (errno)
{
perror(message);
}
exit(1);
}
// a typedef creates a fake type,.in this case for a function pointer
typedef int(*compare_cb)(int a, int b);
// ***************************************
// A classic bubble sort function that uses the compare_cb to do the sorting.
int *bubble_sort(int *numbers, int count, compare_cb cmp)
{
int temp = 0;
int i = 0;
int j = 0;
int *target = malloc(count * sizeof(int));
if (!target)
{
die("Memory error.");
}
memcpy(target, numbers, count * sizeof(int));
for (i = 0; i < count; ++i)
{
for (j = 0; j < count - 1; ++j)
{
if (cmp(target[j], target[j + 1]) > 0)
{
temp = target[j + 1];
target[j + 1] = target[j];
target[j] = temp;
}
}
}
return target;
}
int sorted_order(int a, int b)
{
return a - b;
}
int reverse_order(int a, int b)
{
return b - a;
}
int strange_order(int a, int b)
{
if (0 == a || 0 == b)
{
return 0;
}
else
{
return a % b;
}
}
// ******************************************
// Used to test that we are sorting things correctly
// by doing the sort and printing it out.
void test_sorting(int *numbers, int count, compare_cb cmp)
{
int i = 0;
int *sorted = bubble_sort(numbers, count, cmp);
if (!sorted)
{
die("Failed to sort as requested.");
}
for (i = 0; i < count; ++i)
{
printf("%d ", sorted[i]);
}
printf("\n");
free(sorted);
}
int main(int argc, char *argv[])
{
if (argc < 2)
{
die("USAGE: ex18 4 3 1 5 6");
}
int count = argc - 1;
int i = 0;
char **inputs = argv + 1;
// count times sizeof(int)
int *numbers = malloc(count * sizeof(int));
if (!numbers)
{
die("Memory error.");
}
for (i = 0; i < count; ++i)
{
numbers[i] = atoi(inputs[i]);
}
test_sorting(numbers, count, sorted_order);
test_sorting(numbers, count, reverse_order);
test_sorting(numbers, count, strange_order);
free(numbers);
return 0;
}

BIN
ex18/ex18_test Normal file

Binary file not shown.

184
ex18/ex18_test.c Normal file
View File

@ -0,0 +1,184 @@
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <string.h>
// Our old friend die from ex17.
void die(const char *message)
{
if (errno)
{
perror(message);
}
exit(1);
}
// a typedef creates a fake type,.in this case for a function pointer
typedef int(*compare_cb)(int a, int b);
typedef int*(*sort)(int *numbers, int count, compare_cb cmp);
// ***************************************
// A classic bubble sort function that uses the compare_cb to do the sorting.
int *bubble_sort(int *numbers, int count, compare_cb cmp)
{
int temp = 0;
int i = 0;
int j = 0;
int *target = malloc(count * sizeof(int));
if (!target)
{
die("Memory error.");
}
memcpy(target, numbers, count * sizeof(int));
for (i = 0; i < count; ++i)
{
for (j = 0; j < count - 1; ++j)
{
if (cmp(target[j], target[j + 1]) > 0)
{
temp = target[j + 1];
target[j + 1] = target[j];
target[j] = temp;
}
}
}
return target;
}
int *selection_sort(int *numbers, int count, compare_cb cmp)
{
int temp = 0;
int *target = malloc(count * sizeof(int));
int i = 0;
int j = 0;
int index = 0;
if (!target)
{
die("Memory error.");
}
memcpy(target, numbers, count * sizeof(int));
// One by one move boundary of unsorted subarray
for (i = 0; i < count - 1; ++i)
{
// Find the minimum element in unsorted array
index = i;
for (j = i + 1; j < count; ++j)
{
if (cmp(target[j], target[index]) < 0 )
{
index = j;
}
}
temp = target[index];
target[index] = target[i];
target[i] = temp;
}
return target;
}
int sorted_order(int a, int b)
{
return a - b;
}
int reverse_order(int a, int b)
{
return b - a;
}
// int bad_order(int a, int b, int c)
// {
// return a - b;
// }
int strange_order(int a, int b)
{
if (0 == a || 0 == b)
{
return 0;
}
else
{
return a % b;
}
}
// ******************************************
// Used to test that we are sorting things correctly
// by doing the sort and printing it out.
// void test_sorting(int *numbers, int count, compare_cb cmp)
void test_sort(sort s, int *numbers, int count, compare_cb cmp)
{
int i = 0;
// int *sorted = bubble_sort(numbers, count, cmp);
int *sorted = s(numbers, count, cmp);
if (!sorted)
{
die("Failed to sort as requested.");
}
for (i = 0; i < count; ++i)
{
printf("%d ", sorted[i]);
}
printf("\n");
free(sorted);
unsigned char *data = (unsigned char *)cmp;
for(i = 0; i < 25; ++i)
{
printf("%2x:", data[i]);
}
printf("\n");
}
int main(int argc, char *argv[])
{
if (argc < 2)
{
die("USAGE: ex18 4 3 1 5 6");
}
int count = argc - 1;
int i = 0;
char **inputs = argv + 1;
// count times sizeof(int)
int *numbers = malloc(count * sizeof(int));
if (!numbers)
{
die("Memory error.");
}
for (i = 0; i < count; ++i)
{
numbers[i] = atoi(inputs[i]);
}
// test_sort(numbers, count, sorted_order);
// test_sort(numbers, count, reverse_order);
// test_sort(numbers, count, strange_order);
test_sort(bubble_sort, numbers, count, sorted_order);
test_sort(selection_sort, numbers, count, sorted_order);
test_sort(bubble_sort, numbers, count, NULL);
// test_sort(numbers, count, NULL);
free(numbers);
return 0;
}

6
ex19/Makefile Normal file
View File

@ -0,0 +1,6 @@
CFLAGS=-Wall -g -DNDEBUG
all: ex19
clean:
rm -f ex19

30
ex19/dbg.h Normal file
View File

@ -0,0 +1,30 @@
#ifndef __dbg_h__
#define __dbg_h__
#include <stdio.h>
#include <errno.h>
#include <string.h>
#ifdef NDEBUG
#define debug(M, ...)
#else
#define debug(M, ...) fprintf(stderr, "DEBUG %s:%d: " M "\n", __FILE__, __LINE__, ##__VA_ARGS__)
#endif
#define clean_errno() (errno == 0 ? "None" : strerror(errno))
#define log_err(M, ...) fprintf(stderr, "[ERROR] (%s:%d: errno: %s) " M "\n", __FILE__, __LINE__, clean_errno(), ##__VA_ARGS__)
#define log_warn(M, ...) fprintf(stderr, "[WARN] (%s:%d: errno: %s) " M "\n", __FILE__, __LINE__, clean_errno(), ##__VA_ARGS__)
#define log_info(M, ...) fprintf(stderr, "[INFO] (%s:%s:%d) " M "\n", __FUNCTION__, __FILE__, __LINE__, ##__VA_ARGS__)
#define check(A, M, ...) if(!(A)) {log_err(M, ##__VA_ARGS__); errno=0; goto error;}
#define sentinel(M, ...) {log_err(M, ##__VA_ARGS__); errno=0; goto error;}
#define check_mem(A) check((A), "Out of memory.")
#define check_debug(A, M, ...) if(!(A)) {debug(M, ##__VA_ARGS__); errno=0; goto error;}
#endif

BIN
ex19/ex19 Normal file

Binary file not shown.

127
ex19/ex19.c Normal file
View File

@ -0,0 +1,127 @@
#include "dbg.h"
#include <stdlib.h>
#include <stdio.h>
void test_debug()
{
// notice you don't need the \n
debug("I have Brown Hair.");
// passing in arguments like printf
debug("I am %d years old.", 37);
}
void test_log_err()
{
log_err("I believe everthing is broken.");
log_err("There are %d problems in %s.", 0, "space");
}
void test_log_warn()
{
log_warn("You can safely ignore this.");
log_warn("Maybe consider looking at: %s.", "/etc/passwd");
}
void test_log_info()
{
log_info("Well I did something mundane.");
log_info("It happened %f times today.", 1.3f);
}
int test_check(char *file_name)
{
FILE *input = NULL;
char *block = NULL;
block = malloc(100);
check_mem(block); // should work
input = fopen(file_name, "r");
check(input, "Failed to open %s.", file_name);
free(block);
fclose(input);
return 0;
error:
if (block) {
free(block);
}
if (input) {
fclose(input);
}
return -1;
}
int test_sentinel(int code)
{
char *temp = malloc(100);
check_mem(temp);
switch (code) {
case 1:
log_info("It worked.");
break;
default:
sentinel("I shouldn't run.");
}
free(temp);
return 0;
error:
if (temp)
{
free(temp);
}
return -1;
}
int test_check_mem()
{
char *test = NULL;
check_mem(test);
free(test);
return 1;
error:
return -1;
}
int test_check_debug()
{
int i = 0;
check_debug(i != 0, "Oops, I was 0.");
return 0;
error:
return -1;
}
int main(int argc, char *argv[])
{
check(2 == argc, "Need an argument.");
test_debug();
// test_log_err();
// test_log_warn();
test_log_info();
check(0 == test_check("ex19.c"), "failed with ex19.c");
check(-1 == test_check(argv[1]), "failed with argv");
check(0 == test_sentinel(1), "test_sentinel failed.");
check(-1 == test_sentinel(100), "test_sentinel failed.");
check(-1 == test_check_mem(), "test_check_mem failed.");
check(-1 == test_check_debug(), "test_check_debug failed.");
return 0;
error:
return 1;
}

6
ex21/Makefile Normal file
View File

@ -0,0 +1,6 @@
CFLAGS=-Wall -g
all: ex21
clean:
rm -f ex21

BIN
ex21/ex21 Normal file

Binary file not shown.

249
ex21/ex21.c Normal file
View File

@ -0,0 +1,249 @@
#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>
#include <assert.h>
#include <string.h>
int main(void)
{
int integer = 55;
double num1 = 0.1;
float num2 = 0.2;
char ch = 'a';
void *thing = NULL;
enum weather{Sunny, Rainy, Cloudy};
enum weather today = Cloudy;
printf("%d %f %f %c %p %d\n", integer, num1, num2, ch, thing, today);
unsigned int num3 = 65533;
signed int num4 = 700000000;
long int num5 = 700000000000;
short int num6 = 65500;
printf("%u %d %ld %d\n", num3, num4, num5, num6);
const int num7 = 123;
volatile int num8 = 567;
register int num9 = 890;
// num7 = 1;
printf("%d %d %d\n", num7, num8, num9);
long num10 = 567;
char ch2 = '9';
int num11 = 890;
double num12 = 10.1;
printf("%lf\n", (double)num10 - (double)ch2 - (double)num11 * num12);
int8_t num13 = 130;
int16_t num14 = 130;
int32_t num15 = 130;
int64_t num16 = 130;
uint8_t num17 = 130;
uint16_t num18 = 130;
uint32_t num19 = 130;
uint64_t num20 = 130;
printf("int8: %d %d %d\n", num13, INT8_MAX, INT8_MIN);
printf("int16: %d %d %d\n", num14, INT16_MAX, INT16_MIN);
printf("int32: %d %d %d\n", num15, INT32_MAX, INT32_MIN);
printf("int64: %ld %ld %ld\n", num16, INT64_MAX, INT64_MIN);
printf("uint8: %d %d\n", num17, UINT8_MAX);
printf("uint16: %d %d\n", num18, UINT16_MAX);
printf("uint32: %d %u\n", num19, UINT32_MAX);
printf("uint64: %ld %lu\n", num20, UINT64_MAX);
int_least8_t num21 = 111;
int_least16_t num22 = 33333;
int_least32_t num23 = 4444;
int_least64_t num24 = 55555;
uint_least8_t num25 = 123;
uint_least16_t num26 = 444;
uint_least32_t num27 = 666;
uint_least64_t num28 = 999;
printf("int_least8: %d %d %d\n", num21, INT_LEAST8_MAX, INT_LEAST8_MIN);
printf("int_least16: %d %d %d\n", num22, INT_LEAST16_MAX, INT_LEAST16_MIN);
printf("int_least32: %d %d %d\n", num23, INT_LEAST32_MAX, INT_LEAST32_MIN);
printf("int_least64: %ld %ld %ld\n", num24, INT_LEAST64_MAX, INT_LEAST64_MIN);
printf("uint_least8_t: %u %u\n", num25, UINT_LEAST8_MAX);
printf("uint_least16_t: %u %u\n", num26, UINT_LEAST16_MAX);
printf("uint_least32_t: %u %u\n", num27, UINT_LEAST32_MAX);
printf("uint_least64_t: %lu %lu\n", num28, UINT_LEAST64_MAX);
int_fast8_t num29 = 111;
int_fast16_t num30 = 222;
int_fast32_t num31 = 444;
int_fast64_t num32 = 666;
uint_fast8_t num33 = 123;
uint_fast16_t num34 = 222;
uint_fast32_t num35 = 444;
uint_fast64_t num36 = 666;
printf("int_fast8: %d %d %d\n", num29, INT_FAST8_MAX, INT_FAST8_MIN);
printf("int_fast16: %ld %ld %ld\n", num30, INT_FAST16_MAX, INT_FAST16_MIN);
printf("int_fast32: %ld %ld %ld\n", num31, INT_FAST32_MAX, INT_FAST32_MIN);
printf("int_fast64: %ld %ld %ld\n", num32, INT_FAST64_MAX, INT_FAST64_MIN);
printf("uint_fast8: %u %u\n", num33, UINT_FAST8_MAX);
printf("uint_fast16: %lu %lu\n", num34, UINT_FAST16_MAX);
printf("uint_fast32: %lu %lu\n", num35, UINT_FAST32_MAX);
printf("uint_fast64: %lu %lu\n", num36, UINT_FAST64_MAX);
intptr_t num37 = 123;
uintptr_t num38 = 333;
printf("intptr: %ld %ld %ld\n", num37, INTPTR_MAX, INTPTR_MIN);
printf("uintptr: %lu %lu\n", num38, UINTPTR_MAX);
intmax_t num39 = 666;
uintmax_t num40 = 777;
printf("intmax: %ld %ld %ld\n", num39, INTMAX_MAX, INTMAX_MIN);
printf("uintmax: %lu %lu\n", num40, UINTMAX_MAX);
printf("ptrdiff: %ld %ld\n", PTRDIFF_MAX, PTRDIFF_MIN);
printf("size_t: %lu\n", SIZE_MAX);
// 运算符
int a = 5;
int b = 6;
printf("a*b: %d\n", a * b);
printf("a/b: %f\n", (double)a / (double)b);
printf("a+b: %d\n", a + b);
printf("+a: %d\n", +a);
printf("a++: %d\n", a++);
printf("a: %d\n", a);
printf("++a: %d\n", ++a);
printf("a: %d\n", a);
printf("a--: %d\n", a--);
printf("a: %d\n", a);
printf("--a: %d\n", --a);
printf("a: %d\n", a);
printf("a-b: %d\n", a - b);
printf("-a: %d\n", -a);
struct Person
{
char *name;
int age;
int height;
int weight;
};
char name[] = "博洋";
struct Person *who = malloc(sizeof(struct Person));
assert(who != NULL);
who -> name = strdup(name);
who -> age = 27;
who -> height = 181;
who -> weight = 160;
printf("My name is %s\n", who -> name);
printf("I am %d years old.\n", who -> age);
printf("I am %d cm tall.\n", who -> height);
printf("I am %f kg fat.\n", (double)(who -> weight) / (double)2);
struct Person who2;
who2.name = "王博洋\0";
who2.age = 27;
who2.height = 181;
who2.weight = 160;
printf("My name is %s\n", who2.name);
printf("I am %d years old.\n", who2.age);
printf("I am %d cm tall.\n", who2.height);
printf("I am %f kg fat.\n", (double)who2.weight / (double)2);
int arr[4] = {1, 3, 5, 6};
printf("sizeof arr: %ld\n", sizeof(arr));
int *p = arr;
printf("address: %p %p %p\n", p, (p + 1), &p);
printf("arr[1]: %d\n", *(p + 1));
double c = 5.0000001;
double d = 5.0000002;
// int e = 5;
if (c != d)
{
printf("c != b\n");
}
if (c < d)
{
printf("c < d\n");
}
if (c <= d)
{
printf("c <= d\n");
}
if (c == d)
{
printf("c == d\n");
}
if (c > d)
{
printf(" c > d\n");
}
if (c >= d)
{
printf(" c >= d\n");
}
int e = 255;
int f = 256;
printf(" hex: e:%x f:%x\n", e, f);
printf("e&f: %x\n", e&f);
printf("e >> 1: %x\n", e >> 1);
printf("e<<1: %x\n", e << 1);
printf("e^f: %x\n", e^f);
printf("e|f: %x\n", e|f);
printf("~e+1: %x\n", ~e + 1);
int g = 0;
int h = 1;
if (g)
{
printf("g is true\n");
}
if (!g)
{
printf(" g is not true\n");
}
if (g&&h)
{
printf("g&&h is true\n");
}
if (g||h)
{
printf("g||h is true\n");
}
g?printf("g is true\n") : printf("g is false\n");
return 0;
}

10
ex22/Makefile Normal file
View File

@ -0,0 +1,10 @@
all: ex22_main
ex22_main: ex22.o ex22_main.c
cc -Wall -g -DNDEBUG ex22_main.c ex22.o -o ex22_main
ex22.o: ex22.c
cc -Wall -g -DNDEBUG -c -o ex22.o ex22.c
clean:
rm -f ex22.o ex22_main

30
ex22/dbg.h Normal file
View File

@ -0,0 +1,30 @@
#ifndef __dbg_h__
#define __dbg_h__
#include <stdio.h>
#include <errno.h>
#include <string.h>
#ifdef NDEBUG
#define debug(M, ...)
#else
#define debug(M, ...) fprintf(stderr, "DEBUG %s:%d: " M "\n", __FILE__, __LINE__, ##__VA_ARGS__)
#endif
#define clean_errno() (errno == 0 ? "None" : strerror(errno))
#define log_err(M, ...) fprintf(stderr, "[ERROR] (%s:%d: errno: %s) " M "\n", __FILE__, __LINE__, clean_errno(), ##__VA_ARGS__)
#define log_warn(M, ...) fprintf(stderr, "[WARN] (%s:%d: errno: %s) " M "\n", __FILE__, __LINE__, clean_errno(), ##__VA_ARGS__)
#define log_info(M, ...) fprintf(stderr, "[INFO] (%s:%s:%d) " M "\n", __FUNCTION__, __FILE__, __LINE__, ##__VA_ARGS__)
#define check(A, M, ...) if(!(A)) {log_err(M, ##__VA_ARGS__); errno=0; goto error;}
#define sentinel(M, ...) {log_err(M, ##__VA_ARGS__); errno=0; goto error;}
#define check_mem(A) check((A), "Out of memory.")
#define check_debug(A, M, ...) if(!(A)) {debug(M, ##__VA_ARGS__); errno=0; goto error;}
#endif

71
ex22/ex22.c Normal file
View File

@ -0,0 +1,71 @@
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#include <string.h>
#include "ex22.h"
#include "dbg.h"
char *get_name(struct State *state)
{
return state->my_name;
}
void set_name(struct State *state, char *name)
{
state->my_name = name;
}
int get_size(struct State *state)
{
return state->the_size;
}
void set_size(struct State *state, int size)
{
state->the_size = size;
}
int get_age(struct State *state)
{
return state->the_age;
}
void set_age(struct State *state, int age)
{
state->the_age = age;
}
double update_ratio(double new_ratio)
{
static double ratio = 1.0;
double old_ratio = ratio;
ratio = new_ratio;
return old_ratio;
}
void print_size(struct State *state)
{
log_info("I think size is: %d", state->the_size);
}
void Person_destroy(struct State *who)
{
assert(who != NULL);
free(who->my_name);
free(who);
}
struct State *Person_create(char *name, int age, int size)
{
struct State *who = malloc(sizeof(struct State));
assert(who != NULL);
who->the_age = age;
who->the_size = size;
who->my_name = strdup(name);
return who;
}

30
ex22/ex22.h Normal file
View File

@ -0,0 +1,30 @@
#ifndef _ex22_h
#define _ex22_h
struct State {
int the_size;
int the_age;
char *my_name;
};
// gets and sets an internal static variable in ex22.c
int get_age(struct State *state);
void set_age(struct State *state, int age);
int get_size(struct State *state);
void set_size(struct State *state, int size);
char *get_name(struct State *state);
void set_name(struct State *state, char *name);
// updates a static variable that's inside update_ratio
double update_ratio(double ratio);
void print_size();
void Person_destroy(struct State *who);
struct State *Person_create(char *name, int age, int size);
#endif

BIN
ex22/ex22.o Normal file

Binary file not shown.

BIN
ex22/ex22_main Normal file

Binary file not shown.

62
ex22/ex22_main.c Normal file
View File

@ -0,0 +1,62 @@
#include "ex22.h"
#include "dbg.h"
void scope_demo(int count)
{
log_info("count is: %d", count);
if (count > 10 ) {
int apple = 100; // BAD! BUGS!
log_info("apple in this scope is %d", apple);
}
log_info("count is at exit: %d", count);
count = 3000;
log_info("count after assign: %d", count);
// scope_demo(3000);
}
int main(int argc, char *argv[])
{
struct State *joe = Person_create("Joe Alex", 27, 43);
// test out THE_AGE accessors
log_info("My name: %s, age: %d", get_name(joe), get_age(joe));
set_age(joe, 100);
log_info("My age is now: %d", get_age(joe));
// test out THE_SIZE extern
log_info("THE_SIZE is: %d", get_size(joe));
print_size();
set_size(joe, 9);
log_info("THE_SIZE IS NOW: %d", get_size(joe));
print_size();
// test the ratio function static
log_info("Ratio at first: %f", update_ratio(2.0));
log_info("Ratio again: %f", update_ratio(10.0));
log_info("Ratio once more: %f", update_ratio(300.0));
// ratio = 5;
// test the scope demo
int count = 4;
scope_demo(count);
scope_demo(count * 20);
log_info("count after calling scope_demo: %d", count);
Person_destroy(joe);
return 0;
}

6
ex22/task/Makefile Normal file
View File

@ -0,0 +1,6 @@
CFLAGS=-Wall -g
all: swap
clean:
rm -f swap

BIN
ex22/task/swap Normal file

Binary file not shown.

50
ex22/task/swap.c Normal file
View File

@ -0,0 +1,50 @@
#include <stdio.h>
int *ptr = NULL;
void Swap(int a, int b)
{
int temp = 0;
temp = a;
a = b;
b = temp;
}
void Swap2(int *a, int *b)
{
int temp = 100;
*ptr = temp;
temp = *a;
*a = *b;
*b = temp;
}
int main(void)
{
int a = 5;
int b = 9;
printf("before swap\n");
printf("a:%d b:%d\n", a, b);
Swap(a, b);
printf("after swap\n");
printf("a:%d b:%d\n", a, b);
Swap2(&a, &b);
printf("after swap2\n");
printf("a:%d b:%d\n", a, b);
printf("%d\n", *ptr);
return 0;
}

6
ex23/Makefile Normal file
View File

@ -0,0 +1,6 @@
CFLAGS=-Wall -g
all: ex23 ex23_copy test
clean:
rm -f ex23 ex23_copy test

30
ex23/dbg.h Normal file
View File

@ -0,0 +1,30 @@
#ifndef __dbg_h__
#define __dbg_h__
#include <stdio.h>
#include <errno.h>
#include <string.h>
#ifdef NDEBUG
#define debug(M, ...)
#else
#define debug(M, ...) fprintf(stderr, "DEBUG %s:%d: " M "\n", __FILE__, __LINE__, ##__VA_ARGS__)
#endif
#define clean_errno() (errno == 0 ? "None" : strerror(errno))
#define log_err(M, ...) fprintf(stderr, "[ERROR] (%s:%d: errno: %s) " M "\n", __FILE__, __LINE__, clean_errno(), ##__VA_ARGS__)
#define log_warn(M, ...) fprintf(stderr, "[WARN] (%s:%d: errno: %s) " M "\n", __FILE__, __LINE__, clean_errno(), ##__VA_ARGS__)
#define log_info(M, ...) fprintf(stderr, "[INFO] (%s:%s:%d) " M "\n", __FUNCTION__, __FILE__, __LINE__, ##__VA_ARGS__)
#define check(A, M, ...) if(!(A)) {log_err(M, ##__VA_ARGS__); errno=0; goto error;}
#define sentinel(M, ...) {log_err(M, ##__VA_ARGS__); errno=0; goto error;}
#define check_mem(A) check((A), "Out of memory.")
#define check_debug(A, M, ...) if(!(A)) {debug(M, ##__VA_ARGS__); errno=0; goto error;}
#endif

BIN
ex23/ex23 Normal file

Binary file not shown.

139
ex23/ex23.c Normal file
View File

@ -0,0 +1,139 @@
#include <stdio.h>
#include <string.h>
#include "dbg.h"
int normal_copy(char *from, char *to, int count)
{
int i = 0;
for (i = 0; i < count; ++i)
{
to[i] = from[i];
}
return i;
}
int duffs_device(char *from, char *to, int count)
{
{
int n = (count + 7) / 8;
switch (count % 8)
{
case 0:
do
{
*to++ = *from++;
case 7:
*to++ = *from++;
case 6:
*to++ = *from++;
case 5:
*to++ = *from++;
case 4:
*to++ = *from++;
case 3:
*to++ = *from++;
case 2:
*to++ = *from++;
case 1:
*to++ = *from++;
} while (--n > 0);
}
}
return count;
}
int zeds_device(char *from, char *to, int count)
{
{
int n = (count + 7) / 8;
switch (count % 8)
{
case 0:
again: *to++ = *from++;
case 7:
*to++ = *from++;
case 6:
*to++ = *from++;
case 5:
*to++ = *from++;
case 4:
*to++ = *from++;
case 3:
*to++ = *from++;
case 2:
*to++ = *from++;
case 1:
*to++ = *from++;
if (--n > 0)
{
goto again;
}
}
}
return count;
}
int valid_copy(char *data, int count, char expects)
{
int i = 0;
for ( i = 0; i < count; ++i)
{
if (data[i] != expects)
{
log_err("[%d] %c != %c", i, data[i], expects);
return 0;
}
}
return 1;
}
int main(int argc, char *argv[])
{
char from[999] = { 'a' };
char to[999] = { 'c' };
int rc = 0;
// printf("%s", from);
// set up the from to have some stuff
memset(from, 'x', 999);
// set it to a failure mode
memset(to, 'y', 999);
check(valid_copy(to, 999, 'y'), "Not initialized right.");
// use normal copy to
rc = normal_copy(from, to, 999);
check(rc == 999, "Normal copy failed: %d", rc);
check(valid_copy(to, 999, 'x'), "Normal copy failed.");
// reset
memset(to, 'y', 999);
// duffs version
rc = duffs_device(from, to, 999);
check(rc == 999, "Duff's device failed: %d", rc);
check(valid_copy(to, 999, 'x'), "Duff's device failed copy.");
// reset
memset(to, 'y', 999);
// my version
rc = zeds_device(from, to, 999);
check(rc == 999, "Zed's device failed: %d", rc);
check(valid_copy(to, 999, 'x'), "Zed's device failed copy.");
return 0;
error:
return 1;
}

BIN
ex23/ex23_copy Normal file

Binary file not shown.

139
ex23/ex23_copy.c Normal file
View File

@ -0,0 +1,139 @@
#include <stdio.h>
#include <string.h>
#include "dbg.h"
int normal_copy(char *from, char *to, int count)
{
int i = 0;
for (i = 0; i < count; ++i)
{
to[i] = from[i];
}
return i;
}
int duffs_device(char *from, char *to, int count)
{
{
int n = (count + 7) / 8;
switch (count % 8)
{
case 0:
do
{
*to = *from++;
case 7:
*to = *from++;
case 6:
*to = *from++;
case 5:
*to = *from++;
case 4:
*to = *from++;
case 3:
*to = *from++;
case 2:
*to = *from++;
case 1:
*to = *from++;
} while (--n > 0);
}
}
return count;
}
int zeds_device(char *from, char *to, int count)
{
{
int n = (count + 7) / 8;
switch (count % 8)
{
case 0:
again: *to++ = *from++;
case 7:
*to++ = *from++;
case 6:
*to++ = *from++;
case 5:
*to++ = *from++;
case 4:
*to++ = *from++;
case 3:
*to++ = *from++;
case 2:
*to++ = *from++;
case 1:
*to++ = *from++;
if (--n > 0)
{
goto again;
}
}
}
return count;
}
int valid_copy(char *data, int count, char expects)
{
int i = 0;
for ( i = 0; i < count; ++i)
{
if (data[i] != expects)
{
log_err("[%d] %c != %c", i, data[i], expects);
return 0;
}
}
return 1;
}
int main(int argc, char *argv[])
{
char from[999] = { 'a' };
char to[999] = { 'c' };
int rc = 0;
// printf("%s", from);
// set up the from to have some stuff
memset(from, 'x', 999);
// set it to a failure mode
memset(to, 'y', 999);
check(valid_copy(to, 999, 'y'), "Not initialized right.");
// use normal copy to
rc = normal_copy(from, to, 999);
check(rc == 999, "Normal copy failed: %d", rc);
check(valid_copy(to, 999, 'x'), "Normal copy failed.");
// reset
memset(to, 'y', 999);
// duffs version
rc = duffs_device(from, to, 999);
check(rc == 999, "Duff's device failed: %d", rc);
check(valid_copy(to, 999, 'x'), "Duff's device failed copy.");
// reset
memset(to, 'y', 999);
// my version
rc = zeds_device(from, to, 999);
check(rc == 999, "Zed's device failed: %d", rc);
check(valid_copy(to, 999, 'x'), "Zed's device failed copy.");
return 0;
error:
return 1;
}

BIN
ex23/test Normal file

Binary file not shown.

13
ex23/test.c Normal file
View File

@ -0,0 +1,13 @@
#include <stdio.h>
#define AREA(l, b) (l * b)
#define CASE_STATEMENT(n) case n: \
*to++ = *from++;
int main(void)
{
printf("hello, world!%d\n", AREA(10, 5));
return 0;
}

6
ex24/Makefile Normal file
View File

@ -0,0 +1,6 @@
CFLAGS=-Wall -g
all: ex24 test ex24_copy ex24_change
clean:
rm -f ex24 test ex24_copy ex24_change

30
ex24/dbg.h Normal file
View File

@ -0,0 +1,30 @@
#ifndef __dbg_h__
#define __dbg_h__
#include <stdio.h>
#include <errno.h>
#include <string.h>
#ifdef NDEBUG
#define debug(M, ...)
#else
#define debug(M, ...) fprintf(stderr, "DEBUG %s:%d: " M "\n", __FILE__, __LINE__, ##__VA_ARGS__)
#endif
#define clean_errno() (errno == 0 ? "None" : strerror(errno))
#define log_err(M, ...) fprintf(stderr, "[ERROR] (%s:%d: errno: %s) " M "\n", __FILE__, __LINE__, clean_errno(), ##__VA_ARGS__)
#define log_warn(M, ...) fprintf(stderr, "[WARN] (%s:%d: errno: %s) " M "\n", __FILE__, __LINE__, clean_errno(), ##__VA_ARGS__)
#define log_info(M, ...) fprintf(stderr, "[INFO] (%s:%s:%d) " M "\n", __FUNCTION__, __FILE__, __LINE__, ##__VA_ARGS__)
#define check(A, M, ...) if(!(A)) {log_err(M, ##__VA_ARGS__); errno=0; goto error;}
#define sentinel(M, ...) {log_err(M, ##__VA_ARGS__); errno=0; goto error;}
#define check_mem(A) check((A), "Out of memory.")
#define check_debug(A, M, ...) if(!(A)) {debug(M, ##__VA_ARGS__); errno=0; goto error;}
#endif

BIN
ex24/ex24 Normal file

Binary file not shown.

77
ex24/ex24.c Normal file
View File

@ -0,0 +1,77 @@
#include <stdio.h>
#include "dbg.h"
#define MAX_DATA 100
typedef enum EyeColor {
BLUE_EYES, GREEN_EYES, BROWN_EYES,
BLACK_EYES, OTHER_EYES
} EyeColor;
const char *EYE_COLOR_NAMES[] = {
"Blue", "Green", "Brown", "Black", "Other"
};
typedef struct Person {
int age;
char first_name[MAX_DATA];
char last_name[MAX_DATA];
EyeColor eyes;
double income;
} Person;
int main(int argc, char *argv[])
{
Person you = { .age = 0 };
int i = 0;
char *in = NULL;
printf("What's your First Name? ");
in = fgets(you.first_name, MAX_DATA - 1, stdin);
// gets(you.first_name);
check(in != NULL, "Failed to read first name.");
// fscanf(stdin, "%50s", you.first_name);
printf("What's your Last Name? ");
in = fgets(you.last_name, MAX_DATA - 1, stdin);
check(in != NULL, "Failed to read last name.");
printf("How old are you? ");
int rc = fscanf(stdin, "%d", &you.age);
check(rc > 0, "You have to enter a number.");
printf("What color are your eyes:\n");
for (i = 0; i <= OTHER_EYES; ++i)
{
printf("%d %s\n", i + 1, EYE_COLOR_NAMES[i]);
}
printf("> ");
int eyes = -1;
rc = fscanf(stdin, "%d", &eyes);
check(rc > 0, "You have to enter a number.");
you.eyes = eyes - 1;
check(you.eyes <= OTHER_EYES
&& you.eyes >= 0, "Do it right, that's not an option.");
printf("How much do you make an hour? ");
rc = fscanf(stdin, "%lf", &you.income);
check(rc > 0, "Enter a floating point number.");
printf("----- RESULTS -----\n");
printf("First Name: %s", you.first_name);
printf("Last Name: %s", you.last_name);
printf("Age: %d\n", you.age);
printf("Eyes: %s\n", EYE_COLOR_NAMES[you.eyes]);
printf("Income: %f\n", you.income);
return 0;
error:
return -1;
}

BIN
ex24/ex24_change Normal file

Binary file not shown.

90
ex24/ex24_change.c Normal file
View File

@ -0,0 +1,90 @@
#include <stdio.h>
#include "dbg.h"
#define MAX_DATA 100
typedef enum EyeColor {
BLUE_EYES, GREEN_EYES, BROWN_EYES,
BLACK_EYES, OTHER_EYES
} EyeColor;
const char *EYE_COLOR_NAMES[] = {
"Blue", "Green", "Brown", "Black", "Other"
};
typedef struct Person {
int age;
char first_name[MAX_DATA];
char last_name[MAX_DATA];
EyeColor eyes;
double income;
} Person;
int main(int argc, char *argv[])
{
Person you = { .age = 0 };
int i = 0;
char *in = NULL;
int j = 0;
printf("What's your First Name? ");
in = fgets(you.first_name, MAX_DATA - 1, stdin);
// gets(you.first_name);
check(in != NULL, "Failed to read first name.");
for (j = 0; you.first_name[j] != '\0'; ++j)
{
}
// printf("j:%d\n", j);
you.first_name[j - 1] = '\0';
// fscanf(stdin, "%50s", you.first_name);
printf("What's your Last Name? ");
in = fgets(you.last_name, MAX_DATA - 1, stdin);
check(in != NULL, "Failed to read last name.");
for (j = 0; you.last_name[j] != '\0'; ++j)
{
}
you.last_name[j - 1] = '\0';
printf("How old are you? ");
int rc = fscanf(stdin, "%d", &you.age);
check(rc > 0, "You have to enter a number.");
printf("What color are your eyes:\n");
for (i = 0; i <= OTHER_EYES; ++i)
{
printf("%d %s\n", i + 1, EYE_COLOR_NAMES[i]);
}
printf("> ");
int eyes = -1;
rc = fscanf(stdin, "%d", &eyes);
check(rc > 0, "You have to enter a number.");
you.eyes = eyes - 1;
check(you.eyes <= OTHER_EYES
&& you.eyes >= 0, "Do it right, that's not an option.");
printf("How much do you make an hour? ");
rc = fscanf(stdin, "%lf", &you.income);
check(rc > 0, "Enter a floating point number.");
printf("----- RESULTS -----\n");
printf("First Name: %s", you.first_name);
printf("Last Name: %s", you.last_name);
printf("Age: %d\n", you.age);
printf("Eyes: %s\n", EYE_COLOR_NAMES[you.eyes]);
printf("Income: %f\n", you.income);
return 0;
error:
return -1;
}

BIN
ex24/ex24_copy Normal file

Binary file not shown.

92
ex24/ex24_copy.c Normal file
View File

@ -0,0 +1,92 @@
#include <stdio.h>
#include <stdlib.h>
#include "dbg.h"
#define MAX_DATA 100
typedef enum EyeColor {
BLUE_EYES, GREEN_EYES, BROWN_EYES,
BLACK_EYES, OTHER_EYES
} EyeColor;
const char *EYE_COLOR_NAMES[] = {
"Blue", "Green", "Brown", "Black", "Other"
};
typedef struct Person {
int age;
char first_name[MAX_DATA];
char last_name[MAX_DATA];
EyeColor eyes;
double income;
} Person;
int main(int argc, char *argv[])
{
Person you = { .age = 0 };
int i = 0;
char *in = NULL;
char temp_age[MAX_DATA];
char temp_eyes[MAX_DATA];
char temp_income[MAX_DATA];
printf("What's your First Name? ");
in = fgets(you.first_name, MAX_DATA - 1, stdin);
// gets(you.first_name);
check(in != NULL, "Failed to read first name.");
// fscanf(stdin, "%50s", you.first_name);
printf("What's your Last Name? ");
in = fgets(you.last_name, MAX_DATA - 1, stdin);
check(in != NULL, "Failed to read last name.");
printf("How old are you? ");
in = fgets(temp_age, MAX_DATA - 1, stdin);
you.age = atoi(temp_age);
check(in != NULL, "Failed to read age.");
// int rc = fscanf(stdin, "%d", &you.age);
// check(rc > 0, "You have to enter a number.");
printf("What color are your eyes:\n");
for (i = 0; i <= OTHER_EYES; ++i)
{
printf("%d %s\n", i + 1, EYE_COLOR_NAMES[i]);
}
printf("> ");
int eyes = -1;
// rc = fscanf(stdin, "%d", &eyes);
// check(rc > 0, "You have to enter a number.");
in = fgets(temp_eyes, MAX_DATA - 1, stdin);
check(in != NULL, "Failed to read eyes.");
eyes = atoi(temp_eyes);
you.eyes = eyes - 1;
check(you.eyes <= OTHER_EYES
&& you.eyes >= 0, "Do it right, that's not an option.");
printf("How much do you make an hour? ");
// rc = fscanf(stdin, "%f", &you.income);
// check(rc > 0, "Enter a floating point number.");
in = fgets(temp_income, MAX_DATA - 1, stdin);
check(in != NULL, "Failed to read eyes.");
you.income = atof(temp_income);
printf("----- RESULTS -----\n");
printf("First Name: %s", you.first_name);
printf("Last Name: %s", you.last_name);
printf("Age: %d\n", you.age);
printf("Eyes: %s\n", EYE_COLOR_NAMES[you.eyes]);
printf("Income: %f\n", you.income);
return 0;
error:
return -1;
}

BIN
ex24/ex24_func Normal file

Binary file not shown.

77
ex24/ex24_func.c Normal file
View File

@ -0,0 +1,77 @@
#include <stdio.h>
#include "dbg.h"
#define MAX_DATA 100
typedef enum EyeColor {
BLUE_EYES, GREEN_EYES, BROWN_EYES,
BLACK_EYES, OTHER_EYES
} EyeColor;
const char *EYE_COLOR_NAMES[] = {
"Blue", "Green", "Brown", "Black", "Other"
};
typedef struct Person {
int age;
char first_name[MAX_DATA];
char last_name[MAX_DATA];
EyeColor eyes;
double income;
} Person;
int main(int argc, char *argv[])
{
Person you = { .age = 0 };
int i = 0;
char *in = NULL;
printf("What's your First Name? ");
in = fgets(you.first_name, MAX_DATA - 1, stdin);
// gets(you.first_name);
check(in != NULL, "Failed to read first name.");
// fscanf(stdin, "%50s", you.first_name);
printf("What's your Last Name? ");
in = fgets(you.last_name, MAX_DATA - 1, stdin);
check(in != NULL, "Failed to read last name.");
printf("How old are you? ");
int rc = scanf("%d", &you.age);
check(rc > 0, "You have to enter a number.");
printf("What color are your eyes:\n");
for (i = 0; i <= OTHER_EYES; ++i)
{
printf("%d %s\n", i + 1, EYE_COLOR_NAMES[i]);
}
printf("> ");
int eyes = -1;
rc = scanf("%d", &eyes);
check(rc > 0, "You have to enter a number.");
you.eyes = eyes - 1;
check(you.eyes <= OTHER_EYES
&& you.eyes >= 0, "Do it right, that's not an option.");
printf("How much do you make an hour? ");
rc = scanf("%lf", &you.income);
check(rc > 0, "Enter a floating point number.");
printf("----- RESULTS -----\n");
printf("First Name: %s", you.first_name);
printf("Last Name: %s", you.last_name);
printf("Age: %d\n", you.age);
printf("Eyes: %s\n", EYE_COLOR_NAMES[you.eyes]);
printf("Income: %f\n", you.income);
return 0;
error:
return -1;
}

BIN
ex24/test Normal file

Binary file not shown.

98
ex24/test.c Normal file
View File

@ -0,0 +1,98 @@
#include <stdio.h>
#include <stdlib.h>
int ReadFile(const char* fname, int size, char name[], int arr_size)
{
int is_ok = EXIT_FAILURE;
FILE* fp = fopen(fname, "w+");
int i = 0;
if (!fp)
{
perror("File opening failed");
return is_ok;
}
fputs("Boyang Wang\n", fp);
rewind(fp);
// int c;
int rc_scanf;
for (i = 0; (i < size - 1)&&(i < arr_size - 1); ++i)
{
// if ((c = fgetc(fp)) != EOF)
// {
// name[i] = c;
// }
rc_scanf = fscanf(fp, "%c", &name[i]);
if (0 == rc_scanf)
{
printf("rc_scanf=0\n");
}
}
name[i] = '\0';
if (ferror(fp))
{
puts("I/O error when reading");
}
else if (feof(fp))
{
puts("End of file is reached successfully");
is_ok = EXIT_SUCCESS;
}
fclose(fp);
remove(fname);
return is_ok;
}
int main(void)
{
const char* fname = "./hello.txt";
int is_ok = EXIT_FAILURE;
FILE* fp = fopen(fname, "w+");
if (!fp)
{
perror("File opening failed");
return is_ok;
}
fputs("Hello, world!\n", fp);
rewind(fp);
int c; // note: int, not char, required to handle EOF
while((c = fgetc(fp)) != EOF)
{
putchar(c);
}
if (ferror(fp))
{
puts("I/O error when reading");
}
else if (feof(fp))
{
puts("End of file is reached successfully");
is_ok = EXIT_SUCCESS;
}
fclose(fp);
remove(fname);
char name[100];
ReadFile("./hello.txt", 12, name, 100);
printf("name:%s\n", name);
return is_ok;
}

6
ex25/Makefile Normal file
View File

@ -0,0 +1,6 @@
CFLAGS=-Wall -g
all: ex25 ex25_copy myPrint simplePrint
clean:
rm -f ex25 ex25_copy myPrint simplePrint

30
ex25/dbg.h Normal file
View File

@ -0,0 +1,30 @@
#ifndef __dbg_h__
#define __dbg_h__
#include <stdio.h>
#include <errno.h>
#include <string.h>
#ifdef NDEBUG
#define ZED_DEBUG_MACRO(M, ...)
#else
#define ZED_DEBUG_MACRO(M, ...) fprintf(stderr, "DEBUG %s:%d: " M "\n", __FILE__, __LINE__, ##__VA_ARGS__)
#endif
#define ZED_CLEAN_ERRNO_MACRO() (errno == 0 ? "None" : strerror(errno))
#define ZED_LOG_ERR_MACRO(M, ...) fprintf(stderr, "[ERROR] (%s:%d: errno: %s) " M "\n", __FILE__, __LINE__, ZED_CLEAN_ERRNO_MACRO(), ##__VA_ARGS__)
#define ZED_LOG_WARN_MACRO(M, ...) fprintf(stderr, "[WARN] (%s:%d: errno: %s) " M "\n", __FILE__, __LINE__, ZED_CLEAN_ERRNO_MACRO(), ##__VA_ARGS__)
#define ZED_LOG_INFO_MACRO(M, ...) fprintf(stderr, "[INFO] (%s:%s:%d) " M "\n", __FUNCTION__, __FILE__, __LINE__, ##__VA_ARGS__)
#define ZED_CHECK_MACRO(A, M, ...) if(!(A)) {ZED_LOG_ERR_MACRO(M, ##__VA_ARGS__); errno=0; goto error;}
#define ZED_SENTINEL_MACRO(M, ...) {ZED_LOG_ERR_MACRO(M, ##__VA_ARGS__); errno=0; goto error;}
#define ZED_CHECK_MEM_MACRO(A) ZED_CHECK_MACRO((A), "Out of memory.")
#define ZED_CHECK_DEBUG_MACRO(A, M, ...) if(!(A)) {ZED_DEBUG_MACRO(M, ##__VA_ARGS__); errno=0; goto error;}
#endif

BIN
ex25/ex25 Normal file

Binary file not shown.

179
ex25/ex25.c Normal file
View File

@ -0,0 +1,179 @@
// WARNING:This code is freash and potentially isn't correct yet.
#include <stdlib.h>
#include <stdio.h>
#include <stdarg.h>
#include "dbg.h"
#include <string.h>
#define MAX_DATA_LENGTH_OF_STRING 100
int read_string(char **out_string, int max_buffer)
{
*out_string = calloc(1, max_buffer + 1);
ZED_CHECK_MEM_MACRO(*out_string);
// printf("hello_s");
char *result = fgets(*out_string, max_buffer, stdin);
ZED_CHECK_MACRO(result != NULL, "Input error.");
return 0;
error:
if (*out_string)
{
free(*out_string);
}
*out_string = NULL;
return -1;
}
int read_long(long *out_long)
{
char *input = NULL;
// char *end = NULL;
int rc = read_string(&input, MAX_DATA_LENGTH_OF_STRING);
// printf("hello_int");
ZED_CHECK_MACRO(0 == rc, "Failed to read number.");
// *out_int = strtoi(input, &end, 10);
// ZED_CHECK_MACRO(('\0' == *end || '\n' == *end) &&
// *input != '\0', "Input number: %s", input);
*out_long = atoi(input);
// calloc set memery to zero, so we can check by testing if *input=='\0'
ZED_CHECK_MACRO(*input != '\0', "Input number: %s", input);
free(input);
return 0;
error:
if (input)
{
free(input);
}
return -1;
}
int read_scan(const char *fmt, ...)
{
int i = 0;
int rc = 0;
long *out_long = NULL;
char *out_char = NULL;
char **out_string = NULL;
int max_buffer = 0;
va_list argp;
va_start(argp, fmt);
for (i = 0; fmt[i] != '\0'; ++i)
{
if ('%' == fmt[i])
{
++i;
switch (fmt[i])
{
case '\0':
ZED_SENTINEL_MACRO("Invalid format, you ended with %%.");
break;
case 'd':
out_long = va_arg(argp, long *);
rc = read_long(out_long);
ZED_CHECK_MACRO(0 == rc, "Failed to read long.");
break;
case 'c':
out_char = va_arg(argp, char *);
*out_char = fgetc(stdin);
break;
case 's':
max_buffer = va_arg(argp, int);
out_string = va_arg(argp, char **);
rc = read_string(out_string, max_buffer);
ZED_CHECK_MACRO(0 == rc, "Failed to read string.");
break;
default:
ZED_SENTINEL_MACRO("Invalid format.");
}
}
else
{
fgetc(stdin);
}
ZED_CHECK_MACRO(!feof(stdin) && !ferror(stdin), "Input error.");
}
va_end(argp);
return 0;
error:
va_end(argp);
return -1;
}
int main(int argc, char *argv[])
{
char *first_name = NULL;
char initial = ' ';
char *last_name = NULL;
long age = 0;
printf("What's your first name? ");
int rc = read_scan("%s", MAX_DATA_LENGTH_OF_STRING, &first_name);
// int rc = read_scan("%s", &first_name);
ZED_CHECK_MACRO(0 == rc, "Failed first name.");
printf("What's your initial? ");
rc = read_scan("%c\n", &initial);
ZED_CHECK_MACRO(0 == rc, "Failed initial.");
printf("What's your last name? ");
rc = read_scan("%s", MAX_DATA_LENGTH_OF_STRING, &last_name);
ZED_CHECK_MACRO(0 == rc, "Failed last name.");
// printf("last_name: %s", last_name);
printf("How old are you? ");
rc = read_scan("%d", &age);
ZED_CHECK_MACRO(0 == rc, "Failed to read age.");
printf("----- RESULTS -----\n");
printf("First Name: %s", first_name);
printf("Initial: '%c'\n", initial);
printf("Last Name: %s", last_name);
// printf("Age: %ld\n", age);
printf("Age: %ld\n", age);
free(first_name);
free(last_name);
return 0;
error:
return -1;
}

BIN
ex25/ex25_copy Normal file

Binary file not shown.

230
ex25/ex25_copy.c Normal file
View File

@ -0,0 +1,230 @@
// WARNING:This code is freash and potentially isn't correct yet.
#include <stdlib.h>
#include <stdio.h>
#include <stdarg.h>
#include "dbg.h"
#include <string.h>
#define MAX_DATA_LENGTH_OF_STRING 100
int read_string(char **out_string, int max_buffer)
{
*out_string = calloc(1, max_buffer + 1);
ZED_CHECK_MEM_MACRO(*out_string);
// printf("hello_s");
// char *result = fgets(*out_string, max_buffer, stdin);
int c;
int count = 0;
char *arr = *out_string;
while (( c = fgetc(stdin)) != '\n')
{
arr[count] = c;
// putchar(c);
++count;
}
// putchar('\n');
// ZED_CHECK_MACRO(result != NULL, "Input error.");
ZED_CHECK_MACRO(*out_string != NULL, "Input error.");
return 0;
error:
if (*out_string)
{
free(*out_string);
}
*out_string = NULL;
return -1;
}
int read_long(long *out_long)
{
char *input = NULL;
// char *end = NULL;
int rc = read_string(&input, MAX_DATA_LENGTH_OF_STRING);
printf("hello_int");
ZED_CHECK_MACRO(0 == rc, "Failed to read number.");
// *out_int = strtoi(input, &end, 10);
// ZED_CHECK_MACRO(('\0' == *end || '\n' == *end) &&
// *input != '\0', "Input number: %s", input);
*out_long = atoi(input);
// calloc set memery to zero, so we can check by testing if *input=='\0'
ZED_CHECK_MACRO(*input != '\0', "Input number: %s", input);
free(input);
return 0;
error:
if (input)
{
free(input);
}
return -1;
}
int read_scan(const char *fmt, ...)
{
int i = 0;
int rc = 0;
long *out_long = NULL;
char *out_char = NULL;
char **out_string = NULL;
int max_buffer = 0;
va_list argp;
va_start(argp, fmt);
for (i = 0; fmt[i] != '\0'; ++i)
{
if ('%' == fmt[i])
{
++i;
switch (fmt[i])
{
case '\0':
ZED_SENTINEL_MACRO("Invalid format, you ended with %%.");
break;
case 'd':
out_long = va_arg(argp, long *);
rc = read_long(out_long);
ZED_CHECK_MACRO(0 == rc, "Failed to read long.");
break;
case 'c':
out_char = va_arg(argp, char *);
*out_char = fgetc(stdin);
break;
case 's':
max_buffer = va_arg(argp, int);
out_string = va_arg(argp, char **);
rc = read_string(out_string, max_buffer);
ZED_CHECK_MACRO(0 == rc, "Failed to read string.");
break;
default:
ZED_SENTINEL_MACRO("Invalid format.");
}
}
else
{
fgetc(stdin);
}
ZED_CHECK_MACRO(!feof(stdin) && !ferror(stdin), "Input error.");
}
va_end(argp);
return 0;
error:
va_end(argp);
return -1;
}
void simple_printf(const char* fmt, ...)
{
va_list args;
va_start(args, fmt);
while (*fmt != '\0') {
if (*fmt == 'd') {
int i = va_arg(args, int);
printf("%d\n", i);
} else if (*fmt == 'c') {
// A 'char' variable will be promoted to 'int'
// A character literal in C is already 'int' by itself
int c = va_arg(args, int);
printf("\'%c\'\n", c);
} else if (*fmt == 'f') {
double d = va_arg(args, double);
printf("%f\n", d);
} else if (*fmt == 's') {
char *str = va_arg(args, char*);
printf("%s\n", str);
}
// printf("fmt:%c", *fmt);
++fmt;
}
va_end(args);
}
int main(int argc, char *argv[])
{
char *first_name = NULL;
char initial = ' ';
char *last_name = NULL;
long age = 0;
printf("What's your first name? ");
int rc = read_scan("%s", MAX_DATA_LENGTH_OF_STRING, &first_name);
// int rc = read_scan("%s", &first_name);
ZED_CHECK_MACRO(0 == rc, "Failed first name.");
printf("What's your initial? ");
rc = read_scan("%c\n", &initial);
ZED_CHECK_MACRO(0 == rc, "Failed initial.");
printf("What's your last name? ");
rc = read_scan("%s", MAX_DATA_LENGTH_OF_STRING, &last_name);
ZED_CHECK_MACRO(0 == rc, "Failed last name.");
// printf("last_name: %s", last_name);
printf("How old are you? ");
rc = read_scan("%d", &age);
ZED_CHECK_MACRO(0 == rc, "Failed to read age.");
printf("----- RESULTS -----\n");
printf("First Name: %s", first_name);
printf("Initial: '%c'\n", initial);
printf("Last Name: %s", last_name);
// printf("Age: %ld\n", age);
printf("Age: %ld\n", age);
puts("----- RESULTS -----\n");
puts("First Name: ");
simple_printf("s", first_name);
puts("Initial: ");
simple_printf("c", initial);
puts("Last Name: ");
simple_printf("s", last_name);
puts("Age: ");
simple_printf("d", age);
free(first_name);
free(last_name);
return 0;
error:
return -1;
}

BIN
ex25/myPrint Normal file

Binary file not shown.

61
ex25/myPrint.c Normal file
View File

@ -0,0 +1,61 @@
#include <stdio.h>
#include <stdarg.h>
#include "dbg.h"
int MyPrint(const char *fmt, ...)
{
int i = 0;
// int rc = 0;
char out_char;
// int max_buffer = 0;
puts("Hello");
va_list argp;
va_start(argp, fmt);
for (i = 0; fmt[i] != '\0'; ++i)
{
if ('%' == fmt[i])
{
++i;
switch(fmt[i])
{
case 'c':
out_char = va_arg(argp, int);
putchar(out_char);
break;
default:
ZED_SENTINEL_MACRO("Invalid format.");
}
}
else
{
fgetc(stdin);
}
ZED_CHECK_MACRO(!feof(stdin) && !ferror(stdin), "Input error.");
}
va_end(argp);
return 0;
error:
va_end(argp);
return -1;
}
int main(void)
{
int rc = 0;
rc = MyPrint("%c\n", 'p');
ZED_CHECK_MACRO(0 == rc, "Failed initial");
return 0;
error:
return -1;
}

BIN
ex25/simplePrint Normal file

Binary file not shown.

36
ex25/simplePrint.c Normal file
View File

@ -0,0 +1,36 @@
#include <stdio.h>
#include <stdarg.h>
void simple_printf(const char* fmt, ...)
{
va_list args;
va_start(args, fmt);
while (*fmt != '\0') {
if (*fmt == 'd') {
int i = va_arg(args, int);
printf("%d\n", i);
} else if (*fmt == 'c') {
// A 'char' variable will be promoted to 'int'
// A character literal in C is already 'int' by itself
int c = va_arg(args, int);
printf("%c\n", c);
} else if (*fmt == 'f') {
double d = va_arg(args, double);
printf("%f\n", d);
} else if (*fmt == 's') {
char *str = va_arg(args, char*);
printf("%s\n", str);
}
// printf("fmt:%c", *fmt);
++fmt;
}
va_end(args);
}
int main(void)
{
simple_printf("dcffs", 3, 'a', 1.999, 42.5, "helloC");
}

6
ex26-20240112/Makefile Normal file
View File

@ -0,0 +1,6 @@
CFLAGS=-Wall -g
all: ex25
clean:
rm -f ex26

BIN
ex26-20240112/ex26 Normal file

Binary file not shown.

127
ex26-20240112/ex26.c Normal file
View File

@ -0,0 +1,127 @@
#include <stdio.h>
#include <stdlib.h>
int main(int argc, char *argv[])
{
int i = 0;
// 打印出输入的参数
if (1 == argc)
{
printf("You only have one argument. You suck.\n");
}
else
{
printf("Here's your arguments:\n");
for (i = 0; i < argc; ++i)
{
printf("%s ", argv[i]);
}
printf("\n");
}
// 从~/.logfind中加载允许访问的日志文件
const char* fname = "/home/charles/.logfind";
int is_ok = EXIT_FAILURE;
FILE* fp = fopen(fname, "w+");
if (!fp)
{
perror("File opening failed");
return is_ok;
}
// 创建文件名列表
fputs("Turing\n",fp);
fputs("Turing1\n", fp);
fputs("Turing2\n", fp);
fputs("Turing9\n",fp);
fputs("Neumann\n", fp);
fputs("Church\n", fp);
rewind(fp);
// 读取文件,打印出匹配的行
int index = 0;
int is_same = 1; // 1表示匹配
const int buf_size = 10; // 文件名最长为9个字符
// char buf_get[buf_size] = argv[1]; // 存储读入的第二个字符串
char buf_file[buf_size];
for (int j = 0; j < buf_size; ++j)
{
buf_file[j] = '\0';
}
int c; // note: int, not char, required to handle EOF
index = 0;
while (((c = fgetc(fp)) != EOF) ) // standard C I/O file reading loop
{
// putchar(argv[1][index]);
// 存入当前行的内容,假设文件名中不包含换行符
if (c != '\n') // 如果当前行的读取没有结束,则继续读入字符
{
buf_file[index] = c;
}
// 对当前行进行处理
if (1 == argc)
{
break;
}
else if (2 == argc)
{
// 朴素模式串匹配,跳过了换行符和问号,包括了问号的功能
if ((c != argv[1][index]) && (c != '\n') && ('?' != argv[1][index]))
{
is_same = 0;
}
// 一行结束
if (c == '\n')
{
if ('?' == argv[1][index]) // 防止文件名末尾出现?时的错误匹配
{
is_same = 0;
}
// (1 == is_same)?puts(" ok"): puts(" no");
if (1 == is_same) // 如果匹配
{
puts(buf_file);
}
// 变量重置
index = -1; // index要等于-1因为后面要++
is_same = 1;
for (int j = 0; j < buf_size; ++j)
{
buf_file[j] = '\0';
}
}
// putchar(c);
++index;
}
else if (argc > 2)
{
}
}
// putchar('a');
if (ferror(fp))
{
puts("I/O error when reading");
}
else if (feof(fp))
{
puts("End of file reached");
is_ok = EXIT_SUCCESS;
}
fclose(fp);
remove(fname);
return is_ok;
}

1
ex26-20240112/guy.txt Normal file
View File

@ -0,0 +1 @@
hello, guys

1
ex26-20240112/smart.txt Normal file
View File

@ -0,0 +1 @@
you are smart

View File

@ -0,0 +1 @@
are you zedshaw

View File

@ -0,0 +1 @@
zedshaw is a smart guy

6
ex26/Makefile Normal file
View File

@ -0,0 +1,6 @@
CFLAGS=-Wall -g
all: ex25
clean:
rm -f ex26

BIN
ex26/ex26 Normal file

Binary file not shown.

106
ex26/ex26.c Normal file
View File

@ -0,0 +1,106 @@
#include <stdio.h>
#include <stdlib.h>
int main(int argc, char *argv[])
{
int i = 0;
// 打印出输入的参数
if (1 == argc)
{
printf("You only have one argument. You suck.\n");
}
else
{
printf("Here's your arguments:\n");
for (i = 0; i < argc; ++i)
{
printf("%s ", argv[i]);
}
printf("\n");
}
// 从~/.logfind中加载允许访问的日志文件
const char* fname = "/home/charles/.logfind";
int is_ok = EXIT_FAILURE;
FILE* fp = fopen(fname, "w+");
if (!fp)
{
perror("File opening failed");
return is_ok;
}
// 创建文件名列表
fputs("Turing1\n", fp);
fputs("Turing2\n", fp);
fputs("Turing9\n",fp);
fputs("Neumann\n", fp);
fputs("Church\n", fp);
rewind(fp);
// 读取文件,打印出匹配的行
int index = 0;
int is_same = 1;
const int buf_size = 10; // 文件名最长为9个字符
// char buf_get[buf_size] = argv[1]; // 存储读入的第二个字符串
char buf_file[buf_size];
for (int j = 0; j < buf_size; ++j)
{
buf_file[j] = '\0';
}
int c; // note: int, not char, required to handle EOF
index = 0;
while ((c = fgetc(fp)) != EOF) // standard C I/O file reading loop
{
// putchar(argv[1][index]);
buf_file[index] = c;
// 朴素模式串匹配,跳过了换行符和问号,包括了问号的功能
if ((c != argv[1][index]) && (c != '\n') && ('?' != argv[1][index]))
{
is_same = 0;
}
// 一行结束
if (c == '\n')
{
// (1 == is_same)?puts(" ok"): puts(" no");
if (1 == is_same)
{
puts(buf_file);
}
// 变量重置
index = -1; // index要等于-1因为后面要++
is_same = 1;
for (int j = 0; j < buf_size; ++j)
{
buf_file[j] = '\0';
}
}
// putchar(c);
++index;
}
// putchar('a');
if (ferror(fp))
{
puts("I/O error when reading");
}
else if (feof(fp))
{
puts("End of file reached");
is_ok = EXIT_SUCCESS;
}
fclose(fp);
remove(fname);
return is_ok;
}

1
ex26/guy.txt Normal file
View File

@ -0,0 +1 @@
hello, guys

1
ex26/smart.txt Normal file
View File

@ -0,0 +1 @@
you are smart

1
ex26/zedshaw.txt Normal file
View File

@ -0,0 +1 @@
are you zedshaw

1
ex26/zedshawsmartguy.txt Normal file
View File

@ -0,0 +1 @@
zedshaw is a smart guy

6
ex27/Makefile Normal file
View File

@ -0,0 +1,6 @@
CFLAGS=-Wall
all: ex27_1
clean:
rm -f ex27_1

30
ex27/dbg.h Normal file
View File

@ -0,0 +1,30 @@
#ifndef __dbg_h__
#define __dbg_h__
#include <stdio.h>
#include <errno.h>
#include <string.h>
#ifdef NDEBUG
#define ZED_DEBUG_MACRO(M, ...)
#else
#define ZED_DEBUG_MACRO(M, ...) fprintf(stderr, "DEBUG %s:%d: " M "\n", __FILE__, __LINE__, ##__VA_ARGS__)
#endif
#define ZED_CLEAN_ERRNO_MACRO() (errno == 0 ? "None" : strerror(errno))
#define ZED_LOG_ERR_MACRO(M, ...) fprintf(stderr, "[ERROR] (%s:%d: errno: %s) " M "\n", __FILE__, __LINE__, ZED_CLEAN_ERRNO_MACRO(), ##__VA_ARGS__)
#define ZED_LOG_WARN_MACRO(M, ...) fprintf(stderr, "[WARN] (%s:%d: errno: %s) " M "\n", __FILE__, __LINE__, ZED_CLEAN_ERRNO_MACRO(), ##__VA_ARGS__)
#define ZED_LOG_INFO_MACRO(M, ...) fprintf(stderr, "[INFO] (%s:%s:%d) " M "\n", __FUNCTION__, __FILE__, __LINE__, ##__VA_ARGS__)
#define ZED_CHECK_MACRO(A, M, ...) if(!(A)) {ZED_LOG_ERR_MACRO(M, ##__VA_ARGS__); errno=0; goto error;}
#define ZED_SENTINEL_MACRO(M, ...) {ZED_LOG_ERR_MACRO(M, ##__VA_ARGS__); errno=0; goto error;}
#define ZED_CHECK_MEM(A) ZED_CHECK_MACRO((A), "Out of memory.")
#define ZED_CHECK_DEBUG_MACRO(A, M, ...) if(!(A)) {ZED_DEBUG_MACRO(M, ##__VA_ARGS__); errno=0; goto error;}
#endif

BIN
ex27/ex27_1 Normal file

Binary file not shown.

81
ex27/ex27_1.c Normal file
View File

@ -0,0 +1,81 @@
#undef NDEBUG
#include "dbg.h"
#include <stdio.h>
#include <assert.h>
/*
* Naive copy that assumes all inputs are always valid
* taken from K&R C and cleaned up a bit.
*/
void copy(char to[], char from[])
{
int i = 0;
// while loop will not end if from isn't '\0' terminated
while ((to[i] = from[i]) != '\0')
{
++i;
}
}
/*
* A safer version that checks for many common errors using the
* length of each string to control the loops and termination.
*/
int safercopy(int from_len, char *from, int to_len, char *to)
{
assert(from != NULL && to != NULL && "from and to can't be NULL");
int i = 0;
int max = from_len > to_len - 1 ? to_len - 1 : from_len;
// to_len must have at least 1 byte
if (from_len < 0 || to_len <= 0)
{
return -1;
}
for (i = 0; i < max; ++i)
{
to[i] = from[i];
}
to[to_len - 1] = '\0';
return 1;
}
int main(int argc, char *argv[])
{
// careful to understand why we can get these sizes
char from[] = "0123456789";
int from_len = sizeof(from);
// notice that it's 7 chars + \0
char to[] = "0123456";
int to_len = sizeof(to);
ZED_DEBUG_MACRO("Copying '%s':%d to '%s':%d", from, from_len, to, to_len);
int rc = safercopy(from_len, from, to_len, to);
ZED_CHECK_MACRO(rc > 0, "Failed to safercopy.");
ZED_CHECK_MACRO('\0' == to[to_len - 1], "String not terminated.");
ZED_DEBUG_MACRO("Result is: '%s':%d", to, to_len);
// now try to break it
rc = safercopy(from_len * -1, from, to_len, to);
ZED_CHECK_MACRO(-1 != rc, "safercopy should fail #1");
// printf("rc:%d", rc);
ZED_CHECK_MACRO('\0' == to[to_len - 1], "String not terminated.");
rc = safercopy(from_len, from, 0, to);
ZED_CHECK_MACRO(-1 == rc, "safercopy should fail #2");
ZED_CHECK_MACRO('\0' == to[to_len - 1], "String not terminated.");
return 0;
error:
return 1;
}

0
ex29/c-skeleton/LICENSE Normal file
View File

54
ex29/c-skeleton/Makefile Normal file
View File

@ -0,0 +1,54 @@
CFLAGS=-g -O2 -Wall -Wextra -Isrc -rdynamic -DNDEBUG $(OPTFLAGS)
LIBS=-ldl $(OPTLIBS)
PREFIX?=/usr/local
SOURCES=$(wildcard src/**/*.c src/*.c)
OBJECTS=$(patsubst %.c,%.o,$(SOURCES))
TEST_SRC=$(wildcard tests/*_tests.c)
TESTS=$(patsubst %.c,%,$(TEST_SRC))
TARGET=build/libex29.a
SO_TARGET=$(patsubst %.a,%.so,$(TARGET))
# The Target Build
all: $(TARGET) $(SO_TARGET) tests
dev: CFLAGS=-g -Wall -Isrc -Wall -Wextra $(OPTFLAGS)
dev: all
$(TESTS): $(TARGET) $(SO_TARGET)
$(TARGET): CFLAGS += -fPIC
$(TARGET): build $(OBJECTS)
ar rcs $@ $(OBJECTS)
ranlib $@
$(SO_TARGET): $(TARGET) $(OBJECTS)
$(CC) -shared -o $@ $(OBJECTS)
build:
@mkdir -p build
@mkdir -p bin
# The Unit Tests
.PHONY: tests
tests: CFLAGS += $(TARGET)
tests: $(TESTS)
sh ./tests/runtests.sh
# The Cleaner
clean:
rm -rf build $(OBJECTS) $(TESTS)
rm -f tests/tests.log
find . -name "*.gc*" -exec rm {} \;
rm -rf 'find . -name "*.dSYM" -print'
# The Install
install: all
install -d $(DESTDIR)/$(PREFIX)/lib/
indtall $(TARGET) $(DESTDIR)/$(PREFIX)/lib/
# The Checker
check:
@echo Files with potentially dangerous functions.
@egrep '[^_.>a-zA-Z0-9](str(n?cpy|n?cat|xfrm|n?dup|str|pbrk|tok|_)|stpn?cpy|a?sn?printf|byte_)' $(SOURCES) || true

View File

Binary file not shown.

Binary file not shown.

30
ex29/c-skeleton/src/dbg.h Normal file
View File

@ -0,0 +1,30 @@
#ifndef __dbg_h__
#define __dbg_h__
#include <stdio.h>
#include <errno.h>
#include <string.h>
#ifdef NDEBUG
#define ZED_DEBUG_MACRO(M, ...)
#else
#define ZED_DEBUG_MACRO(M, ...) fprintf(stderr, "DEBUG %s:%d: " M "\n", __FILE__, __LINE__, ##__VA_ARGS__)
#endif
#define ZED_CLEAN_ERRNO_MACRO() (errno == 0 ? "None" : strerror(errno))
#define ZED_LOG_ERR_MACRO(M, ...) fprintf(stderr, "[ERROR] (%s:%d: errno: %s) " M "\n", __FILE__, __LINE__, ZED_CLEAN_ERRNO_MACRO(), ##__VA_ARGS__)
#define ZED_LOG_WARN_MACRO(M, ...) fprintf(stderr, "[WARN] (%s:%d: errno: %s) " M "\n", __FILE__, __LINE__, ZED_CLEAN_ERRNO_MACRO(), ##__VA_ARGS__)
#define ZED_LOG_INFO_MACRO(M, ...) fprintf(stderr, "[INFO] (%s:%s:%d) " M "\n", __FUNCTION__, __FILE__, __LINE__, ##__VA_ARGS__)
#define ZED_CHECK_MACRO(A, M, ...) if(!(A)) {ZED_LOG_ERR_MACRO(M, ##__VA_ARGS__); errno=0; goto error;}
#define ZED_SENTINEL_MACRO(M, ...) {ZED_LOG_ERR_MACRO(M, ##__VA_ARGS__); errno=0; goto error;}
#define ZED_CHECK_MEM(A) ZED_CHECK_MACRO((A), "Out of memory.")
#define ZED_CHECK_DEBUG_MACRO(A, M, ...) if(!(A)) {ZED_DEBUG_MACRO(M, ##__VA_ARGS__); errno=0; goto error;}
#endif

View File

@ -0,0 +1,45 @@
#include <stdio.h>
#include <ctype.h>
#include "dbg.h"
int print_a_message(const char *msg, int length)
{
printf("A STRING: %s\n", msg);
return 0;
}
int uppercase(const char *msg, int length)
{
int i = 0;
// BUG: \0 termination problems
for (i = 0; i < length; ++i)
{
printf("%c", toupper(msg[i]));
}
printf("\n");
return 0;
}
int lowercase(const char *msg, int length)
{
int i = 0;
// BUG: \0 termination problems
for(i = 0; i < length; ++i)
{
printf("%c", tolower(msg[i]));
}
printf("\n");
return 0;
}
int fail_on_purpose(const char *msg, int length)
{
return 1;
}

Binary file not shown.

Binary file not shown.

View File

@ -0,0 +1,60 @@
#include <stdio.h>
#include "dbg.h"
#include <dlfcn.h>
#include <string.h>
#include "minunit.h"
typedef int (*lib_function) (const char *data, int length);
// 注意需要传入lib_file和lib
int check_function(const char *func_to_run, const char *data, int expected, char *lib_file, void *lib)
{
lib_function func = dlsym(lib, func_to_run);
ZED_CHECK_MACRO(func != NULL, "Did not find %s function in the library %s: %s", func_to_run, lib_file, dlerror());
int length = strlen(data);
int rc = func(data, length);
ZED_CHECK_MACRO(expected == rc, "Function %s return %d for data: %s", func_to_run, rc, data);
return 0;
error:
return 1;
}
char *test()
{
char *lib_file = "build/libex29.so";
// printf("lib_file:%s", lib_file);
// test dlopen
void *lib = dlopen(lib_file, RTLD_LAZY);
ZED_MU_ASSERT_MACRO(lib == NULL, "Failed to open the library to test.");
// test functions
ZED_MU_ASSERT_MACRO(check_function("print_a_message", "Hello, Boyang", 0, lib_file, lib), "print_a_message failed.");
ZED_MU_ASSERT_MACRO(check_function("uppercase", "hello, Boyang", 0, lib_file, lib), "uppercase failed.");
ZED_MU_ASSERT_MACRO(check_function("lowercase", "hello, Boyang", 0, lib_file, lib), "lowercase failed.");
// test failures
ZED_MU_ASSERT_MACRO(check_function("fail_on_purpose", "Hello", 1, lib_file, lib), "fail_on_purpose should fail.");
// test dlclose
int rc = dlclose(lib);
ZED_MU_ASSERT_MACRO(0 != rc, "Failed to close lib.");
return NULL;
}
char *all_tests()
{
ZED_MU_SUITE_START_MACRO();
ZED_MU_RUN_TEST(test);
return NULL;
}
ZED_RUN_TESTS_MACRO(all_tests);

View File

@ -0,0 +1,33 @@
#undef NDEBUG
#ifndef _minunit_h
#define _minunit_h
#include <stdio.h>
#include <dbg.h>
#include <stdlib.h>
#define ZED_MU_SUITE_START_MACRO() char *message = NULL
#define ZED_MU_ASSERT_MACRO(test, message) if (test) {\
ZED_LOG_ERR_MACRO(message); return message; }
#define ZED_MU_RUN_TEST(test) ZED_DEBUG_MACRO("\n-----%s", " " #test); \
message = test(); ++tests_run; if (message) return message;
#define ZED_RUN_TESTS_MACRO(name) int main(int argc, char *argv[]) {\
ZED_DEBUG_MACRO("----- RUNNING: %s", argv[0]); \
printf("----\nRUNNING: %s\n", argv[0]); \
char *result = name(); \
if (result != 0) { \
printf("FAILED: %s\n", result); \
} \
else { \
printf("ALL TESTS PASSED\n"); \
} \
printf("Tests run: %d\n", tests_run); \
exit(result != 0); \
}
int tests_run;
#endif

View File

@ -0,0 +1,19 @@
echo "Running unit tests:"
for i in tests/*_tests
do
if test -f $i
then
if $VALGRIND ./$i 2>> tests/tests.log
then
echo $1 PASS
else
echo "ERROR in test $i: here's tests/tests.log"
echo "------"
tail tests/tests.log
exit 1
fi
fi
done
echo ""

View File

30
ex29/dbg.h Normal file
View File

@ -0,0 +1,30 @@
#ifndef __dbg_h__
#define __dbg_h__
#include <stdio.h>
#include <errno.h>
#include <string.h>
#ifdef NDEBUG
#define ZED_DEBUG_MACRO(M, ...)
#else
#define ZED_DEBUG_MACRO(M, ...) fprintf(stderr, "DEBUG %s:%d: " M "\n", __FILE__, __LINE__, ##__VA_ARGS__)
#endif
#define ZED_CLEAN_ERRNO_MACRO() (errno == 0 ? "None" : strerror(errno))
#define ZED_LOG_ERR_MACRO(M, ...) fprintf(stderr, "[ERROR] (%s:%d: errno: %s) " M "\n", __FILE__, __LINE__, ZED_CLEAN_ERRNO_MACRO(), ##__VA_ARGS__)
#define ZED_LOG_WARN_MACRO(M, ...) fprintf(stderr, "[WARN] (%s:%d: errno: %s) " M "\n", __FILE__, __LINE__, ZED_CLEAN_ERRNO_MACRO(), ##__VA_ARGS__)
#define ZED_LOG_INFO_MACRO(M, ...) fprintf(stderr, "[INFO] (%s:%s:%d) " M "\n", __FUNCTION__, __FILE__, __LINE__, ##__VA_ARGS__)
#define ZED_CHECK_MACRO(A, M, ...) if(!(A)) {ZED_LOG_ERR_MACRO(M, ##__VA_ARGS__); errno=0; goto error;}
#define ZED_SENTINEL_MACRO(M, ...) {ZED_LOG_ERR_MACRO(M, ##__VA_ARGS__); errno=0; goto error;}
#define ZED_CHECK_MEM(A) ZED_CHECK_MACRO((A), "Out of memory.")
#define ZED_CHECK_DEBUG_MACRO(A, M, ...) if(!(A)) {ZED_DEBUG_MACRO(M, ##__VA_ARGS__); errno=0; goto error;}
#endif

BIN
ex29/ex29 Normal file

Binary file not shown.

36
ex29/ex29.c Normal file
View File

@ -0,0 +1,36 @@
#include <stdio.h>
#include "dbg.h"
#include <dlfcn.h>
#include <string.h>
typedef int (*lib_function) (const char *data, int length);
int main(int argc, char *argv[])
{
int rc = 0;
ZED_CHECK_MACRO(4 == argc, "USAGE: ex29 libex29.so function data");
char *lib_file = argv[1];
char *func_to_run = argv[2];
char *data = argv[3];
int length = strlen(argv[3]);
void *lib = dlopen(lib_file, RTLD_NOW);
ZED_CHECK_MACRO(lib != NULL, "Failed to open the library %s: %s", lib_file, dlerror());
lib_function func = dlsym(lib, func_to_run);
ZED_CHECK_MACRO(func != NULL, "Did not find %s function in the library %s: %s", func_to_run, lib_file, dlerror());
rc = func(data, length);
ZED_CHECK_MACRO(0 == rc, "Function %s return %d for data: %s", func_to_run, rc, data);
rc = dlclose(lib);
ZED_CHECK_MACRO(0 == rc, "Failed to close %s", lib_file);
return 0;
error:
return 1;
}

45
ex29/libex29.c Normal file
View File

@ -0,0 +1,45 @@
#include <stdio.h>
#include <ctype.h>
#include "dbg.h"
int print_a_message(const char *msg, int length)
{
printf("A STRING: %s\n", msg);
return 0;
}
int uppercase(const char *msg, int length)
{
int i = 0;
// BUG: \0 termination problems
for (i = 0; i < length; ++i)
{
printf("%c", toupper(msg[i]));
}
printf("\n");
return 0;
}
int lowercase(const char *msg, int length)
{
int i = 0;
// BUG: \0 termination problems
for(i = 0; i < length; ++i)
{
printf("%c", tolower(msg[i]));
}
printf("\n");
return 0;
}
int fail_on_purpose(const char *msg, int length)
{
return 1;
}

BIN
ex29/libex29.o Normal file

Binary file not shown.

BIN
ex29/libex29.so Normal file

Binary file not shown.

0
ex32/liblcthw/LICENSE Normal file
View File

Some files were not shown because too many files have changed in this diff Show More