Python SQLite 資料庫教學與範例

本篇 ShengYu 介紹 Python SQLite 資料庫教學與範例。

以下 Python SQLite 資料庫範例大概分為以下幾部份,

  • Python SQLite CREATE 用法與範例
  • Python SQLite INSERT 用法與範例
  • Python SQLite SELECT 用法與範例
  • Python SQLite UPDATE 用法與範例
  • Python SQLite DELETE 用法與範例

這邊先介紹 Python SQLite 最基本的建立 DB 資料庫連線與關閉 DB 資料庫。
例如我要建立 tutorial.db 這個 database 連線,

python3-sqlite3-tutorial-open-db.py
1
2
3
4
5
6
7
8
9
10
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
import sqlite3

con = sqlite3.connect("tutorial.db")
cur = con.cursor()

# ...

con.close()

以上就是最簡單的 Python SQLite 範例,接下來我們來看看 Python SQLite 常見的操作範例。

Read More

Java File 用法與範例

本篇介紹 Java File 用法與範例,Java File 常見用法是用來判斷路徑的檔案是否存在,或者判斷路徑的資料夾是否存在,還可以取得檔案的長度大小、檔案更動日期等等資訊。

Read More

JavaScript onclick event submit form 用法範例

本篇介紹如何在 JavaScript onclick event 事件中用 form.submit() 函式來 submit form 送出表單。

HTML 基本的 submit form 用法

HTML 基本的 submit form 寫法如下,有個 form 標籤,裡面有個 input 標籤 type="submit"

submit-form.html
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
<html>
<head>
<title>Form Submit Example</title>
<!-- Include CSS File Here
<link rel="stylesheet" href="css/xxx.css"/>
-->
<!-- Include JS File Here
<script src="js/xxx.js"></script>
-->
</head>
<body>
<div class="container">
<div class="main">
<h2>Form Submit Example</h2>
<form action="#" method="post" name="form_name" id="form_id" class="form_class" >
<label>Name :</label><input type="text" name="name" id="name" placeholder="Name" />
<label>Email :</label><input type="text" name="email" id="email" placeholder="Valid Email" />
<input type="submit" name="submit_id" id="btn_id" value="Submit"/>
</form>
</div>
</div>
</body>
</html>

Read More

6 種查詢 SQLite 版本的方法

本篇 ShengYu 介紹 6 種查詢 SQLite 版本的方法,分為這幾種方法,

  • sqlite3.h 標頭檔查詢 SQLite 版本
  • C 語言查詢 SQLite 版本
  • Python 查詢 SQLite 版本
  • SQL 語法查詢 SQLite 版本
  • Command 下指令查詢 SQLite 版本
  • 從 database 檔案本身查詢 SQLite 版本

sqlite3.h 標頭檔查詢 SQLite 版本

一種是從 sqlite3.h 標頭檔去看,在 sqlite3.h 搜尋 SQLITE_VERSION 這個定義就可以找到版本號碼了。

sqlite3.h
1
2
3
#define SQLITE_VERSION        "3.40.1"
#define SQLITE_VERSION_NUMBER 3040001
#define SQLITE_SOURCE_ID "2022-12-28 14:03:47 df5c253c0b3dd24916e4ec7cf77d3db5294cc9fd45ae7b9c5e82ad8197f38a24"

C 語言查詢 SQLite 版本

C 語言的話可呼叫 sqlite3_libversion() API, 有時候系統已經有安裝一份 SQLite 的標頭檔了,但是你想用下載的新版的 SQLite,可能會因為你設置不對造成程式跑去連結系統的那一份,這時用呼叫 sqlite3_libversion() API 來看 SQLite 版本就會比較準確知道你是使用哪一份 SQLite,

Read More

C/C++ rand 產生亂數用法與範例

本篇 ShengYu 介紹 C/C++ rand 產生亂數用法與範例。

C/C++ 要使用 rand 的話需要引入的標頭檔 <stdlib.h>,如果要使用 C++ 的標頭檔則是引入 <cstdlib>
rand 函式原型為

1
int rand (void);

rand() 所產生的亂數是一個整數,其值介於 0 到 RAND_MAX 之間,RAND_MAX 的值會是 2147483647,跟 INT_MAX 一樣。

C/C++ rand 用法

rand() 產生 0-9 亂數寫法如下,

