【C/C++学院】(23)Mysql数据库编程--C语言编程实现mysql客户端_.c_lflag =icanon-程序员宅基地

技术标签: c++  c  c语言  C/C++学院  编程  数据库  


【送给在路上的程序员】

对于一个开发者而言,能够胜任系统中任意一个模块的开发是其核心价值的体现。

对于一个架构师而言,掌握各种语言的优势并可以利运用到系统中,由此简化系统的开发,是其架构生涯的第一步。

对于一个开发团队而言,能够在短期内开发出用户满意的软件系统是其核心竞争力的体现。

每一个程序员都不能固步自封,要多接触新的行业,新的技术领域,突破自我。


makefile

.SUFFIXES: .c .o

CC=gcc
SRCS=mysql1.c\
            mydb.c

OBJS=$(SRCS:.c=.o)
EXEC=mysql1

all: $(OBJS)
    $(CC) -o $(EXEC) $(OBJS) -lmysqlclient
    @echo '-------------ok--------------'

.c.o:
    $(CC) -Wall -g -o $@ -c $< 

clean:
    rm -f $(OBJS)
    rm -f core*

mydb.h

#ifndef MYDB_H_
#define MYDB_H_


void init_db();
int conn_db(const char *hostname, const char *username, const char *password,
        const char *dbname);
void disconn_db();
int open_db(const char *SQL);
int exec_db(const char *SQL);

#endif /* MYDB_H_ */

mydb.c

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <mysql/mysql.h>
#include "mydb.h"

MYSQL *connection = NULL;
MYSQL mysql;

void init_db()
{
    mysql_init(&mysql);//初始化mysql
}

int conn_db(const char *hostname, const char *username, const char *password,
        const char *dbname)
{
    if (connection)
        mysql_close(connection);
    connection = mysql_real_connect(&mysql, hostname, username, password,
            dbname, 0, 0, 0);//连接到mysql

    if (connection == NULL)
    {
        printf("%s\n", mysql_error(&mysql));
        return -1;//连接失败,返回-1
    }

    printf("success connect to mysql\n");
    return 0;
}

void disconn_db()//断开数据库连接
{
    if (connection)
    {
        mysql_close(connection);
        connection = NULL;
    }
}

int open_db(const char *SQL)//执行有返回数据集的SQL语句
{
    int state = mysql_query(connection, SQL);//执行SQL语句
    if (state != 0)
    {
        printf("%s\n", mysql_error(connection));
        return -1;//执行失败,返回-1
    }

    MYSQL_RES *result = mysql_store_result(connection);//得到查询结果
    if (result == (MYSQL_RES *) NULL)
    {
        printf("%s\n", mysql_error(connection));
        return -1;//执行失败,返回-1
    } else
    {
        MYSQL_FIELD *sqlField;
        int iFieldCount = 0;
        while (1)//循环遍历所有字段
        {
            sqlField = mysql_fetch_field(result);
            if (sqlField == NULL)
                break;
            printf("%s\t", sqlField->name);//向屏幕打印字段名
            iFieldCount++;
        }
        printf("\n");//每一行结尾打印一个\n字符

        MYSQL_ROW sqlRow;
        while (1)//循环到每一行
        {
            sqlRow = mysql_fetch_row(result);
            if (sqlRow == NULL)
                break;
            int i;
            for (i = 0; i < iFieldCount; i++)//循环得到每一行中的每个字段
            {
                if (sqlRow[i] == NULL)
                    printf("NULL\t");//如果值为NULL,屏幕打印为"NULL"
                else
                    printf("%s\t", (const char *)sqlRow[i]);//屏幕打印为字段内容
            }
            printf("\n");//每一行结尾打印一个\n字符
        }
        printf("query is ok, %u rows affected\n", (unsigned int)mysql_affected_rows(connection));
        mysql_free_result(result);
    }
    return 0;
}

int exec_db(const char *SQL)//执行没有返回数据集的SQL语句
{
    int state = mysql_query(connection, SQL);//执行SQL语句
    if (state != 0)
    {
        printf("%s\n", mysql_error(connection));
        return -1;
    }
    printf("query is ok, %u rows affected\n", (unsigned int)mysql_affected_rows(connection));
    return 0;
}

mysql1.c

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <sys/types.h>
#include <errno.h>
#include <termios.h>
#include "mydb.h"


void sqldb(const char *src)//参数src为要执行的SQL语句
{
    if ((strncmp(src, "select", 6) == 0) || (strncmp(src, "SELECT", 6) == 0)
            || (strncmp(src, "show", 4) == 0) || (strncmp(src, "SHOW", 4) == 0)
            || (strncmp(src, "desc", 4) == 0) || (strncmp(src, "DESC", 4) == 0))
    {
        open_db(src);//如果src为有返回数据集SQL语句,那么调用open_db函数
    } else
    {
        exec_db(src);//如果src为没有有返回数据集SQL语句,那么调用exec_db函数
    }
}



