LINUX系统下的云词典,实现单词查询,用户管理,历史记录查询等功能

功能展示

1.打印登录界面,未注册用户需先进行注册,若未注册就登陆则会提示用户不存在;

2.注册,若注册时输入的账户信息已存在则会提示用户已存在;

3.登陆;

4.单词查询,按1输入想要查询的单词,输入“#”退出查询;

5.历史记录查询,打印查询的时间及查询内容;

6.退出。

代码实现

服务器

#include "head.h"

int flag = 0;
char str[512] = {0};
int callback(void *buf, int num, char **value, char **name)
{
    flag = 1;
    strcpy(str, value[1]);
    return 0;
}

int main(int argc, char const *argv[])
{

    int sockfd = socket(AF_INET, SOCK_STREAM, 0);                       //建立TCP传输控制协议
    if (socket < 0)
    {
        perror("socket err\n");
        return -1;
    }
    printf("sockfd:%d\n", sockfd);
    struct sockaddr_in saddr, caddr;
    saddr.sin_family = AF_INET;
    saddr.sin_port = htons(atoi(argv[1]));
    saddr.sin_addr.s_addr = inet_addr("0.0.0.0");

    if (bind(sockfd, (struct sockaddr *)&saddr, sizeof(saddr)) < 0)
    {
        perror("bind err\n");
        return -1;
    }
    printf("bind ok\n");

    if (listen(sockfd, 6) < 0)
    {
        perror("listen err\n");
        return -1;
    }
    printf("listen ok\n");
    
    sqlite3 *db;                                                        //打开用户账户表
    if (sqlite3_open("./ydict.db", &db) != SQLITE_OK)
    {
        fprintf(stderr, "open user err %s", sqlite3_errmsg(db));
        return -1;
    }

    int acceptfd, len = sizeof(caddr), ret;
    char buf[128] = {0};
    MSG_t msg;
    char *errmsg = NULL;
    char sql[128] = {0};
    text_t text;
    time_t t;
    struct tm *tm;

    while (1)                                                           //循环接收客户端的连接请求
    {
        acceptfd = accept(sockfd, (struct sockaddr *)&caddr, &len);
        if (acceptfd < 0)
        {
            perror("accept err\n");
            return -1;
        }
        printf("accept ok\n");
        printf("ip:%s  port:%d\n", inet_ntoa(caddr.sin_addr), ntohs(caddr.sin_port));

        sqlite3_exec(db, "delete from history", callback, NULL, &errmsg);

        while (1)                                                         //循环接收客户端注册与登录指令
        {
            flag = 0;
            ret = recv(acceptfd, &msg, sizeof(msg), 0);
            if (msg.type == regis)
            {
                sprintf(sql, "select * from user where name=\"%s\"", msg.name);
                sqlite3_exec(db, sql, callback, NULL, &errmsg);

                if (flag == 1)
                {
                    sprintf(text.buf, "register : user \"%s\" already exist!!!", msg.name);
                    memset(sql, 0, sizeof(sql));
                }
                else
                {
                    sprintf(sql, "insert into user values(\"%s\",\"%s\");", msg.name, msg.password);
                    if (sqlite3_exec(db, sql, NULL, NULL, &errmsg) != SQLITE_OK)
                    {
                        fprintf(stderr, "insert dict err %s\n", errmsg);
                        return -1;
                    }
                    strcpy(text.buf, "register : OK");
                }
                send(acceptfd, &text, sizeof(text), 0);
            }
            if (msg.type == login)
            {
                sprintf(sql, "select * from user where name=\"%s\" and password=\"%s\"", msg.name, msg.password);
                sqlite3_exec(db, sql, callback, NULL, &errmsg);
                if (flag == 1)
                {
                    text.type = right;
                    strcpy(text.buf, "login success");
                    send(acceptfd, &text, sizeof(text), 0);
                    break;
                }
                else
                {
                    strcpy(text.buf, "input error , please try again");
                    send(acceptfd, &text, sizeof(text), 0);
                }
            }

            if (msg.type == quit)
            {
                printf("client quit\n");
            }
        }
        while (1)                                                            //登录后循环接收客户端的操作指令
        {
            recv(acceptfd, &text, sizeof(text), 0);
            if (text.type == query_word)
            {
                flag = 0;
                if (strcmp(text.buf, "#") != 0)
                {
                    time(&t);
                    tm = localtime(&t);
                    sprintf(buf, "%d-%d-%d %d:%d:%d", tm->tm_year + 1900, tm->tm_mon + 1, tm->tm_mday, tm->tm_hour, tm->tm_min, tm->tm_sec);
                    sprintf(sql, "insert into history values(\"%s\",\"%s\");", buf, text.buf);
                    sqlite3_exec(db, sql, NULL, NULL, &errmsg);

                    sprintf(sql, "select * from dict where word=\"%s\"", text.buf);
                    sqlite3_exec(db, sql, callback, NULL, &errmsg);
                    if (flag == 1)
                        strcpy(text.buf, str);
                    else
                        strcpy(text.buf, "input error , please try again");
                    send(acceptfd, &text, sizeof(text), 0);
                }
            }
            if (text.type == history_record)
            {
                char **result = NULL;
                int row, column, k = 0;
                sqlite3_get_table(db, "select * from  history;", &result, &row, &column, &errmsg);
                while (k <= (row * column))
                {
                    sprintf(buf, "%s : %s", result[k], result[k + 1]);
                    k += column;
                    send(acceptfd, buf, sizeof(buf), 0);
                }
                send(acceptfd, "over", sizeof(buf), 0);
            }
            if (msg.type == quit)
            {
                printf("client quit\n");
                break;
            }
        }
    }
    return 0;
}