1
2
3
4
5
6
7
8
9
10
// g++ cpp-rand.cpp -o a.out
#include <stdio.h>
#include <stdlib.h>
#include <time.h>

int main() {
int n = rand() % 10; // 產生 0-9 亂數
printf("n = %d\n", n);
return 0;
}

結果如下,會發現執行3次的結果亂數都一樣,

1
2
3
4
5
6
$ ./a.out 
n = 3
$ ./a.out
n = 3
$ ./a.out
n = 3

這次我們以時間做為亂數種子,再試看看會變成怎麼樣?

cpp-rand-2.cpp
1
2
3
4
5
6
7
8
9
10
11
12
// g++ cpp-rand-2.cpp -o a.out
#include <stdio.h>
#include <stdlib.h>
#include <time.h>

int main() {
srand(time(NULL)); // 設定時間為亂數種子

int n = rand() % 10; // 產生 0-9 亂數
printf("n = %d\n", n);
return 0;
}

Read More

C/C++ Linux shared memory 與 mmap 用法範例

今天 ShengYu 來介紹 Linux 跨行程通訊 IPC 中的其中一種方式:共享記憶體 Shared Memory 以及 named semaphore,這通常也是 OS (operating system)作業系統或linux系統程式課程中的一部分,以下範例分為生產者 producer 與消費者 consumer,基本上會使用到 mmap 與 shm_open 這幾個函式。

共享記憶體傳遞 string 字串的範例

生產者 producer 寫入 string 字串的範例如下,
這邊的 shm_open 是使用 O_CREAT | O_RDWR 能建立且能讀取寫入,同樣的 mmap 也使用 PROT_READ | PROT_WRITE 能讀取跟寫入。

shm-posix-producer-string.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
// gcc shm-posix-producer-string.c -o produce -lrt && ./produce
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <fcntl.h>
#include <sys/shm.h>
#include <sys/stat.h>
#include <sys/mman.h>
#include <sys/types.h>

void display(char *prog, char *bytes, int n) {
printf("display: %s\n", prog);
for (int i = 0; i < n; i++) {
printf("%02x%c", bytes[i], ((i+1)%16) ? ' ' : '\n');
}
printf("\n");
}

int main() {
const int SIZE = 4096;
const char *name = "OS";
const char *message0= "Studying ";
const char *message1= "Operating Systems ";
const char *message2= "Is Fun!";

int shm_fd;
void *ptr;

/* create the shared memory segment */
shm_fd = shm_open(name, O_CREAT | O_RDWR, 0666);

/* configure the size of the shared memory segment */
ftruncate(shm_fd,SIZE);

/* now map the shared memory segment in the address space of the process */
ptr = mmap(0,SIZE, PROT_READ | PROT_WRITE, MAP_SHARED, shm_fd, 0);
if (ptr == MAP_FAILED) {
printf("Map failed\n");
return -1;
}

/**
* Now write to the shared memory region.
*
* Note we must increment the value of ptr after each write.
*/
char *str = (char *)ptr;
sprintf(str,"%s",message0);
str += strlen(message0);
sprintf(str,"%s",message1);
str += strlen(message1);
sprintf(str,"%s",message2);
str += strlen(message2);
display("prod", ptr, 64);

return 0;
}

Read More

Windows XAMPP 攜帶版安裝教學

本篇 ShengYu 介紹 Windows XAMPP 攜帶版安裝教學,以往要安裝 Apache + MySQL + PHP + Perl 這些環境就花費許久時間,所以出現了 XAMPP 讓開發者快速地建置後端環境,以前 XAMPP 是 Apache + MySQL + PHP + Perl 的縮寫。MySQL 為目前市佔率最高的資料庫系統。因為當初 MySQL 被甲骨文公司收購後,開發者擔心會有後患,像是轉為商用等等,於是社群就 clone 出 MariaDB,所以現在 XAMPP 上使用的是 MariaDB 而非 MySQL。但是這兩個系統幾乎完全相同。現在 XAMPP 則是 Apache + MariaDB + PHP 的縮寫。

XAMPP 到官網 https://www.apachefriends.org/zh_tw/download.html 或者 sourceforge 下載 xampp portable 隨身攜帶版

把解壓縮後的 xampp 資料夾放在硬碟或USB隨身(硬)碟的最上層,例如: C:\xampp 或 E:\xampp。

Read More

C/C++ Linux sem_wait 與 sem_post 用法範例

