Chinaunix首页 | 论坛 | 博客
  • 博客访问: 337665
  • 博文数量: 82
  • 博客积分: 2602
  • 博客等级: 少校
  • 技术积分: 660
  • 用 户 组: 普通用户
  • 注册时间: 2007-08-10 08:48
文章分类

全部博文(82)

文章存档

2008年(17)

2007年(65)

分类: C/C++

2007-09-13 17:31:29

引言:
编写一个将数据库查询的数据导入指定文件的程序,符合以下要求:
   名字:TransFileFromDBToSYS
    参数:
        -h 数据库所在主机名称或者IP(默认为127.0.0.1)
        -p 数据库监听的端口 (默认为3306)
        -d 数据库名称
        -t 表名称
        -n文件名称字段名(内容二进制存储)
        -m匹配的字段值
        -i 文件内容字段(内容二进制存储)
        -f 转化成的系统文件名称
    注意:如果有多个值,以最后一个为准。如果参数不满足条件,则提示用法并退出。
代码:
 
 

#include<mysql/mysql.h>
#include<stdio.h>
#define BUFSIZE 4096
char *db_host="127.0.0.1";
unsigned int db_port=3306;
char *db_user=NULL;
char *db_passwd=NULL;
char *database=NULL;
char *db_table=NULL;
char *db_field=NULL;
char *db_match_field=NULL;
char *db_match_content=NULL;
char *file_name=NULL;
char buffer[BUFSIZE]={0};
MYSQL *fp;
MYSQL_RES *result;
MYSQL_ROW row;
static void usage(void)
{
        fprintf(stderr,"Usage:\nFunction [-h host][-p port][-d db][-u user][-s passwd][-t ta
ble][-n field][-m match_field][-i match_content][-f file_name]\n"
);
        exit(0);
}
static void deal_with_arg(int argc,char **argv)
{
        int c;
        while(1){
                c=getopt(argc,argv,"h:p:d:u:s:t:n:m:i:f:?");
                if(c==-1)
                        break;
                switch(c){
                        case 'h':db_host=optarg;break;
                        case 'p':db_port=atoi(optarg);break;
                        case 'd':database=optarg;break;
                        case 'u':db_user=optarg;break;
                        case 's':db_passwd=optarg;break;
                        case 't':db_table=optarg;break;
                        case 'n':db_field=optarg;break;
                        case 'm':db_match_field=optarg;break;
                        case 'i':db_match_content=optarg;break;
                        case 'f':file_name=optarg;break;
                        case '?':usage();
                        default:usage();
                }
        }

}
int db_open(char host[],int port,char *user,char *passwd,char *db)
{
        if((fp=mysql_init(NULL))==NULL){
                fprintf(stderr,"[%s][%d]mysql_init failed!\n",__func__,__LINE__);
                return 1;
        }
        fprintf(stderr,"[%s][%d]mysql_init success!\n",__func__,__LINE__);
        if(mysql_real_connect(fp,host,user,passwd,db,port,NULL,0)==NULL){
                fprintf(stderr,"[%s][%d]mysql_connect failed!\n",__func__,__LINE__);
                return 1;
        }
        fprintf(stderr,"[%s][%d]mysql_connect success!\n",__func__,__LINE__);
        return 0;
}
int db_query(MYSQL *fp,char *NeedField,char *TblName,char *MatchFieldName,char*MatchFieldVal
ue)
{ char *query="select %s from %s where %s = \'%s\'";
        char buf[BUFSIZE]={0};
        char *db_state=NULL;
        sprintf(buf, query, NeedField, TblName, MatchFieldName, MatchFieldValue);
        db_state=mysql_stat(fp);
        if(db_state)
                fprintf(stderr,"[%s][%d][%s]mysql_state success\n",__func__,__LINE__,db_stat
e);

        if(mysql_real_query(fp, buf, strlen(buf)) != 0){
                fprintf(stderr,"[%s][%d]mysql_query failed!\n",__func__,__LINE__);
                return 1;
        }
// fprintf(stderr,"[%s][%d]mysql_query success\n",__func__,__LINE__);
        if((result=mysql_store_result(fp))==NULL){
                fprintf(stderr,"[%s][%d]mysql_store_result failed!\n",__func__,__LINE__);
                return 1;
        }
// fprintf(stderr,"[%s][%d]mysql_store_result success!\n",__func__,__LINE__);
        int field_num;
        if((field_num=mysql_num_fields(result))==0){
                fprintf(stderr,"[%s][%d]mysql_field is zero!\n",__func__,__LINE__);
                return 1;
        }
fprintf(stderr,"[%s]query_result:\n",__func__);
        while((row=mysql_fetch_row(result))!=NULL){
                int i;
                for(i=0;i<field_num;++i){
                        printf("%s\t",row[i]);
                        strncpy(buffer,row[i],strlen(row[i]));
                }
                        printf("\n");
        }
        return 0;
}
static int DBToFile(char *buf,int len,char *file)
{
        FILE *fp;
        if(NULL==file){
                fprintf(stderr,"[%s][%d]NO file!\n",__func__,__LINE__);
                return 1;
        }
        if((fp=fopen(file,"w+"))==NULL){
                fprintf(stderr,"[%s][%d]fopen error!\n",__func__,__LINE__);
                return 1;
        }
        if(fwrite(buf,len,1,fp)==0){
                fprintf(stderr,"[%s][%d]fwrite error!\n",__func__,__LINE__);
                return 1;
        }
        fclose(fp);
        return 0;
}
int
main(int argc,char **argv)
{
        deal_with_arg(argc,argv);
// printf("[%s][%d][%s][%s][%s]\n",db_host,db_port,db_user,db_passwd,database);
        if(!(db_user&&db_passwd&&database&&db_table&&db_field&&db_match_field&&db_match_cont
ent)){
                usage();
        }

        if(db_port<0||db_port>65535){
                fprintf(stderr,"[%s][%d]db_port fault!\n",__func__,__LINE__);
                exit(1);
        }
        if(db_open(db_host,db_port,db_user,db_passwd,database)){
                fprintf(stderr,"[%s][%d]db_open error!\n",__func__,__LINE__);
                exit(1);
        }
// fprintf(stderr,"[%s][%d]\n",__func__,__LINE__);
        if(db_query(fp,db_field,db_table,db_match_field,db_match_content)){
                fprintf(stderr,"[%s][%d]db_query error!\n",__func__,__LINE__);
                exit(1);
        }
// fprintf(stderr,"[%s][%d]\n",__func__,__LINE__);
        mysql_free_result(result);
        result=NULL;
        mysql_close(fp);
if(DBToFile(buffer,strlen(buffer),file_name)){
                fprintf(stderr,"[%s][%d]transDBToFile failed!\n",__func__,__LINE__);
                exit(1);
        }
        exit(0);
}

 