客户端

#include "head.h"

int main(int argc, char const *argv[])
{
    int sockfd = socket(AF_INET, SOCK_STREAM, 0);              //建立tcp传输控制协议
    if (sockfd < 0)
    {
        perror("sockfd err\n");
        return -1;
    }

    struct sockaddr_in saddr, caddr;
    saddr.sin_family = AF_INET;
    saddr.sin_port = htons(atoi(argv[1]));
    saddr.sin_addr.s_addr = inet_addr("输入服务器网络地址");

    if (connect(sockfd, (struct sockaddr *)&saddr, sizeof(saddr)) < 0)        //与服务器连接
    {
        perror("connect err\n");
        return -1;
    }

    int num;
    MSG_t msg;
    char buf[128] = {0};
    text_t text;
    while (1)
    {
        printf("**********************************\n");
        printf("* 1: register  2: login  3: quit *\n");
        printf("**********************************\n");
        printf("please input your choice: ");
        scanf("%d", &num);                                         //循环输入注册、登录指令进行判断
        switch (num)
        {
        case 1:
            msg.type = regis;
            printf("input name:");
            scanf("%s", msg.name);
            printf("input password:");
            scanf("%s", msg.password);
            send(sockfd, &msg, sizeof(msg), 0);
            break;

        case 2:
            msg.type = login;
            printf("input name:");
            scanf("%s", msg.name);
            printf("input password:");
            scanf("%s", msg.password);
            send(sockfd, &msg, sizeof(msg), 0);
            break;
        case 3:
            msg.type = quit;
            send(sockfd, &msg, sizeof(msg), 0);
            return 0;
        }
        recv(sockfd, &text, sizeof(text), 0);
        printf("%s\n", text.buf);
        putchar(10);
        if (text.type == right)
            break;
    }
    while (1)                                                     //登录后循环输入操作指令
    {
        printf("*********************************************\n");
        printf("* 1: query_word  2: history_record  3: quit *\n");
        printf("*********************************************\n");
        printf("please input your choice: ");

        scanf("%d", &num);
        putchar(10);
        switch (num)
        {
        case 1:
            while (1)
            {
                text.type = query_word;                            //单词查询
                printf("input word(# to quit) : ");
                scanf("%s", text.buf);
                send(sockfd, &text, sizeof(text), 0);
                if (strcmp(text.buf, "#") == 0)
                    break;
                else
                {
                    recv(sockfd, &text, sizeof(text), 0);
                    printf("%s\n", text.buf);
                    putchar(10);
                }
            }
            break;
        case 2:
            text.type = history_record;                            //历史记录查询
             send(sockfd, &text, sizeof(text), 0);
             while (1)
             {
                 recv(sockfd,buf,sizeof(buf),0);
                 if (strcmp(buf,"over")==0)
                     break;
                 printf("%s\n",buf);
             }
            break;
        case 3:
            msg.type = quit;                                        //登出
            send(sockfd, &msg, sizeof(msg), 0);
            printf("bye~~\n");
            return 0;
            break;
        }
        putchar(10);
    }

    return 0;
}

head.h

#ifndef __HEAD_H__
#define __HEAD_H__

#include <stdio.h>
#include <sys/types.h> 
#include <sys/socket.h>
#include <sys/stat.h>
#include <sys/time.h>
#include <netinet/in.h>
#include <netinet/ip.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <string.h>
#include <stdlib.h>
#include <fcntl.h>
#include <signal.h>
#include <poll.h>
#include <sqlite3.h>
#include <time.h>

//消息对应的结构体
typedef struct msg_t
{
    int type;       
    char name[32]; 
    char password[128]; 
} MSG_t;

typedef struct TEXT
{
    int type;       
    char buf[128]; 
} text_t;

enum un
{
    regis,
    login,
    quit,
    query_word,
    history_record,
    error,
    right,

};

#endif

单词文本导入数据库

#include <stdio.h>
#include <sqlite3.h>

int callback(void *buf, int num, char **value, char **name);

int main(int argc, char const *argv[])
{
    sqlite3 *db;
    // 打开数据库
    if (sqlite3_open("./ydict.db", &db) != SQLITE_OK)
    {
        fprintf(stderr, "open ydict err %s", sqlite3_errmsg(db));
        return -1;
    }
    //操作数据库
    char *errmsg = NULL;
    //创建表
    if (sqlite3_exec(db, "create table history(time char,word char);",
                     NULL, NULL, &errmsg) != SQLITE_OK)
    {
        fprintf(stderr, "create dict err %s\n", errmsg);
        //return -1;
    }
   
    sqlite3_close(db);
    return 0;
}

此外,需要在数据库中创建三个表,分别来储存单词文本,用户信息,历史记录

代码讲解

该云词典的核心内容是sql数据库的操作,表格的建立,数据的插入、删除和查询是支撑辞典运行的关键。

登陆之前,输入账号时在表格中查询该账号是否存在,不存在则反馈信息,若存在且账号密码一致则登陆

登录后进入查询循环,每次查询单词都要将查询时间和单词插入历史表格中,以供查询历史记录使用,时间可以用localtime函数。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值