今天 ShengYu 來介紹 C/C++ Linux sem_wait 與 sem_post 用法範例,Semaphore 跟 Mutex 相比,雖然 Semaphore 同樣可以用來保護 Critical section,不過它更常被用來確保多執行緒的執行順序。在 Semaphore 中是用 sem_wait 減少與 sem_post 增加 Semaphore 號誌,不像是 Mutex 解鎖還需要同一個人解的 owner ship 特性,也就像解鈴還需繫鈴人概念,以下就來看看 sem_wait 與 sem_post 用法範例吧!

sem_wait() 函式原型:

1
int sem_wait(sem_t *sem);

解釋:若 semaphore 為非 0,則 semaphore 值減 1;若 semaphore 為 0,則呼叫此 function 的 thread 會被 block ,直到 semaphore 值大於 0。

sem_post() 函式原型:

1
int sem_post(sem_t *sem);

解釋:對 semaphore 值加 1。

同行程內的 sem_wait() 跟 sem_post() 用法

以下範例是在一個行程內使用 sem_wait() 跟 sem_post(),在 main 函式 會產生 producer 執行緒跟 consumer 執行緒,producer 執行緒負責產生 1-20 之間的亂數並呼叫 insert_item 放入 buffer 中,而 consumer 執行緒負責用 remove_item 來消耗這 中的亂數。

如果 consumer 都沒有消耗任何變數的情況下,在 producer 會因為 sem_wait(&empty) 從初始值 5 一直減 1 直到 0 不能再減的情況下就會被 block 卡住,直到大於 0 為止才會繼續往下執行。

反之,如果 producer 都沒有生產任何變數的情況下,在 consumer 會因為 sem_wait(&full) 從初始值 0 一直減 1 直到 0 不能再減的情況下就會被 block 卡住,直到大於 0 為止才會繼續往下執行。

linux-sem_wait.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
// gcc linux-sem_wait.c -pthread
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <pthread.h>
#include <semaphore.h>

#define BUFFER_SIZE 5
int buffer[BUFFER_SIZE];

pthread_mutex_t mutex;
sem_t empty;
sem_t full;

int insertPointer = 0, removePointer = 0;

void *producer(void *param);
void *consumer(void *param);

void display_int_array(char *prog, int *arr, int n) {
printf("%s: ", prog);
for (int i = 0; i < n; i++) {
printf("%d%c", arr[i], ((i+1)%16) ? ' ' : '\n');
}
printf("\n");
}

int insert_item(int item) {
/* Acquire Empty Semaphore */
sem_wait(&empty);

/* Acquire mutex lock to protect buffer */
pthread_mutex_lock(&mutex);

buffer[insertPointer++] = item;
insertPointer = insertPointer % BUFFER_SIZE;
display_int_array("prod", buffer, BUFFER_SIZE);

/* Release mutex lock and full semaphore */
pthread_mutex_unlock(&mutex);
sem_post(&full);

return 0;
}

int remove_item(int *item) {
/* Acquire Full Semaphore */
sem_wait(&full);

/* Acquire mutex lock to protect buffer */
pthread_mutex_lock(&mutex);

*item = buffer[removePointer];
buffer[removePointer++] = -1;
removePointer = removePointer % BUFFER_SIZE;
display_int_array("cons", buffer, BUFFER_SIZE);

/* Release mutex lock and empty semaphore */
pthread_mutex_unlock(&mutex);
sem_post(&empty);

return 0;
}

int main(int argc, char *argv[]) {
int sleepTime = 10, producerThreads, consumerThreads;

/* Initialize the synchronization tools */
pthread_mutex_init(&mutex, NULL);
sem_init(&empty, 0, BUFFER_SIZE);
sem_init(&full, 0, 0);
srand(time(0));

/* Create the producer and consumer threads */
{
pthread_t tid;
pthread_attr_t attr;
pthread_attr_init(&attr);
pthread_create(&tid, &attr, producer, NULL);
}

{
pthread_t tid;
pthread_attr_t attr;
pthread_attr_init(&attr);
pthread_create(&tid, &attr, consumer, NULL);
}

/* Sleep for user specified time */
sleep(sleepTime);
return 0;
}

void *producer(void *param) {
int random;
int r;

while (1) {
r = rand() % 3;
sleep(r);
random = rand() % 20 + 1;

if (insert_item(random))
fprintf(stderr, "Error");

printf("Producer produced %d \n", random);
}
}

