这是一个 C 语言程序,它将所有数据库(结构)放入文件并随后读取,但是当我通过以下方式执行它时:(编译后)
a ab.txt w 1 abc abc@me.com
程序崩溃并停止工作 <windows>
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include<errno.h>
struct Rows{
int id;
int state;
char* name;
char* email;
};
struct database{
struct Rows rows[200];
};
struct connection{
FILE* fil;
struct database *db;
};
size_t dbsize = sizeof(struct database*);
void die(char* err){
if(errno)perror(err);
else fprintf(stderr,err);
exit(0);
}
struct connection fileopener(char* filename,char mode){
struct connection conn;
if(mode=='w')conn.fil=fopen(filename,"a+");
else conn.fil=fopen(filename,"r+");
return conn;
}
void writetof(struct connection conn){
int rc =fwrite(conn.db,dbsize,1,conn.fil);
if(rc!=1)die("cannot write");
rc = fflush(conn.fil);
if(rc==-1) die("cannot flush");
}
void writetodb(struct connection conn,int id ,char*name,char* email){
if(conn.db->rows[id].state = =1)die("already written");
conn.db->rows[id].state=1;
conn.db->rows[id].id=id;
conn.db->rows[id].name = strdup(name);
conn.db->rows[id].email = strdup(email);
}
void delete(struct connection conn,int id){
conn.db->rows[id].state=0;
}
void readfrom(struct connection conn,int id){
if(conn.db->rows[id].state==0)die(" no record sorry");
else {
printf("id\tname\temail\n");
printf("%d\t%s\t%s\n", conn.db->rows[id].id,conn.db->rows[id].name,conn.db->rows[id].email);
}
}
void printall(struct connection conn){
int i =0;
printf("id\tname\\temail\n");
for(;i<200;i++){
if(conn.db->rows[i].state==1){
printf("%d\t%s\t%s\t",conn.db->rows[i].id,conn.db->rows[i].name,conn.db->rows[i].email);
}
}
if(i==0)die("no records");
}
void init(struct connection conn){
int i ;
for(i=0;i<200;i++){
conn.db->rows[i].id=i;
conn.db->rows[i].state=0;
}
}
int main(int argc,char* argv[]){
if(argc<3)die("need filename and mode");
char* filename = argv[1];
char mode = argv[2];
struct connection conn = fileopener(filename,mode);
init(conn);
int mid;
fread(conn.db,dbsize,1,conn.fil);
if(argc>3)mid = atoi(argv[3]);
switch(mode){
case 'w':
if(argc<6)die("need data to be written <id> <name> <email>");
writetodb(conn,mid,argv[4],argv[5]);
writetof(conn);
break;
case 'r':
if(argc<3)die("need id");
readfrom(conn,mid);
break;
case 'p':
printall(conn);
case 'd':
delete(conn,mid);
break;
default:
die("mode should be w , r , p d");
}
return 0;
}
最佳答案
我看到的问题:
检查fopen
返回值失败
你有:
struct connection fileopener(char* filename,char mode){
struct connection conn;
if(mode=='w')conn.fil=fopen(filename,"a+");
else conn.fil=fopen(filename,"r+");
return conn;
}
我建议在那里添加一个检查来处理打开文件失败的情况。
struct connection fileopener(char* filename,char mode){
struct connection conn;
if(mode=='w')conn.fil=fopen(filename,"a+");
else conn.fil=fopen(filename,"r+");
if ( conn.fil == NULL )
{
die("cannot open file");
}
return conn;
}
使用未初始化的指针
你有
void init(struct connection conn){
int i ;
for(i=0;i<200;i++){
conn.db->rows[i].id=i;
conn.db->rows[i].state=0;
}
}
此时conn.db
尚未初始化。在使用它之前,您需要为其分配内存。将其更改为:
void init(struct connection* conn){
int i ;
conn->db = malloc(sizeof(*(conn->db)));
for(i=0;i<200;i++){
conn->db->rows[i].id=i;
conn->db->rows[i].state=0;
}
}
我建议将参数类型更改为指针并为其分配内存。否则,为 conn.db
分配的内存将仅用于对象的本地副本,而不是 main
中的对象。
这意味着将 main
中对 init
的调用更改为:
init(&conn);
关于c - 如何用C语言调试一个简单的数据库?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37451630/