总结:

这个程序经过了多次调试,可以在远程PC端使用,在调试过程中注意到了如下问题:

1、全局变量的问题

MYSQL *fp;

......

int db_open(MYSQL *fp,..);

上面这段代码就会导致调用db_open错误,并且参数传递过程也会得不到想要的结果。这个问题具有很大的隐蔽性,我调试了很长时间才发现。

2、字符串指针问题

虽说这是一个比较基础的问题,以前也专门研究过,但在实际应用中还是畏首畏尾,不敢放心大胆的使用。要深刻理解:字符串指针一旦初始化,你就不可以修改其指向的内存的内容,但你可以使其指向另外的内存!内存和内存中的数据要严格分清

      1#include"ourhdr.h"
      2
      3 int
      4 main(void)
      5 {
      6 char *p="abcde";
      7 printf("p1:%s\n",p);
      8 p="xyzm";
      9 printf("p2:%s\n",p);
     10 exit(0);
     11 }

输出结果:p1:abcde

         p2:xyzm 

3、转义字符的问题

对于sql语句中指定列的值在写入内存过程中,不要忽视了“引号”的作用。

char *query="select %s from %s where %s = \'%s\'";

4、mysql与c的API接口函数的返回值的问题

对于接口函数通常会返回指针或者整数:

返回指针的函数返回非NULL指明成功,返回NULL表示出错;

返回整数的函数返回0表示成功,返回非0表示出错。

5、通过gdb调试,发现当出现segment fault时,内核产生一个SIGSEGV无效内存应用信号

在调试过程中,注意在代码的关键地方显示"__func__"和"__LINE__"即函数名和行号,这样可以缩小调试范围,及时发现问题。

6、调试代码是一项枯燥的事情,但这更需要你的冷静与坚持。

7、注释和调试信息是代码中不可或缺的一部分。

注意编译:

(这一段引自http://blog.chinaunix.net/u1/35100/showart_315325.html

gcc -o TransFileFromDBToSYS $(mysql_config --cflags) -g TransFileFromDBToSYS.c $(mysql_config --libs)  

MySQL中有一个特殊的脚本,叫做mysql_config. 它会为你编译MySQL客户端,并连接到MySQL服务器提供有用的信息.你需要使用下面两个选项.
1. --libs 选项 - 连接MySQL客户端函数库所需要的库和选项.

$ mysql_config --libs
输出:

-L/usr/lib64/mysql -lmysqlclient -lz -lcrypt -lnsl -lm -L/usr/lib64 -lssl -lcrypto

2. --cflags 选项 - 使用必要的include文件的选项等等.
$ mysql_config --cflags
输出:

-I/usr/include/mysql -g -pipe -m64 -D_GNU_SOURCE -D_FILE_OFFSET_BITS=64 -D_LARGEFILE_SOURCE -fno-strict-aliasing

 

阅读(1399) | 评论(0) | 转发(0) |
0

上一篇:数据类型

下一篇:一个计算表达式的函数

给主人留下些什么吧!~~