void *consumer(void *param) {
int random;
int r;

while (1) {
r = rand() % 3;
sleep(r);

if (remove_item(&random))
fprintf(stderr, "Error Consuming");
else
printf("Consumer consumed %d \n", random);
}
}

輸出如下,

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
prod: 7 0 0 0 0 
Producer produced 7
cons: -1 0 0 0 0
Consumer consumed 7
prod: -1 14 0 0 0
Producer produced 14
cons: -1 -1 0 0 0
Consumer consumed 14
prod: -1 -1 3 0 0
Producer produced 3
cons: -1 -1 -1 0 0
Consumer consumed 3
prod: -1 -1 -1 8 0
Producer produced 8
cons: -1 -1 -1 -1 0
Consumer consumed 8
prod: -1 -1 -1 -1 10
Producer produced 10
cons: -1 -1 -1 -1 -1
Consumer consumed 10
prod: 10 -1 -1 -1 -1
Producer produced 10

跨行程的 sem_wait() 跟 sem_post() 用法

跨行程的 sem_wait() 跟 sem_post() 用法,用 fork 分離出兩個行程,並在這父行程與子行程兩行程間用共享記憶體傳遞資料,使用 mmap 共享記憶體來當作 mutex,原理跟上述範例類似,只是這是跨行程。

shm_open / ftruncate / mmap 跟 sem_open 這兩種方式都可以成功。

linux-sem_wait-2.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
// gcc linux-sem_wait-2.c -lrt -pthread
#include <semaphore.h>
#include <stdio.h>
#include <errno.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/mman.h>
#include <fcntl.h>

void display(char *prog, char *bytes, int n) {
printf("%s: ", prog);
for (int i = 0; i < n; i++) {
printf("%02x%c", bytes[i], ((i+1)%16) ? ' ' : '\n');
}
printf("\n");
}

int main(int argc, char **argv) {
int fd, i, count = 0,nloop = 2,zero = 0, *ptr;
sem_t *mutex;

int shm;
if ((shm = shm_open("myshm", O_RDWR | O_CREAT, S_IRWXU)) == 0) {
perror("shm_open");
exit(1);
}

if (ftruncate(shm, sizeof(sem_t)) < 0 ) {
perror("ftruncate");
exit(1);
}

if ((mutex = mmap(NULL, sizeof(sem_t), PROT_READ | PROT_WRITE,
MAP_SHARED, shm, 0)) == MAP_FAILED) {
perror("mmap");
exit(1);
}

// open a file and map it into memory
fd = open("tmp.txt",O_RDWR | O_CREAT, S_IRWXU);
write(fd, &zero, sizeof(int));
ptr = mmap(NULL, sizeof(int), PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
close(fd);

/*if ((mutex = sem_open("mysemaphore", O_CREAT, 0644, 1)) == SEM_FAILED) {
perror("semaphore initilization");
exit(1);
}*/

// create, initialize semaphore
if (sem_init(mutex, 1, 1) < 0) {
perror("semaphore initilization");
exit(0);
}

if (fork() == 0) { // child process
for (i = 0; i < nloop; i++) {
sem_wait(mutex);
printf("child entered crititical section: %d\n", (*ptr)++);
display("child", (char *)ptr, 16);
sleep(2);
printf("child leaving critical section\n");
sem_post(mutex);
sleep(1);
}
exit(0);
}

// back to parent process
for (i = 0; i < nloop; i++) {
sem_wait(mutex);
printf("parent entered critical section: %d\n", (*ptr)++);
display("parent", (char *)ptr, 16);
sleep(2);
printf("parent leaving critical section\n");
sem_post(mutex);
sleep(1);
}

return 0;
}

以上就是 C/C++ Linux sem_wait 與 sem_post 用法範例介紹,
如果你覺得我的文章寫得不錯、對你有幫助的話記得 Facebook 按讚支持一下!

其它參考
Semaphores on Linux - sem_init() vs sem_open() - Superpatterns
https://blog.superpat.com/semaphores-on-linux-sem_init-vs-sem_open
在這篇當中提到 shm_open / ftruncate / mmap 跟 sem_open 這兩種方式

其它相關文章推薦
如果你想學習 C++ 相關技術,可以參考看看下面的文章,
C/C++ 新手入門教學懶人包
C/C++ Linux shared memory 與 mmap 用法範例