void work(const char *userid, const char *password)
{
    init_db();
    if (conn_db("localhost", userid, password, "test") != 0)//连接到数据库
    {
        return;//连接数据库失败,函数退出
    }
    char buf[2048];
    while (1)//循环从键盘读取
    {
        write(STDOUT_FILENO, "mysql1>", strlen("mysql1>"));//屏幕输出命令提示符mysql1>
        memset(buf, 0, sizeof(buf));
        read(STDIN_FILENO, buf, sizeof(buf));//等待用户从键盘输入
        if (strncmp(buf, "quit", 4) == 0)
            break;//用户输入quit,循环break;
        sqldb(buf);
    }
    disconn_db();//断开数据库连接
}


struct termios oldterm;
void setstty()//设置输入退格键,不回显
{
    //system("stty erase ^H");//执行shell命令,也可以 用来设置读取用户键盘输入的时候,退格键不回显
    struct termios term;
    if(tcgetattr(STDIN_FILENO, &term) == -1)//得到系统termion的设置
    {
        printf("tcgetattr error is %s\n", strerror(errno));
        return;
    }

    oldterm = term;//保留当前termios设置,以便程序退出的时候可以恢复termios

    /*
    term.c_lflag &= ~ICANON;//取消ICANON选项(不规范输入)
    term.c_lflag |= ICANON;//设置ICANON选项(规范输入)
    term.c_cc字段为要设置的具体特殊输入字符,如c_cc[VERASE]代表退格键,
    term.c_cc[VERASE] = '\b';意思为把退格键修改为'\b'
    VERASE代表向前擦出一个字符,VINTR代表发送ctrl + C中断信号,ctrl + c的ASCII码为3
    例如:term.c_cc[VINTR] = '\t';意思为将tab键设置为终端信号
    tcsetattr中,第二个参数说明,TCSAFLUSH:发送了所有输出后更改才生效,在更改发生时,未读取的所有输入数据都被删除
    TCSANOW:更改立即生效
    TCSADRAIN:发送了所有输出后更改才发生,如果更改输出参数则应该使用该选项
    */
    term.c_cc[VERASE] = '\b';//'\b'为退格键的ASCII码
    if (tcsetattr(STDIN_FILENO, TCSANOW, &term) == -1)//设置系统termion
    {
        printf("tcsetattr error is %s\n", strerror(errno));
    }
    return;
}

void returnstty()//恢复系统的termios设置
{
    if (tcsetattr(STDIN_FILENO, TCSAFLUSH, &oldterm) == -1)//设置系统termion
    {
        printf("tcsetattr error is %s\n", strerror(errno));
    }
    return;
}


int main(int arg, char *args[])
{
    if (arg < 4)//如果没有参数,main函数退出
    {
        return EXIT_FAILURE;
    }

    if (strncmp(args[1], "-u", 2) != 0)//如果第二个参数不是-u,main函数退出
    {
        return EXIT_FAILURE;
    }

    if (strncmp(args[3], "-p", 2) != 0)//如果第四个参数不是-p,main函数退出
    {
        return EXIT_FAILURE;
    }

    const char *passwd = getpass("please input password:");//输入密码,屏幕不回显

    setstty();//设置输入退格键,不回显
    work(args[2], passwd);
    returnstty();//恢复系统的termios设置
    return EXIT_SUCCESS;
}


|========== 吴英强程序员宅基地专栏==========|

|== C/C++学院 专栏文章的内容(不定期更新)===|

|== linux驱动开发 探索linux底层的奥秘 ========|

|== Java基础学习篇 掌握java语言的基础知识=====|

|====== 每天进步一点点,健康快乐每一天 ======|

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/waldmer/article/details/46680783

智能推荐

