我试图从文件中读取我的链表而没有运气。使用fprintf正确保存Struct(无法使用fwrite)。这是我的结构:
typedef struct database
{
int id;
int nrindeksu;
char *imie;
char *nazwisko;
char *wydzial;
char *kierunek;
struct database* link;
} data;
char buffer[1024]; //changed buffer size
我使用此功能将链接列表保存到文件中:编辑:对其他功能进行一些更改后,这个功能会崩溃。
void save(data* head)
{
FILE *fp;
fp = fopen("test.txt", "w");
data* current = head->link;
while (current != NULL) {
fprintf(fp,"%d ",current->nrindeksu);
fprintf(fp,"%s ",current->imie);
fprintf(fp,"%s ",current->nazwisko);
fprintf(fp,"%s ",current->wydzial);
fprintf(fp,"%s\n",current->kierunek);
current = current->link;
}
fclose(fp);
}
并试图从文件中读取它:
void read(data* head)
{
data* current = head;
FILE *fp;
fp = fopen("test.txt", "r");
while(//I still need help with this loop)
fscanf(fp, "%d", current->link->nrindeksu);
fscanf(fp, "%s", buffer);
current->link->imie=malloc(strlen(buffer) + 1);
if(current->link->imie == NULL) {
fprintf(stderr, "Malloc error");
exit(0);
}
strcpy(current->link->imie, buffer);
fscanf(fp, "%s", buffer);
current->link->nazwisko=malloc(strlen(buffer) + 1);
if(current->link->nazwisko == NULL) {
fprintf(stderr, "Malloc error");
exit(0);
}
strcpy(current->link->nazwisko, buffer);
fscanf(fp, "%s", buffer);
current->link->wydzial=malloc(strlen(buffer) + 1);
if(current->link->wydzial == NULL) {
fprintf(stderr, "Malloc error");
exit(0);
}
strcpy(current->link->wydzial, buffer);
fscanf(fp, "%s", buffer);
current->link->kierunek=malloc(strlen(buffer) + 1);
if(current->link->kierunek == NULL) {
fprintf(stderr, "Malloc error");
exit(0);
}
strcpy(current->link->kierunek, buffer);
fclose(fp);
}
知道为什么它没有读什么? 此外,我不知道如何编写一个循环来确定它应该停止从文件中读取的位置。
编辑: 我使用此功能将项目添加到列表中:
void add_bottom(data* head)
{
data* current = head;
while (current->link != NULL)
{
current = current->link;
}
current->link = malloc(sizeof(*current));//changed every malloc
if(current->link == NULL) {
fprintf(stderr, "Malloc error");
exit(0);
}
printf("Podaj nr indeksu studenta: ");
scanf("%d", current->link->nrindeksu);
printf("Podaj imie studenta: ");
fflush(stdin);
scanf("%19[^\n]", buffer);
current->link->imie=malloc(strlen(buffer) + 1);
if(current->link->imie == NULL) {
fprintf(stderr, "Malloc error");
exit(0);
}
strcpy(current->link->imie, buffer);
printf("Podaj nazwisko studenta: ");
fflush(stdin);
scanf("%19[^\n]", buffer);
current->link->nazwisko=malloc(strlen(buffer) + 1);
if(current->link->nazwisko == NULL) {
fprintf(stderr, "Malloc error");
exit(0);
}
strcpy(current->link->nazwisko, buffer);
printf("Podaj wydzial studenta: ");
fflush(stdin);
scanf("%29[^\n]", buffer);
current->link->wydzial=malloc(strlen(buffer) + 1);
if(current->link->wydzial == NULL) {
fprintf(stderr, "Malloc error");
exit(0);
}
strcpy(current->link->wydzial, buffer);
printf("Podaj kierunek studenta: ");
fflush(stdin);
scanf("%29[^\n]", buffer);
current->link->kierunek=malloc(strlen(buffer) + 1);
if(current->link->kierunek == NULL) {
fprintf(stderr, "Malloc error");
exit(0);
}
strcpy(current->link->kierunek, buffer);
current->link->link = NULL;
}
主:
int main(int argc, char *argv[])
{
char c;
head = init(head);
if(head == NULL) {
fprintf(stderr, "Malloc error");
exit(0);
}
read(head);
do{
printf("Baza danych - wybierz opcje: [d]odaj, [w]yswietl, [u]sun, [k]oniec: ");
scanf("%c", &c);
if(c=='d')
{
system("cls");
add_bottom(head);
}
if(c=='w')
{
system("cls");
show(head);
}
if(c=='u')
{
system("cls");
show(head);
remove_by_id(&head);
system("cls");
show(head);
printf("\n");
}
fflush(stdin);
}while(c!='k');
save(head);
free(head);
return 0;
}
函数init也只是
head = calloc(1,sizeof(data));
这样第一个节点始终为NULL,无法以其他方式创建或编辑第一个节点。
答案 0 :(得分:1)
评论网站的代码有几个问题。仅举几例说明......
陈述(其中6个):
fscanf("%d", &nrindeksu);
...原样不允许您发布的代码进行编译,因为fscanf()
需要FILE *
作为第一个参数。
fscanf(fp, "%d", &nrindeksu);
函数strlen(nazwisko)
(与帖子中所有其他类似的行一样)只返回缓冲区的长度,而不用计算NULL终止符,这将需要长度为接收缓冲区current->link->nazwisko
。
至少,你可以通过明确地为NULL终结符添加空间来解决这个问题:
current->link->nazwisko=(char*)malloc(sizeof(char) * strlen(nazwisko) + 1);
^^^^^^^ ^^^^^^^^^^^^^^ ^^^
not necessary necessary
因为sizeof(char)
总是== 1,所以没有必要
清理:
current->link->nazwisko=malloc(strlen(nazwisko) + 1);
或者,正如评论中所建议的那样(如果POSIX是一个选项),您可以使用strdup()
char *tmp = 0;
tmp = strdup(nazwisko);
if(tmp)
{
current->link->nazwisko = tmp;
strcpy(current->link->nazwisko, nazwisko);
}
另一个小问题。以下是合法的,并确实分配了足够的空间:
current->link = malloc(sizeof(data));
但是这种形式:
current->link = malloc(sizeof(*current));
是 generally recommended ,因为在variable
表达式中使用type
而不是sizeof
会更好。
另外一条评论 it is not necessary to cast the return of [m][c]alloc when using C 。
编辑(编辑你的代码,允许它编译和运行。[完成内存泄漏])
//does not include global declarations of struct data and variables
void read(data** head); //so object can be changed when passes as function argument
// ^
void save(data* head);
int main(void)
{
data *h = calloc(1, sizeof(data));
read(&h); //note, passing to data **, not data *
save(h);
return 0;
}
void save(data* head)
{
FILE *fp;
fp = fopen("text2.txt", "w");
//data* current = head->link;
fprintf(fp,"%d ",head->link->nrindeksu);
fprintf(fp,"%s ",head->link->imie);
fprintf(fp,"%s ",head->link->nazwisko);
fprintf(fp,"%s ",head->link->wydzial);
fprintf(fp,"%s\n",head->link->kierunek);
fclose(fp);
}
void read(data **head)
{
data *current = calloc(1, sizeof(*current));
current = *head;
int count;
FILE *fp;
fp = fopen(".\\text.txt", "r");
{
current->link = malloc(sizeof(data));
if(current->link == NULL) {
fprintf(stderr, "Malloc error");
exit(0);
}
count = fscanf(fp,"%d %s %s %s %s", &nrindeksu, imie, nazwisko, wydzial, kierunek);
if(count != 5)
{
free(current);
return
}
current->link->nrindeksu = nrindeksu;
current->link->imie=(char*)malloc(sizeof(char) * strlen(imie)+1);
if(current->link->imie == NULL) {
fprintf(stderr, "Malloc error");
exit(0);
}
strcpy(current->link->imie, imie);
current->link->nazwisko=(char*)malloc(sizeof(char) * strlen(nazwisko)+1);
if(current->link->nazwisko == NULL) {
fprintf(stderr, "Malloc error");
exit(0);
}
strcpy(current->link->nazwisko, nazwisko);
current->link->wydzial=(char*)malloc(sizeof(char) * strlen(wydzial)+1);
if(current->link->wydzial == NULL) {
fprintf(stderr, "Malloc error");
exit(0);
}
strcpy(current->link->wydzial, wydzial);
current->link->kierunek=(char*)malloc(sizeof(char) * strlen(kierunek)+1);
if(current->link->kierunek == NULL) {
fprintf(stderr, "Malloc error");
exit(0);
}
strcpy(current->link->kierunek, kierunek);
current->link->link = NULL;
}
fclose(fp);
}
注意:上面的代码确实将数据读入节点,并且能够将节点数据写入文件,但是您必须清理内存。什么都没有被释放。我在上面的评论中发布的链接将有助于解决这个问题。
编辑2 (基于 this tutorial link 中的功能)
以下将文本文件(参见代码底部的示例文件)读入链表,然后将列表内容写入第二个文本文件,然后清理所有使用的内存。
typedef struct database
{
int id;
int nrindeksu;
char *imie;
char *nazwisko;
char *wydzial;
char *kierunek;
struct database* link;
}data;
typedef struct {
int id;
int nrindeksu;
char imie[20];
char nazwisko[20];
char wydzial[30];
char kierunek[30];
}LINE;
LINE line;
void push(data** head_ref, LINE *line);
void store(data *d, FILE *p);
void cleanup(data *d);
int main(void)
{
data *head = NULL;
FILE *fp;
fp = fopen(".\\text1.txt", "r");
if(fp)
{
while(fscanf(fp,"%d %s %s %s %s", &line.nrindeksu, line.imie, line.nazwisko, line.wydzial, line.kierunek)== 5)
{
push(&head, &line);
}
fclose(fp);
}
fp = fopen(".\\text2.txt", "w");
if(fp)
{
store(head, fp);
fclose(fp);
}
cleanup(head);
return 0;
}
/// synonymous with your "read()"
void push(data** head_ref, LINE *line)
{
/* 1. allocate node */
data *new_node = malloc(sizeof(*new_node));
/* 2. put in the data */
new_node->id = line->id;
new_node->nrindeksu = line->nrindeksu;
new_node->imie = calloc(1, strlen(line->imie)+1);
strcpy(new_node->imie, line->imie);
new_node->nazwisko = calloc(1, strlen(line->nazwisko)+1);
strcpy(new_node->nazwisko, line->nazwisko);
new_node->wydzial = calloc(1, strlen(line->wydzial)+1);
strcpy(new_node->wydzial, line->wydzial);
new_node->kierunek = calloc(1, strlen(line->kierunek)+1);
strcpy(new_node->kierunek, line->kierunek);
/* 3. Make next of new node as head */
new_node->link = (*head_ref);
/* 4. move the head to point to the new node */
(*head_ref) = new_node;
}
void store(data *d, FILE *p)
{
char line[260];
while(d != NULL)
{
sprintf(line, "%d %s %s %s %s\n", d->nrindeksu, d->imie, d->nazwisko, d->wydzial, d->kierunek);
fputs(line, p);
d = d->link;
}
}
void cleanup(data *d)
{
data *tmp;
while(d != NULL)
{
tmp = d;
if(tmp->imie) free(d->imie);
if(tmp->nazwisko) free(d->nazwisko);
if(tmp->wydzial) free(d->wydzial);
if(tmp->kierunek) free(d->kierunek);
d = d->link;
free(tmp);
}
free(d);
}
作为代码示例的输入引用的文本文件:
text1.txt:
0 string01 string02 string03 string04
1 string11 string12 string13 string14
2 string21 string22 string23 string24
3 string31 string32 string33 strin3g4
4 string41 string42 string43 string44
5 string51 string52 string53 string54
6 string61 string62 string63 string64
7 string71 string72 string73 string74
8 string81 string82 string83 string84
9 string91 string92 string93 string94