【发布时间】:2021-08-29 05:54:26
【问题描述】:
我遇到的问题是,一旦我想读取文件,程序会打印出所有内容,但它不会读取文件的最后一个元素。 所以在文件中可以说我有:
- admin:pass:1000:off
- test:testxx:1000:off
- ret:passx:1000:off
它打印出前 2 行,然后显示“缓冲区结束”(它只是一个 printf,我将其放入代码中以了解问题出在哪里)。 打印出“缓冲区结束”后,它会打印出最后一行.. 我做错了什么?
#include <stdlib.h> /* exit */
#include <errno.h> /* perror */
#include <stdio.h>
#include <unistd.h> /* write, read, close*/
#include <sys/types.h>
#include <sys/stat.h> /*open */
#include <fcntl.h>
#include <string.h>
#define MAX 500
struct utente{
char username[MAX];
char password[MAX];
int gettoni;
char stato[MAX];
struct utente *next;
};
void menu(int);
struct utente* lettura_file(struct utente *);
struct utente* ins_coda(struct utente *t, char username[], char password[], char gettoni[], char stato[]);
void stampa_lista(struct utente*);
struct utente* elabora(struct utente *top, char buffer[]);
int check(struct utente *, char *);
void aggiornamento_file(struct utente *top);
int main(){
while(1){
char scelta[MAX], stringa[MAX];
int i=0, res=0;
struct utente *TOP=NULL;
printf("1. STAMPA LISTA\nInserisci scelta --> ");
scanf("%s", scelta);
i=atoi(scelta);
switch(i){
case 1:
TOP=lettura_file(TOP);
stampa_lista(TOP);
/*printf("Inserisci stringa da trovare: ");
scanf("%s", stringa);
res=check(TOP, stringa);
if(res==1)
aggiornamento_file(TOP);
*/
break;
}
}
return 0;
}
struct utente* lettura_file(struct utente *top){
int fd, nread;
char buffer[MAX];
fd=open("utenti.txt", O_RDONLY);
if(fd==-1){
perror("ERRORE APERTURA FILE");
return top;
}
while((nread=read(fd, buffer, MAX)>0)){
top=elabora(top,buffer);
}
close(fd);
return top;
}
struct utente* elabora(struct utente *top, char buffer[]){
char username[MAX], password[MAX], gettoni[MAX], stato[MAX];
int i=0;
int j=0; //indice username
int k=0; //indice password
int t=0; //indice gettoni
int x=0; //indice stato
int count=0;
printf("Inzio buffer:\n%sfine buffer\n" ,buffer);
while(buffer[i]!='\0'){
//ELABORO NOME
while(buffer[i]!=':'){
username[j]=buffer[i];
j++;
i++;
}
username[j]='\0';
i++;
//ELABORO COGNOME
while(buffer[i]!=':'){
password[k]=buffer[i];
k++;
i++;
}
password[k]='\0';
i++;
//ELABORO GETTONI
while(buffer[i]!=':'){
gettoni[t]=buffer[i];
t++;
i++;
}
gettoni[t]='\0';
i++;
while(buffer[i]!='\n' && buffer[i]!='\0'){
stato[x]=buffer[i];
x++;
i++;
}
stato[x]='\0';
if(buffer[i]=='\n')
i++;
if(buffer[i]=='\0'){
printf("\nEnd of the buffer %c\n", buffer[i]);
printf("Fine%s %s %s %s\n\n", username, password, gettoni, stato);
top=ins_coda(top, username, password, gettoni, stato);
return top;
}
printf("Utente %d, %s %s %s %s\n\n", count, username, password, gettoni, stato);
top=ins_coda(top, username, password, gettoni, stato);
bzero(username, MAX);
bzero(password, MAX);
bzero(gettoni, MAX);
bzero(stato, MAX);
j=0;
k=0;
t=0;
x=0;
}
return top;
}
struct utente* ins_coda(struct utente *t, char username[], char password[], char gettoni[], char stato[]){
struct utente *p, *top;
int n_gettoni;
p=(struct utente*)malloc(sizeof(struct utente));
strcpy(p->username, username);
strcpy(p->password, password);
n_gettoni=atoi(gettoni);
p->gettoni=n_gettoni;
strcpy(p->stato, stato);
p->next=NULL;
if(t==NULL)
return p;
top=t;
while(t->next!=NULL)
t=t->next;
t->next=p;
return top;
}
void stampa_lista(struct utente *TOP){
int i=1;
while(TOP!=NULL){
printf("Utente %d:\n Username: %s\nPassword: %s\nGEttoni: %d\nStato: %s\n", i, TOP->username, TOP->password, TOP->gettoni, TOP->stato);
TOP=TOP->next;
i++;
}
return;
}
int check(struct utente *top, char stringa[]){
int len=strlen(stringa);
while(top!=NULL){
if(strncmp(top->username, stringa, len)==0){
strcpy(top->stato, "on");
printf("OK\n");
return 1;
}else{
printf("KO\n");
return 0;
}
top=top->next;
}
return 0;
}
void aggiornamento_file(struct utente *top){
char username[MAX], password[MAX], gettoni[MAX], stato[MAX]="";
int fd;
fd = open("utenti.txt", O_WRONLY |O_TRUNC, S_IRUSR | S_IWUSR);
if(fd==-1){
perror("ERROR apertura file utenti!");
exit(1);
}else{
while(top!=NULL){
strcpy(username, top->username);
strcpy(password, top->password);
sprintf(gettoni, "%d", top->gettoni);
strcpy(stato, top->stato);
write(fd, username, strlen(username));
write(fd, ":", 1);
write(fd, password, strlen(password));
write(fd, ":", 1);
write(fd, gettoni, strlen(gettoni));
write(fd, ":", 1);
write(fd, stato, strlen(stato));
write(fd, "\n", 1);
top=top->next;
}
}
close(fd);
return;
}
【问题讨论】:
-
这种字符串拆分可能会让人困惑,那么用strtok加上“:”分隔符或者sscanf不是更方便吗?
-
这里发生的事情太多了,无法真正给出一个连贯的答案。一方面,您在
elabora中有while(buffer[i]!='\0'){。也许我遗漏了一些东西,但我不知道你会期望在哪里找到'\0'。它可能与更大的问题无关,但这些小事可能有助于掩盖它。 -
当然可以,但是我想了解为什么当还有一行时他会到达缓冲区的末尾?它似乎在文件的最后一行之前读取 '\0'
-
我怀疑
'\0'正是在当前条件下发生成为char buffer[MAX];的基础。 -
您正在使用
open/read。虽然可以做到这一点,但您正在重新发明fopen/fgets已经在做的事情。
标签: c linux system-calls