STL_算法_查找算法(find、find_if)_for ( ; first != last; ++first ) if ( value == *fi-程序员宅基地

文章浏览阅读4k次。C++ Primer 学习中。。。 简单记录下我的学习过程 (代码为主) find 、 find_if /**********************线性查找O(n)find();find_if();注意: 1.如果是已序区间,可以使用区间查找算法 2.关联式容器(set,map)有等效的成员函数find();时间复杂度O(log(_for ( ; first != last; ++first ) if ( value == *first ) return first; return

OpenStack 常用指令 --Neutron_neutron floatingip-list-程序员宅基地

文章浏览阅读3.8k次,点赞2次,收藏11次。个人总结neutron常用指令_neutron floatingip-list

b端 ux 设计思维_借助系统思维从视觉设计过渡到UX-程序员宅基地

文章浏览阅读279次。b端 ux 设计思维“How can I switch to UX?” This is a common question from visual designers because there’s a lot of overlap on the surface. But it can also be a difficult transition since UX encompasses much..._复杂系统的ux设计

php使用redis安装步骤,Windows下安装Redis、PHP安装Redis,PHP使用redis教程!-程序员宅基地

文章浏览阅读407次。【温馨提示】源码包解压密码:www.youhutong.comwindows下安装redis、PHP安装redis,PHP使用redis教程:1、下载redis和PHP扩展包:文章底部有下载连接!2、开始安装:1》安装redis:1、把下载下来的安装包解压到:(解压到什么地方都行)有32位的和64位,这个看你电脑操作系统!2、启动redis,测试redis:1、打开cmd命令进入到redis目录下..._phpstudy_pro启动redis

闽江学院c语言期末试卷,2008—2009学年第1学期闽江学院考试试卷(A)-程序员宅基地

文章浏览阅读175次。D)静态数据成员可以直接用类名调用14、下面对于友元函数描述正确的是A)友元函数的实现必须在类的内部定义B)友元函数是类的成员函数C)友元函数破坏了类的封装性和隐藏性D)友元函数不能访问类的私有成员15、在公有派生情况下,有关派生类对象和基类对象的关系,下列叙述不正确的是A)派生类的对象可以赋给基类的对象B)派生类的对象可以初始化基类的引用C)派生类的对象可以直接访问基类中的成员D)派生类的对象的..._闽江学院公共课c语言期末试卷

【学习笔记】操作系统&计算机网络&Linux运维&常用组件_常见linux运维组件-程序员宅基地

文章浏览阅读204次。【学习笔记】操作系统&计算机网络&Linux运维&常用组件_常见linux运维组件

随便推点

JAVAResource leak: 'sc' is never closed-程序员宅基地

文章浏览阅读916次。Resource leak: ‘sc’ is never closed这句话翻译一下“资源泄露:sc没有关”因为我输入的时候一般会喜欢用Scanner这种方法,用的话会先定义Scanner sc= new Scanner(System.in);但是就出现了这个问题怎么解决呢sc.close();把他关了就好了..._resource leak: 'sc' is never closed

CSDN—Markdown编辑器之如何插入emoji表情_csdn中如何 插入表情包-程序员宅基地

文章浏览阅读733次,点赞7次,收藏8次。  日常写博客时候总是忍不住想要加个表情包来更好的表达个人感情色彩,以前都是用这种:“O(∩_∩)O哈哈~”、“o(╥﹏╥)o”,但是这种表情包太少而且总觉得用着不怎么舒服,于是去网上一搜,搜出来一堆,开心得不得了????先分别附上两款表情包官网第一种????:https://www.webfx.com/tools/emoji-cheat-sheet/这个网站的表情包是这种类型(列举仅为一小部分表..._csdn中如何 插入表情包

TCP-Westwood拥塞算法_tcp westwood-程序员宅基地

文章浏览阅读3.1k次,点赞8次,收藏20次。TCP-Westwood在TCP-Reno的基础上增强了窗口控制和退避处理,例如,TCPW发送端监控ACK报文的接收速率,进而估算当前连接可达到的数据发送速率(可用带宽)。当发送端检测到丢包时(超时或者3个重复ACK),发送端根据估算的发送速率设置拥塞窗口大小(cwnd)和慢启动阈值(ssthresh)。不同于TCP-Reno的窗口减半处理,TCP-Westwood避免太过保守的减低窗口操作,TCP-Westwood称此为:Faster-Recovery。与TCP-Reno相比,TCP-Westwood更适_tcp westwood

Power BI——切片器_powerbi切片器横向排列-程序员宅基地

文章浏览阅读1.5k次。一、概念:它是 Power BI Desktop 中的一种画布内视觉筛选器,是一种功能强大的可视化效果,查看报表的任何用户都可使用它按年份或地理位置等特定值来分割数据。_powerbi切片器横向排列

[给 ASP.NET 初学者的话] 不要练功练了三年,才发现自己必须「砍掉重练」!-程序员宅基地

文章浏览阅读80次。以下是文章备份,我的网站在:http://www.dotblogs.com.tw/mis2000lab/我写的原文:[给初学者的话]不要练功练了三年,才发现自己必须「砍掉重练」!http://www.dotblogs.com.tw/mis2000lab/archive/2012/03/15/game_over.aspx我上课的时候,尤其是第一..._asp.net 值不值得学

Redis7---单线程和多线程(一)_redis7 单线程-程序员宅基地

文章浏览阅读1.4k次,点赞2次,收藏3次。对于redis单线程和多线程的讲解。_redis7 单线程