思维不灵活的我如何学习编程
- 对于我个人而言,面对不熟悉的代码,如何去学习,在我的学习之路上面对的一堆堆的看不懂的东西,英语也不是特别的好,对于我而言,就是通过去对代码的不断去注释,去理解它的用法,去了解这个函数/方法,比如它的返回值是什么,传入的参数是什么类型,等等,在代码处写下自己的理解,(自己怎么想的就怎么写可能效果要好的多),通过对一个个项目的不断注释去提高自己,抄写别人的代码不可耻,去把别人的代码,写作的思路学习到就很好。
- 下面是我通过网络词典的注释理解到的写作思路
头文件
#ifndef com_h
#define com_h
struct msg{
int opt;
//选择 1.注册 2,登录 3.查询 4修改密码 5.查询历史记录
char use_name[16];
//使用者账号
char use_password[16];
//使用者密码
int login_res;
//服务器回应值 0-成功 -1-失败
char resbuf[256];
//回应内容
int look_res;
//单词查询返回 0-成功 -1-失败
int update_res;
//修改密码返回值 0-成功 -1-失败
char find_word[16];
//查询单词
char word_exp[1024];
//单词及注释/解释
int wordlen;
//单词长度
char hisbuf[64];
//历史记录
};
#endif
```c
服务器
#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <string.h>
#include "common.h"
#include <unistd.h>
#include <pthread.h>
#include <sqlite3.h>
#include <stdlib.h>
#include <time.h>
int ser_fd,ser_fd_new; //服务器的主线程和新线程的名字
struct msg ser_msg; //服务器用于接收和发送的空间--使用全局变量,可以避免传参而导致的数据丢失
int ret; //用于作为发送,接收等的返回值
sqlite3 *db; //数据库的地址,通过db去操作数据库
struct my_socket_new{
int socket_new; //产生新的连接去连接新的线程
pthread_t tid; //线程的tid
};
//注册操作
int do_sign(int socket_new)
{
char **ptable = NULL; //表的地址
int nrow,ncol; //行与列
char sqlbuf[128]; //存放sql语句的地方
memset(sqlbuf,0,sizeof(sqlbuf)); //存放前先清空
//截胡printf,将SQL语句放置在sqlbuf中
snprintf(sqlbuf,sizeof(sqlbuf),\
"select *from user where name=\'%s\'",ser_msg.use_name);
ret = sqlite3_open("./dic.db",&db);
if(ret){
printf("open err:%s\n",sqlite3_errmsg(db));
return -1;
} //对数据库进行查询操作,是否被存在
ret = sqlite3_get_table(db,sqlbuf,&ptable,&nrow,&ncol,NULL);
if(ret){
printf("select name err:%s\n",sqlite3_errmsg(db));
return -1;
}
if(nrow){
//行不等于0,查询到相关的信息,说明该用户已经存在
strcpy(ser_msg.resbuf,"this`s user already be used !");
}else{
//如果行的值等于0,说明没有查询到信息,可以插入/注册
strcpy(ser_msg.resbuf,"use name sign success !");
memset(sqlbuf,0,sizeof(sqlbuf));
snprintf(sqlbuf,sizeof(sqlbuf),\
"insert into user (name,password) values (\'%s\',\'%s\')",\
ser_msg.use_name,ser_msg.use_password);
//没有记录,插入客服端的值到数据库中
ret=sqlite3_get_table(db,sqlbuf,&ptable,NULL,NULL,NULL);
if(ret){
printf("intsert into err:%s\n",sqlite3_errmsg(db));
return -1;
}
}
//操作结束,操作结果发给客服端
ret = send(socket_new,&ser_msg, sizeof(ser_msg),0);
if(ret < 0){
perror("insert into send err");
return -1;
}
ret = sqlite3_close(db);
if(ret){
printf("close err:%s\n",sqlite3_errmsg(db));
return -1;
}
return 0;
}
//登录操作
int do_login(int socket_new)
{
char **ptable = NULL; //表的地址
int nrow,ncol; //行与列
char sqlbuf[128]; //存放sql语句的地方
memset(sqlbuf,0,sizeof(sqlbuf)); //存放前先清空
//截胡printf,将SQL语句放置在sqlbuf中
snprintf(sqlbuf,sizeof(sqlbuf),\
"select *from user where name=\'%s\' and password=\'%s\'",\
ser_msg.use_name,ser_msg.use_password);
ret = sqlite3_open("./dic.db",&db);
if(ret){
printf("open err:%s\n",sqlite3_errmsg(db));
return -1;
} //对数据库进行查询操作,是否被存在
ret = sqlite3_get_table(db,sqlbuf,&ptable,&nrow,&ncol,NULL);
if(ret){
printf("select name err:%s\n",sqlite3_errmsg(db));
return -1;
} //没有查询到记录,登录失败
if(nrow == 0){
ser_msg.login_res = -1;
strcpy(ser_msg.resbuf,"login falied !");
}else{ //反之,查询到记录,登录成功
ser_msg.login_res = 0;
strcpy(ser_msg.resbuf,"login success !");
} //数据处理完成,发送结果值客服端
ret=send(socket_new,&ser_msg, sizeof(ser_msg),0);
if(ret<0){
perror("send failed");
return -1;
}
ret = sqlite3_close(db);
if(ret){
printf("close err:%s\n",sqlite3_errmsg(db));
return -1;
}
return 0;
}
//查询单词
int look_word(int socket_new)
{
char cli_word[16]; //用来暂时存放来自客服端的单词
char ser_word[1024]; //用来存放获取到关于单词一整行的内容
FILE *fp;
fp=fopen("./dict.txt","r");
if(fp==NULL){
perror("fopen");
return -1;
}
while(1)
{
//获取文本中每一行
if(fgets(ser_word,sizeof(ser_word),fp) !=NULL)
{
for (int j=0;ser_word[j] !=' ';j++){
cli_word[j]=ser_word[j];
//将单词放置在发给客服端的数组中
}
//判断单词与客服端发送的是否一致
if(strcmp(cli_word,ser_msg.find_word)==0)
{ //将查询到的内容发送给客服端
strcpy(ser_msg.word_exp,ser_word);
//每次查询完之后都要清空,以便于循环查询
memset(cli_word,0,sizeof(cli_word));
memset(ser_word,0,sizeof(ser_word));
ser_msg.look_res = 0; //发送查询结果到客服端
}else{ //由于对比的时候有赋值操作,不一致时也需要清空容器
memset(cli_word,0,sizeof(cli_word));
memset(ser_word,0,sizeof(ser_word));
}
} //查询到空的行,说明关于该单词的内容不存在
else{
ser_msg.look_res = -1;
stpcpy(ser_msg.resbuf,"sorry no find anything !");
} //将查询结果发送给客服端
ret=send(socket_new,&ser_msg, sizeof(ser_msg),0);
if(ret<0){
perror("send failed");
return -1;
}
char **ptable = NULL; //表的地址
int nrow,ncol; //行与列
fclose(fp);
//时间获取
time_t look_time;
char look_time_buf[32]; //存放时间的容器
struct tm *look_tm;
time(&look_time);
look_tm = localtime(&look_time); //获取当前本地时间
snprintf(look_time_buf,sizeof(look_time_buf),"%d-%d-%d %d-%d-%d",look_tm->tm_year+1900,look_tm->tm_mon+1,\
look_tm->tm_mday,look_tm->tm_hour,look_tm->tm_min,look_tm->tm_sec);
//暂时将时间存放在look_time_buf中
char sql_look_record[128]; //存放浏览记录的sq的容器
memset(sql_look_record,0,sizeof(sql_look_record));
snprintf(sql_look_record,sizeof(sql_look_record),\
"intsert into history (name,day,word) values(\'%s\',\'%s\',\'%s\',)",\
ser_msg.use_name,look_time_buf,ser_msg.find_word);
ret=sqlite3_open("./dic.db",&db); //将数据存放在数据的表中
if(ret){
printf("look open err:%s\n",sqlite3_errmsg(db));
return -1;
}
ret = sqlite3_get_table(db,sql_look_record,&ptable,&nrow,&ncol,NULL);
if(ret){
printf("sqlite3_get_table in look err:%s\n",sqlite3_errmsg(db));
return -1;
}
ret = sqlite3_close(db);
if(ret){
printf("close err:%s\n",sqlite3_errmsg(db));
return -1;
}
}
return 0;
}
//修改密码
int update_password(int socket_new)
{
char **ptable = NULL; //表的地址
char sqlbuf[128];
int nrow,ncol; //行与列
memset(sqlbuf,0,sizeof(sqlbuf));
snprintf(sqlbuf,sizeof(sqlbuf), //根据客服端的用户名去寻找对应的那一行
"select *from user where name=\'%s\'",ser_msg.use_name);
ret = sqlite3_open("./dic.db",&db);
if(ret){
printf("update open err:%s\n",sqlite3_errmsg(db));
return -1;
}
ret = sqlite3_get_table(db,sqlbuf,&ptable,&nrow,&ncol,NULL);
if(ret){
printf("sqlite3_get_table in update err:%s\n",sqlite3_errmsg(db));
return -1;
}
if(nrow == 0){ //如果行等于0,则说明没有注册过
ser_msg.update_res = -1;
stpcpy(ser_msg.resbuf,"your name is unreal !!");
}else{ //反之,则是注册过
ser_msg.update_res = 0;
memset(sqlbuf,0,sizeof(sqlbuf));
//更新数据,将密码替换成客服端传来的密码
snprintf(sqlbuf,sizeof(sqlbuf),\
"update user set passwd=\'%s\' where name=\'%s\'",\
ser_msg.use_password,ser_msg.use_name);
ret = sqlite3_get_table(db,sqlbuf,&ptable,&nrow,&ncol,NULL);
if(ret){
printf("update_sqlite3_get_table err:%s\n",sqlite3_errmsg(db));
return -1;
}
}
ret = sqlite3_close(db);
if(ret){
printf("close in update password err:%s\n",sqlite3_errmsg(db));
return -1;
} //更新数据成功,将结果返回至客服端
strcpy(ser_msg.resbuf,"update password success");
ret=send(socket_new,&ser_msg, sizeof(ser_msg),0);
if(ret<0){
perror("send failed");
return -1;
}
return 0;
}
//查看历史记录
int look_history(int socket_new)
{
char hissqlbuf[128]; //装放查询历史记录的sql语句
int nrow,ncol;
char **ptable=NULL;
memset(hissqlbuf,0,sizeof(hissqlbuf)); //遍历历史记录表
snprintf(hissqlbuf,sizeof(hissqlbuf),"select * from history");
ret=sqlite3_open("./dic.db",&db);
if(ret){
printf("open err:%s\n",sqlite3_errmsg(db));
return -1;
}
ret = sqlite3_get_table(db,hissqlbuf,&ptable,&nrow,&ncol,NULL);
if(ret){
printf("sqlite3_get_table err:%s\n",sqlite3_errmsg(db));
return -1;
}
char hisbuf1[128]; //放置查询到的历史记录内容
if(nrow>=5)
{
for(int i=(nrow-5)*ncol;i<(nrow+1)*ncol;i++)
{
snprintf(hisbuf1,sizeof(hisbuf)," %s ",ptable[i]);
strcat(ser_msg.hisbuf,hisbuf1);
if((i+1)%ncol==0){
printf("\n");
strcat(ser_msg.hisbuf,"\n");
}
}
}
else
{
for(int i=0;i<(nrow+1)*ncol;i++)
{
snprintf(hisbuf1,sizeof(hisbuf)," %s ",ptable[i]);
strcat(ser_msg.hisbuf,hisbuf1);
if((i+1)%ncol==0){
printf("\n");
strcat(ser_msg.hisbuf,"\n");
}
}
}
ret=send(socket_new,&ser_msg, sizeof(ser_msg),0);
if(ret<0){
perror("send failed");
return -1;
}
ret = sqlite3_close(db);
if(ret){
printf("close err:%s\n",sqlite3_errmsg(db));
return -1;
}
return 0;
}
//子线程操作/运行函数---对来自客服端的数据进行处理
void *cli_thread_new(void *args)
{
while(1)
{
struct my_socket_new *pnew = args;
ret = recv(ser_fd_new,&ser_msg,sizeof(ser_msg),0);
if(ret < 0){
perror("recv falied");
return NULL;
}else if(ret == 0){ //防止注册完成后客服端没有发生信息导致服务器关闭
printf("wait ....\n");
return NULL;
}
switch(ser_msg.opt)
{
case 1: //注册操作
do_sign(pnew->socket_new);
break;
case 2: //登录操作
do_login(pnew->socket_new);
break;
case 3: //单词查询
look_word(pnew->socket_new);
break;
case 4: //修改密码
update_password(pnew->socket_new);
break;
case 5: //查看历史记录
look_history(pnew->socket_new);
break;
default:
break;
}
}
return NULL;
}
int main()
{
//创建一个套接字/连接
ser_fd=socket(AF_INET,SOCK_STREAM,0);
if(ser_fd<0){
perror("socket create error");
return -1;
}
struct sockaddr_in serv_addr;
serv_addr.sin_family = AF_INET;
serv_addr.sin_port = htons(8888);
serv_addr.sin_addr.s_addr = INADDR_ANY;
// serv_addr.sin_addr.s_addr = inet_addr("127.0.0.1");
//绑定
ret=bind(ser_fd,(struct sockaddr *)&serv_addr,sizeof(serv_addr));
if(ret<0){
perror("bind error");
return -1;
}
//监听
ret=listen(ser_fd,5);
if(ret<0){
perror("listen error");
return -1;
}
struct sockaddr_in cli_addr;
socklen_t clilen=sizeof(cli_addr);
loop:
//新连接
ser_fd_new=accept(ser_fd,(struct sockaddr *)&cli_addr,&clilen);
if(ser_fd_new<0){
perror("accept error");
return -1;
}
printf("serv accept client ip=%s port=%d\n",\
inet_ntoa (cli_addr.sin_addr ), ntohs(cli_addr.sin_port));
//开新的线程
struct my_socket_new *pnew=malloc(sizeof(struct my_socket_new));
pnew->socket_new=ser_fd_new;
ret=pthread_create(&pnew->tid,NULL,cli_thread_new,pnew);
if(ret!=0){
perror("pthread_create");
return -1;
}
goto loop;
close(ser_fd_new);
return 0;
}
客服端
#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <string.h>
#include "common.h"
#include <unistd.h>
#include <pthread.h>
#include <sqlite3.h>
#include <stdlib.h>
#include <time.h>
int cli_fd; //全局套接字变量,可以避免传参出现错误
struct msg climsg; //客服端接收和发送空间
int ret; //用于作为发送,接收等的返回值
void mainshow()
{
printf("~~~~~~~~~~\n");
printf("网络小词典\n");
printf("1:注册账号\n");
printf("2:登录\n");
printf("3:退出\n");
printf("~~~~~~~~~~\n");
}
void sonshow()
{
printf("~~~~~~~~~~\n");
printf("操作选择\n");
printf("1:查询单词\n");
printf("2:查看历史记录\n");
printf("3:修改密码\n");
printf("4:返回主界面\n");
printf("~~~~~~~~~~\n");
}
//注册账号
int do_sign()
{
//发送内容
char sign_name[16];
char sign_password[16];
memset(&climsg,0,sizeof(climsg));
printf("please input your sign name:");
scanf("%s",sign_name);
printf("please input your sign passwd:");
scanf("%s",sign_password);
strcpy(climsg.use_name,sign_name);
strcpy(climsg.use_password,sign_password);
climsg.opt=1;
//发送至服务器
ret=send(cli_fd,&climsg,sizeof(climsg),0);
if(ret<0){
perror("sign msg send error");
return -1;
}
//接收服务器的返回内容
memset(&climsg,0,sizeof(climsg));
ret=recv(cli_fd,&climsg,sizeof(climsg),0);
if(ret<0){
perror("sign msg recv error");
return -1;
}else if(ret==0){
printf("sign find server is close\n");
return -1;
close(cli_fd);
}
//打印返回内容
printf("%s\n",climsg.resbuf);
close(cli_fd);
return 0;
}
//登录操作
int do_login()
{
//发送内容
char login_name[16];
char login_password[16];
memset(&climsg,0,sizeof(climsg));
printf("please input your sign name:");
scanf("%s",login_name);
printf("please input your sign passwd:");
scanf("%s",login_password);
strcpy(climsg.use_name,login_name);
strcpy(climsg.use_password,login_password);
climsg.opt=2;
//发送至服务器
ret=send(cli_fd,&climsg,sizeof(climsg),0);
if(ret<0){
perror("login msg send error");
return -1;
}
//接收服务器的返回内容
memset(&climsg,0,sizeof(climsg));
ret=recv(cli_fd,&climsg,sizeof(climsg),0);
if(ret<0){
perror("login recv error");
return -1;
}else if(ret==0){
printf("login find server is close\n");
return -1;
close(cli_fd);
}
//打印返回内容
printf("%s\n",climsg.resbuf);
close(cli_fd);
return 0;
}
//查询单词
int look_word()
{
char myword[16]; //放置查询的单词
printf("please input you want to look thing:");
scanf("%s",myword);
climsg.wordlen=strlen(myword); //单词的长度赋值
strcpy(climsg.find_word,myword); //单词赋值准备发送
climsg.opt = 3; //操作类型发送至服务器
ret=send(cli_fd,&climsg,sizeof(climsg),0); //send
if(ret<0){
perror("look word send error:");
return -1;
}
ret=recv(cli_fd,&climsg,sizeof(climsg),0); //recv
if(ret<0){
perror("look word recv error:");
return -1;
}else if(ret==0){
printf("looking word server is close\n");
return -1;
}
if(climsg.look_res ==0){ //服务器查询到单词,返回单词的注释
printf("%s",climsg.word_exp);
}else if(climsg.look_res ==-1){ //服务器没有找到
printf("%s",climsg.resbuf);
}
return 0;
}
//查询历史记录
int history()
{
climsg.opt=5;
ret=send(cli_fd,&climsg,sizeof(climsg),0); //send
if(ret<0){
perror("look history send error:");
return -1;
}
ret=recv(cli_fd,&climsg,sizeof(climsg),0); //recv
if(ret<0){
perror("look history recv error:");
return -1;
}else if(ret==0){
printf("looking history server is close\n");
return -1;
}
printf("%s\n",climsg.hisbuf);
return 0;
}
//修改密码
int update_password()
{
char newpassword[32]; //存放新密码的容器
char updatename[16]; //存放寻找修改密码是用到用户名
printf("please input your user name :");
scanf("%s",updatename);
printf("please input your new passwd:");
scanf("%s",newpassword);
memset(&climsg,0,sizeof(climsg));
stpcpy(climsg.use_password,newpassword);
stpcpy(climsg.use_name,updatename); //发送内容赋值
climsg.opt=4;
ret=send(cli_fd,&climsg,sizeof(climsg),0); //send
if(ret<0){
perror("update password send error:");
return -1;
}
ret=recv(cli_fd,&climsg,sizeof(climsg),0); //recv
if(ret<0){
perror("update passwordrecv error:");
return -1;
}else if(ret==0){
printf("update password server is close\n");
return -1;
}
printf("%s\n",climsg.resbuf);
return 0;
}
int main()
{
//创建连接
cli_fd=socket(AF_INET,SOCK_STREAM,0);
if(cli_fd<0){
perror("socket create error");
return -1;
}
struct sockaddr_in srecv_addr; //服务器地址
srecv_addr.sin_family = AF_INET;
srecv_addr.sin_port = htons(8888);
srecv_addr.sin_addr.s_addr = inet_addr("192.168.24.130");
// srecv_addr.sin_addr.s_addr = inet_addr("127.0.0.1");
//连接服务器
ret=connect(cli_fd,(struct sockaddr *)&srecv_addr,sizeof(srecv_addr));
if(ret<0){
perror("connect error:");
return -1;
}
login_and_sign:
while(1)
{
int opt;
mainshow();
printf("input options:");
scanf("%d",&opt);
switch(opt)
{
case 1:
do_sign();
break;
case 2:
do_login();
switch(climsg.login_res)
{
case -1:
goto login_and_sign;
case 0:
printf("login success !!\n");
look:
while(1)
{
int son;
sonshow();
printf("input options:");
scanf("%d",&son);
switch(son)
{
case 1:
look_word();
break;
case 2:
history();
break;
case 3:
update_password();
break;
case 4:
goto login_and_sign;
default:
printf("your what want going ?\n");
goto look;
}
}
}
break;
case 3:
close(cli_fd);
break;
default:
printf("your what want going ?\n");
goto login_and_sign;
}
}
close(cli_fd);
return 0;
}
3.可能有部分理解可能有问题,自己的理解能力有限,希望大家可以多多指点,互相学习。

被折叠的 条评论
为什么被折叠?



