學習筆記,小白可以相互學習,大佬看到能告訴咱理解不對的地方就好了。
數據庫基本概念:
1.數據:能夠輸入計算機並能被計算機程序識別和處理的信息集合
2.數據庫:數據庫是在數據庫管理和控制之下,存放在存儲介質上的數據集合
文件管理階段:
優點:1.數據可長期保存 2.能存儲大量數據
缺點:1.數據冗餘度大,數據一致性和完整性難以維持 2.數據與程序缺乏高度獨立性
數據庫系統階段:
1.數據組織結構化 2.數據冗餘度比較小,易擴充 3.具有較高的數據與程序之間的獨立性 4.統一的數據控制
SQLite有以下特性:
1.零配置----無需安裝和管理配置
2.存儲在單一磁盤文件中的一個完整的數據庫
3.數據庫文件可以再不同字節順序的機器間自由共享
4.支持數據庫大小至2TB
5.足夠小,全部源碼大致3萬行c代碼,250kb
6.比目前流行的大多數數據庫對數據的操作要快
SQLite常用命令介紹
顯示所有命令:sqlite->help
退出sqlite3:sqlite->quit
顯示當前打開的數據庫文件:sqlite->database
顯示數據庫中所有的表名:sqlite->.table
查看錶的結構:sqlite->.schema <table_name>
以下爲SQL命令以;結束
1.創建新表
sqlite->creat table <table_name> (f1 type1,f2 type2,...);
例如:creat table stu(nu Integer,name char,score float);//char 表示字符串,也可用string ,txt
//creat table stu(nu Integer primary key,name char,score float);加了primary key表示nu作爲主鍵,不可重複,不能插入相同主鍵的數據
2.插入(向表中添加新記錄)
insert into <table_name> values(value1,value2,...);
例如:insert into stu values(1,"xiaoli",99);
3.查詢
selete * from <table_name>;//查詢表中所有記錄,例如selete * from stu;
按照指定條件查詢:
selete * from <table_name> where <expression>;
//例如:selete number * from stu where score>60 and number=1;
//selete number,name from stu where score<60;
4.刪除
delete from <table_name> where <expression>;//刪除指定記錄
drop table <table_name>;//刪除表
5.修改(更新表中內容)
update <table_name> set <f1=value1> <f2=value2>...where <expression>;
例如:update stu set name="xiaozhang" ,score=100 where number = 3;
6.在表中添加字段(添加一列)
alter table <table_name> add column <filed> <type> default...;//添加
alter table <table_name> drop column<filed>;//刪除一列
例如:alter table stu add column address char;//address是添加的名稱,char是添加的address的類型
7.在表中刪除字段(刪除一列)
sqlite中不允許刪除字段,通過下面的步驟一樣可以達到同樣的目的
creat table stu1 as select number,name,score from stu;//新建一張表stu1同原來一樣
drop table stu;//刪除原表stu
alter table stu1 rename to stu ;//將表stu1重命名爲stu
SQLite編程接口(編譯時gcc sqlite.c -lsqlite3)
int sqlite3_open(char *filename,sqlite 3 **db);
功能:打開sqlite數據庫
filename:數據庫文件名(UTF-8編碼格式)
db:指向sqlite句柄的指針
返回值:成功:0 失敗:返回錯誤碼(非0值)//ret !=SQLITE_OK判斷否成功返回
int sqlite2_close(sqlite3 *db);
功能:關閉sqlite數據庫
返回值:成功返回0,失敗返回錯誤碼
const char *sqlite3_errmsg(sqlite *db)
功能:存放錯誤信息
返回值:返回錯誤信息
int sqlite3_exec(sqlite3 *db,const char *sql,sqlite3_callback callback,void *,char **errmsg);
功能:執行SQL操作
db:數據庫句柄
sql:SQL語句
callback:回調函數,沒有則爲NULL
errmsg:錯誤信息指針的地址
返回值:成功返回0,石板返回錯誤碼
typedef int(*sqlite3_callback)(void *para,int f_num,char **f_value,char **f_name);
功能:找到每一條記錄自動執行一次回調函數
f_num:記錄中包含的字段數目
f_value:包含每個字段值的指針數組
f_name:包含每個字段名稱的指針數組
返回值:成功0,失敗-1
不使用回調函數執行SQL語句
int sqlite3_get_table(sqlite3 *db,const char *sql,char ***resultp,int *nrow,int ncolumn,char **errmsg);
功能:執行SQL操作
db:數據庫句柄 //打開的數據庫
sql:SQL語句 //要評估的sql
resultp:用來指向sql執行結果的指針 //查詢結果
nrow:滿足條件的記錄的數目 //寫在這裏的結果行號
ncolumn:每條記錄包含的字段數目 //結果列數
errmsg:錯誤信息指針的地址
返回值:成功返回0,失敗返回錯誤碼
/********sqlite.c*********************************/
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <sqlite3.h>
/*
* 何時調用callback函數:表中要要查詢的數據的時候;
* 查詢到有幾條,函數調用幾次;
*/
int callback(void *para, int f_num, char **f_value, char **f_name)
{
int i;
for (i = 0; i < f_num; i++)
printf("%s : %s\n", f_name[i], f_value[i]);
return 0;
}
int main()
{
int ret;
sqlite3 *db;
char *errmsg;
char sql[128];
/* 打開數據庫文件 */
ret = sqlite3_open("my.db", &db);
if (ret != SQLITE_OK) {
fprintf(stderr, "open : %s\n", sqlite3_errmsg(db));
return -1;
}
#if 0
/* 創建表 */
sprintf(sql, "create table stu(nu Integer primary key, name char, score float)");
ret = sqlite3_exec(db, sql, NULL, NULL, &errmsg);
if (ret != SQLITE_OK) {
fprintf(stderr, "create fail : %s\n", errmsg);
return -1;
}
/* 插入數據 */
int nu = 3;
char name[20] = "xiaoli";
float score = 89;
sprintf(sql, "insert into stu values(%d, '%s', %f)", nu, name, score);
ret = sqlite3_exec(db, sql, NULL, NULL, &errmsg);
if (ret != SQLITE_OK) {
fprintf(stderr, "create fail : %s\n", errmsg);
return -1;
}
sleep(10);
/* 修改數據 */
nu = 2;
strcpy(name, "xiaowang");
sprintf(sql, "update stu set name='%s' where nu='%d'", name, nu);
ret = sqlite3_exec(db, sql, NULL, NULL, &errmsg);
if (ret != SQLITE_OK) {
fprintf(stderr, "create fail : %s\n", errmsg);
return -1;
}
/* 查詢數據 */
char test[20];
sprintf(sql, "select * from stu");
ret = sqlite3_exec(db, sql, callback, test, &errmsg);
if (ret != SQLITE_OK) {
fprintf(stderr, "create fail : %s\n", errmsg);
return -1;
}
#endif
char **result;
int row;
int column;
sprintf(sql, "select * from stu");
ret = sqlite3_get_table(db, sql, &result, &row, &column, &errmsg);
if (ret != SQLITE_OK) {
fprintf(stderr, "select fail : %s\n", errmsg);
return -1;
}
printf("row = %d, column = %d\n", row, column);
int i;
int j;
result += column;
#if 1
for (i = 0; i < row; i++) {
for (j = 0; j< column; j++) {
printf("%s ", *result++);
}
printf("\n");
}
#endif
sqlite3_close(db);
}
英英詞典代碼:
/*******server.c*********************************************************************************/
#include<stdio.h>
#include<sys/types.h>
#include<sys/socket.h>
#include<string.h>
#include<arpa/inet.h>
#include<unistd.h>
#include<pthread.h>
#include<sqlite3.h>
#include<time.h>
#include<sys/stat.h>
#include<fcntl.h>
int server_start(int listenfd); //服務器初始化函數
int server_accept(int listenfd); //服務器連接客戶端函數
void *thread_func(void *connfd); //線程的處理函數
int server_register(int connfd); //服務器註冊函數
int server_login(int connfd); //服務器登陸函數
int server_search(int connfd,int l); //服務器搜索單詞函數
int server_history(int connfd,int l); //服務器歷史紀錄傳給客戶端函數
int server_history_write(char *word); //服務器歷史記錄寫入文件函數
int main()
{
int ret;
int listenfd;
listenfd = server_start(listenfd);
if(-1 == ret )
{
printf("server_start failed\n");
return -1;
}
while(1)
{
//建立連接
int connfd;
connfd = server_accept(listenfd);
if(-1 == connfd)
{
printf("server_accept failed\n");
return -1;
}
//採用多線程的方式
pthread_t thread;
ret = pthread_create(&thread,NULL,thread_func,(void *)&connfd);
if (0 != ret)
{
perror("pthread_creat");
close(connfd);
continue;
}
printf("pthread_creat success! connfd\n");
//給線程收屍體,用pthread_join會阻塞
if(0 != pthread_detach(thread))
{
perror("pthread_detach");
close(connfd);
continue;
}
}
return 0;
}
/********************************************************************/
/*******************服務器初始化**************************************/
int server_start(int listenfd)
{
/*1.socket*/
int ret;
listenfd = socket(AF_INET,SOCK_STREAM,0);
if(-1 == listenfd)
{
perror("server->socket");
return -1;
}
printf("created listenfd = %d success\n",listenfd);
/*2.bind*/
struct sockaddr_in addr;
memset(&addr,0,sizeof(struct sockaddr));
addr.sin_family = AF_INET;
addr.sin_port = htons(9999);
addr.sin_addr.s_addr = htonl(INADDR_ANY);
ret = bind(listenfd,(const struct sockaddr *)&addr,sizeof(struct sockaddr_in));
if(-1 == ret)
{
perror("server->bind");
return -1;
}
printf("port: %d \n",htons(addr.sin_port));
/*3.listen*/
ret = listen(listenfd,0);
if(-1 == ret)
{
perror("server->listen");
return -1;
}
printf("listen success\n");
return listenfd;
}
/********************************************************************/
/******************服務器連接************************************/
int server_accept(int listenfd)
{
/*4.accept*/
socklen_t addrlen;
struct sockaddr_in cltaddr;
addrlen = sizeof(socklen_t);
int connfd;
connfd = accept(listenfd,(struct sockaddr *)&cltaddr,&addrlen);
if(-1 == connfd)
{
perror("server->accept");
return -1;
}
printf("connfd = %d\n",connfd);
return connfd;
}
/********************************************************************/
/************線程的處理函數*****************************************/
void *thread_func(void *arg)
{
int connfd = *(int *)arg;
int ret;
int l;
int chause;
char buf[256];
char word[16];
while(1)
{
ret = read(connfd,&chause,sizeof(chause));//接收chause
//printf("chause = %d\n",chause);
if(-1 == ret)
{
perror("server->read");
close(connfd);
pthread_exit(0);
}
switch(chause)
{
case 1:
server_register(connfd);
break;
case 2:
l = server_login(connfd);
break;
case 3:
server_search(connfd,l);
break;
case 4:
server_history(connfd,l);
break;
case 5:
printf("this client quit\n");
close(connfd);
pthread_exit(0);
default:
continue;
}
}
}
/********************************************************************/
/********註冊***********************************/
int server_register(int connfd)
{
char buf[256];
char buf2[256];
int ret;
char name[16];
char mima[16];
char sql[256];
sqlite3 *db;
char *errmsg;
int k = 1;//用來保存註冊是否成功的狀態
memset(sql,0,sizeof(sql));
memset(buf,0,sizeof(buf));
memset(buf2,0,sizeof(buf2));
ret = read(connfd,buf,sizeof(buf));//name
strncpy(name,buf,16);
if(-1 == ret)
{
perror("server_register->read.name");
return -1;
}
ret = read(connfd,buf2,sizeof(buf2));//mima
strncpy(mima,buf2,16);
if(-1 == ret)
{
perror("server_register->read.mima");
return -1;
}
/*打開數據庫文件*/
ret = sqlite3_open("my.db",&db);
if(SQLITE_OK != ret)
{
fprintf(stderr,"open:%s\n",sqlite3_errmsg(db));
return -1;
}
#if 0
/*創建表之前應該判斷下有沒有user這個表,如果有就不創建了*/
sprintf(sql,"create table user(name char primary key,mima Interger)");
ret = sqlite3_exec(db,sql,NULL,NULL,&errmsg);
if(SQLITE_OK != ret)
{
fprintf(stderr,"create:%s\n",errmsg);
return -1;
}
#endif
memset(sql,0,sizeof(sql));
/*插入數據*/
sprintf(sql,"insert into user values('%s','%s')",name,mima);
ret = sqlite3_exec(db,sql,NULL,NULL,&errmsg);
if(SQLITE_OK != ret)
{
k = 0;
fprintf(stderr,"insert:%s\n",errmsg);
ret = write(connfd,&k,sizeof(k));
if(-1 == ret)
{
perror("server_login->write k");
return -1;
}
return -1;
}
ret = write(connfd,&k,sizeof(k));
if(-1 == ret)
{
perror("server_login->write k");
return -1;
}
printf("註冊成功\n");
return 0;
}
/********************************************************************/
/*********登陸********************************/
int server_login(int connfd)
{
int ret;
char buf[16];
char buf2[16];
char sql[256];
char sql1[256];
char name[16];
char mima[16];
char *errmsg;
sqlite3 *db;
memset(buf,0,sizeof(buf));
memset(buf2,0,sizeof(buf2));
memset(sql,0,sizeof(sql));
memset(sql1,0,sizeof(sql1));
ret = read(connfd,buf,sizeof(buf));//name
strncpy(name,buf,16);
if(-1 == ret)
{
perror("server_register->read.name");
return -1;
}
ret = read(connfd,buf2,sizeof(buf2));//mima
strncpy(mima,buf2,16);
if(-1 == ret)
{
perror("server_register->read.mima");
return -1;
}
/*打開數據庫文件*/
ret = sqlite3_open("my.db",&db);
if(SQLITE_OK != ret)
{
fprintf(stderr,"open:%s\n",sqlite3_errmsg(db));
return -1;
}
/*查詢數據*/
char **result;
int row;
int column;
int b = 1;
sprintf(sql,"select * from user where name='%s' and mima='%s'",name,mima);
printf("name = %s,mima=%s\n",name,mima);
ret = sqlite3_get_table(db,sql,&result,&row,&column,&errmsg);
if(SQLITE_OK != ret)
{
fprintf(stderr,"select:%s\n",errmsg);
return -1;
}
if((1 == row))
{
printf("login success\n");
ret = write(connfd,&b,sizeof(b));
if(-1 == ret)
{
perror("server_login->write");
return -1;
}
return 0;
}
else
{
b = 0;
ret = write(connfd,&b,sizeof(b));
if(-1 == ret)
{
perror("server_login->write");
return -1;
}
printf("login fail\n");
return -1;
}
}
/********************************************************************/
/**********搜索*********************************/
int server_search(int connfd,int l)
{
int ret;
char r = '0';
char buf[1024];
char b[256];
char word[64];
memset(buf,0,sizeof(buf));
memset(b,0,sizeof(b));
memset(word,0,sizeof(word));
if(0 != l)
{
printf("please login\n");
return 0;
}
ret = read(connfd,word,sizeof(word));
if(-1 == ret)
{
perror("server_search->read");
return -1;
}
ret = server_history_write(word);///////////////寫入歷史紀錄文檔
if(-1 == ret)
{
printf("history write fail\n");
}
FILE *fp;
fp = fopen("dict.txt","r");
while(1)
{
int i = 0;
int k = 1;
memset(buf,0,sizeof(buf));
if (NULL == fgets(buf,sizeof(buf),fp))
{
break;
}
while(word[i])
{
if(word[i] != buf[i])
{
k = 0;
break;
}
i++;
}
if((k == 1) && (buf[i++] ==' '))
{
ret = write(connfd,buf,strlen(buf));
r = '1';//表示找到這個單詞
if(-1 == ret)
{
perror("server_search->write");
return -1;
}
break;
}
}
//r = 0;//表示沒找到這個單詞
if(r == '0')
{
ret = write(connfd,&r,sizeof(r));
if(-1 == ret)
{
perror("server_serach->noword");
return -1;
}
}
return 0;
}
/********************************************************************/
/***********歷史記錄寫入文件********************************/
int server_history_write(char *word)
{
FILE *fp;
size_t ret;
char buf[64];
memset(buf,0,sizeof(buf));
time_t t;
time(&t);
struct tm *tp = localtime(&t);
int i = 0;
fp = fopen("history.txt","a+");
if(NULL == fp)
{
perror("fopen");
return -1;
}
fprintf(fp,"%2d-%2d %2d:%2d:%2d : ",tp->tm_mon +1,tp->tm_mday,tp->tm_hour,tp->tm_min,tp->tm_sec);
while('\0' != word[i])//word len
{
i++;
}
ret = fwrite(word,i,1,fp);
if(-1 == ret)
{
perror("server_history->write time");
return -1;
}
ret = fwrite("\n",1,1,fp);
if(-1 == ret)
{
perror("server_history->write huanhang");
return -1;
}
fclose(fp);
return 0;
}
/********************************************************************/
/****************歷史紀錄讀出來,傳給服務器 *******************/
int server_history(int connfd,int l)
{
int fd;
char buf[128];
memset(buf,0,sizeof(buf));
int ret;
FILE *fp;
int i = 0;
if(0 != l)
{
return -1;
}
fp = fopen("history.txt","r");
if(NULL == fp)
{
perror("fopen");
return -1;
}
while(NULL != fgets(buf,sizeof(buf),fp))// 獲得行號
{
i++;
}
fclose(fp);
ret = write(connfd,&i,sizeof(i));//發送行號
if(-1 == ret)
{
perror("server_history->line");
return -1;
}
fp = fopen("history.txt","r");
while(NULL != fgets(buf,sizeof(buf),fp))// 發送具體內容
{
ret = write(connfd,buf,sizeof(buf));
if(-1 == ret)
{
perror("server_history->write");
return -1;
}
}
fclose(fp);
return 0;
}
/********client.c******************************************************************************/
#include<stdio.h>
#include<sys/types.h>
#include<sys/socket.h>
#include<string.h>
#include<arpa/inet.h>
#include<unistd.h>
int client_start(int sockfd); //客戶端初始化函數
void client_meau(void); //客戶端菜單函數
int client_register(int sockfd); //客戶端註冊函數
int client_login(int sockfd); //客戶端登陸函數
int client_search(int sockfd,int l); //客戶端搜索單詞函數
int client_history(int sockfd,int l); //客戶端查詢歷史記錄函數
int client_name(int sockfd); //客戶端登陸和註冊輸入名字函數
int client_mima(int sockfd); //客戶端登陸和註冊輸入密碼函數
int main()
{
int ret;
int sockfd;
int chause;
int l = 2;
char buf[256];
sockfd = client_start(sockfd);
if(-1 == sockfd)
{
printf("client_start failed\n");
return -1;
}
while(1)
{
client_meau();
scanf("%d",&chause);
memset(buf,0,sizeof(buf));
ret = write(sockfd,&chause,sizeof(chause));//傳chause給服務器
if(-1 == ret)
{
perror("client->write");
continue;
}
switch(chause)
{
case 1:
client_register(sockfd);
break;
case 2:
l = client_login(sockfd);//用l保存登陸的狀態
break;
case 3:
client_search(sockfd,l);
break;
case 4:
client_history(sockfd,l);
break;
case 5:
return 0;
default:
printf("請選擇正確的選項\n");
continue;
}
}
close(sockfd);
return 0;
}
/*************************************************************/
/***********客戶端********************************************/
int client_start(int sockfd)
{
int ret;
/*1.socket*/
sockfd = socket(AF_INET,SOCK_STREAM,0);
if(-1 == sockfd)
{
perror("server->socket");
return -1;
}
printf("sockfd = %d\n",sockfd);
/*2.connect*/
struct sockaddr_in addr;
memset(&addr,0,sizeof(struct sockaddr));
addr.sin_family = AF_INET;
addr.sin_port = htons(9999);
addr.sin_addr.s_addr = htonl(INADDR_ANY);
ret = connect(sockfd,(const struct sockaddr *)&addr,sizeof(struct sockaddr_in));
if(-1 == ret)
{
perror("server->bind");
return -1;
}
printf("connect success\n");
return sockfd;
}
/*************************************************************/
/**********主菜單******************************************/
void client_meau(void)
{
printf("**********請您選擇要進行的操作****************\n");
printf("----------------------------------------------\n");
printf("| -.-*英英詞典*-.- |\n");
printf("| * __ * |\n");
printf("| |\n");
printf("| 1.用戶註冊 |\n");
printf("| 2.用戶登陸 |\n");
printf("| 3.單詞在線翻譯 |\n");
printf("| 4.歷史記錄查詢 |\n");
printf("| 5.退出 |\n");
printf("| |\n");
printf("----------------------------------------------\n");
printf("\n");
printf("input:");
}
/*************************************************************/
/***********註冊*****************************************/
int client_register(int sockfd)
{
int ret;
int k = 0;// 保存註冊的狀態
ret = client_name(sockfd);
if(-1 == ret)
{
printf("name failed\n");
return -1;
}
ret = client_mima(sockfd);
if(-1 == ret)
{
printf("mima failed\n");
return -1;
}
ret = read(sockfd,&k,sizeof(k));
if(-1 == ret)
{
printf("client_register->read k\n");
return -1;
}
if(k == 1)
{
printf("註冊成功\n");
}
else
{
printf("註冊失敗\n");
}
return 0;
}
int client_name(int sockfd)//name
{
char name;
int ret;
char buf[16];
memset(buf,0,sizeof(buf));
fprintf(stdout,"請輸入帳號:\n");
scanf("%s",buf);
//buf[strlen(buf)-1] = '\0';
if(0 == strlen(buf))
{
printf("name is null\n");
return -1;
}
ret = write(sockfd,buf,sizeof(buf));
if(-1 == ret)
{
perror("client_register->write.name");
printf("failed\n");
return -1;
}
return 0;
}
int client_mima(int sockfd)//mima
{
char mima;
int ret;
char buf[16];
fprintf(stdout,"請輸入密碼\n");
scanf("%s",buf);
//buf[strlen(buf)-1] = '\0';
if(0 == strlen(buf))
{
printf("mima is null\n");
return -1;
}
ret = write(sockfd,buf,sizeof(buf));
if(-1 == ret)
{
perror("client_register->write.mima");
printf("failed\n");
return -1;
}
return 0;
}
/*************************************************************/
/************登陸****************************************/
int client_login(int sockfd)
{
int ret;
char buf[16];
int b = 0;
memset(buf,0,sizeof(buf));
client_name(sockfd);
if(-1 == ret)
{
printf("name failed\n");
return -1;
}
client_mima(sockfd);
if(-1 == ret)
{
printf("mima failed\n");
return -1;
}
ret = read(sockfd,&b,sizeof(b));
if(-1 == ret)
{
perror("client_register->write.mima");
printf("failed\n");
return -1;
}
if(1 == b)
{
printf("login success\n");
return 0;
}
else
{
printf("login fail\n");
return -1;
}
}
/*************************************************************/
/***********搜索************************************/
int client_search(int sockfd,int l)
{
char word[64];
int ret;
char r = '1';
char buf[1024];
memset(word,0,sizeof(word));
memset(buf,0,sizeof(buf));
if(0 != l)
{
printf("please login\n");
return -1;
}
printf("請輸入要搜索的單詞:\n");
scanf("%s",word);
ret = write(sockfd,word,sizeof(word));
if(-1 == ret)
{
perror("client_search->write");
return -1;
}
ret = read(sockfd,buf,sizeof(buf));
if(-1 == ret)
{
perror("client_search->read");
return -1;
}
if('0' == buf[0])
{
printf("no the word\n");
}
else
{
printf("查詢內容:%s\n",buf);
}
return 0;
}
/*************************************************************/
/*************歷史查詢*************************************/
int client_history(int sockfd,int l)
{
char buf[128];
int ret;
int i = 0;
if(0 != l)
{
printf("please login\n");
return -1;
}
ret = read(sockfd,&i,sizeof(i));
if(-1 == ret)
{
perror("client_history->line");
return -1;
}
printf("一共有%3d個歷史數據\n",i);
while(i--)
{
memset(buf,0,sizeof(buf));
ret = read(sockfd,buf,sizeof(buf));
if(-1 == ret)
{
perror("client_history->read");
return -1;
}
printf("%s",buf);
}
printf("\n");
return 0;
}
/**Makefile******************************************************************/
all:
gcc server.c -o server -lpthread -lsqlite3
gcc client.c -o client -lsqlite3
.PHONY:clean
clean:
rm server client