你好,我是信息学的学生,我尝试做一个锁定/解锁文件夹的程序。
我把完整的程序给你试试。我可以编译并运行它,但我总是被阻止。 我不知道如何阅读文件(我总是有一个带有读取的返回-1。)
我不会要求我们更正所有代码,只是为了告诉我POSIX的错误
这里我的问题与read(返回-1), 我希望我的程序创建文件,如果不存在但我不知道是否可能 如何验证文件是否打开?我找不到办法。 此函数在文件" PATH_FILE_OWNER"中添加一个struc所有者。在添加锁之前,请验证OWNER是否已具有与新ID相同的ID,如果没有将新的所有者添加到文件中。
void addOwner()
{
proprietaire* proprio = (proprietaire*)malloc(sizeof(proprietaire));
if(proprio == NULL){
perror("L'allocation n'a pu etre réalisee\n");
exit(1);
}
int fd=open(PATH_FILE_OWNER, O_RDWR|O_CREAT, S_IRUSR|S_IWUSR);
struct flock verrou;
verrou.l_type=F_WRLCK;
verrou.l_whence=verrou.l_start=verrou.l_len=0;
while((fcntl(fd, F_SETLK, &verrou) )== -1 && (errno == EACCES || errno == EAGAIN)){
sleep(5);
printf("Verrouiller\n");
}
int idDispo = FALSE,
id;
while(idDispo == FALSE)
{
cleanBuffer();
printf("Entrez un identifiant non utilise\n");
scanf("%d", &id);
printf("id: %d\n", id);
// verifie si l'id est utilisé
int trouve = FALSE, temp;
while((temp = read(fd, proprio, sizeof(proprietaire))) != 0 && trouve == FALSE)
{
// I have add this for verify the error, it is right ? (if yes I ll do every where :)
if(temp < 0){
printf("Boucle %d\n", temp);
perror("erreur");
printf("errno=%d\n", errno);
exit(1);
}
if(proprio->identifiant == id){
trouve = TRUE;
}
}
// si l'id est utilisé redemande un autre id et refait une recherche,
// sinon sort de la boucle et continue
if(trouve == TRUE){
printf("Identifiant deja utilise\n");
} else {
idDispo = TRUE;
}
}
// demande le reste des info et initialise la structure
proprio->identifiant = id;
printf("Entrez son nom:\n");
scanf("%s",proprio->nom);
printf("Entrez son prenom:\n");
scanf("%s",proprio->prenom);
printf("Entrez son adresse:\n");
scanf("%s",proprio->adresse);
proprio->nbVoiture = 0;
// test affichage
printf("Id : %d\n", proprio->identifiant);
printf("Nom: %s\n", proprio->nom);
printf("Prenom: %s\n", proprio->prenom);
printf("Adresse: %s\n", proprio->adresse);
printf("Nombre de voiture posseder: %d\n\n", proprio->nbVoiture);
// j'enregistrer le proprietaire
lseek(fd,0,SEEK_END);
write(fd, proprio , sizeof(proprio));
// je deverrouille
verrou.l_type = F_UNLCK;
if (fcntl(fd, F_SETLK, &verrou) == -1){
perror("Impossible de deverouiller le record");
exit(1);
}
close(fd);
free(proprio);
}
这里是完整的代码:
#if defined(linux) || defined(__linux__) || defined(unix) || defined (__unix__) || defined (__APPLE__)
#define mrpropre system("clear")
#else
#define mrpropre system("cls")
#endif
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <unistd.h>
#include <sys/types.h>
#include <stdio.h>
#include <sys/stat.h>
#include <errno.h>
#include <string.h>
#include <fcntl.h>
#define TAILLE_NOM_MARQUE 20
#define TAILLE_NOM_MODELE 10
#define TAILLE_NOM_COULEUR 10
#define TAILLE_NOM_PLAQUE 7
#define TAILLE_NOM_PROPRIETAIRE 20
#define TAILLE_PRENOM_PROPRIETAIRE 20
#define TAILLE_ADRESSE_PROPRIETAIRE 40
#define FALSE 0
#define TRUE 1
#define PATH_FILE_OWNER "fichProprio.bin"
#define PATH_FILE_CAR "fichVoiture.bin"
typedef struct voiture
{
char nomMarque[TAILLE_NOM_MARQUE];
char nomModele[TAILLE_NOM_MODELE];
char couleur[TAILLE_NOM_COULEUR];
char plaque[TAILLE_NOM_PLAQUE];
int idProprietaire;
} voiture;
typedef struct proprietaire
{
int identifiant;
char nom[TAILLE_NOM_PROPRIETAIRE];
char prenom[TAILLE_PRENOM_PROPRIETAIRE];
char adresse[TAILLE_ADRESSE_PROPRIETAIRE];
int nbVoiture;
} proprietaire;
char menu();
void showOwnerWithCar();
void addOwner();
void addCar();
void updateOwner();
void updateCar();
void deleteOwner();
void deleteCarID(int);
void deleteCar();
int addCarToOwner(int, int);
void cleanBuffer();
int main(void)
{
int fin=0;
while(fin == 0)
{
mrpropre;
cleanBuffer();
char choixMenu = menu();
switch(choixMenu)
{
case '0': // Quitter
fin = 1;
break;
case '1':
showOwnerWithCar();
break;
case '2':
addOwner();
break;
case '3':
addCar();
break;
case '4':
updateOwner();
break;
case '5':
updateCar();
break;
case '6':
deleteOwner();
break;
case '7':
deleteCar();
break;
default:
printf("Erreur, aucun choix \n");
getchar();
break;
}
}
return 0;
}
char menu()
{
printf("\nQue voulez-vous faire ?\n-------------------\n\n");
printf("\t 1) Afficher un proprietaire et ces voiture\n");
printf("\t 2) Ajouter un proprietaire\n");
printf("\t 3) Ajouter une voiture (elle devra etre liee a un proprietaire)\n");
printf("\t 4) Mise a jour des informations d'un proprietaire\n");
printf("\t 5) Mise a jour des informations d'une voiture\n");
printf("\t 6) Supprimer un proprietaire et ces voitures\n");
printf("\t 7) Supprimer une voiture\n");
printf("\t 0) Quitter le programme\n");
return getchar();
}
void showOwnerWithCar(){
// on cherche le propriétaire
printf("Entrez l'identifiant du proprietaire\n");
int idChercher;
scanf("%d", &idChercher);
proprietaire* proprio = (proprietaire*)malloc(sizeof(proprietaire));
if(proprio == NULL){
perror("L'allocation n'a pu etre réalisee\n");
exit(1);
}
int fdOwner = open(PATH_FILE_OWNER, O_RDONLY|O_CREAT, S_IRUSR);
int trouve = FALSE;
while(read(trouve == FALSE && fdOwner, proprio, sizeof(proprietaire)) != 0)
{
printf("ici1\t");
if(proprio->identifiant == idChercher)
{
trouve = TRUE;
}
}
close(fdOwner);
printf("ici2\t");
voiture * car = (voiture*)malloc(sizeof(voiture));
voiture * tabVoiture = malloc(proprio->nbVoiture * sizeof(voiture));
int fdCar = open(PATH_FILE_CAR, O_RDONLY);
// ensuite on cherche ces voitures
int nbVoitureTrouver = 0;
while(read(fdCar, car, sizeof(voiture)) != 0 && nbVoitureTrouver < proprio->nbVoiture)
{
if(proprio->identifiant == idChercher)
{
tabVoiture[nbVoitureTrouver] = *car;
nbVoitureTrouver++;
}
}
close(fdCar);
free(car);
// on affiche le propriétaire
printf("Id : %d\n", proprio->identifiant);
printf("Nom: %s\n", proprio->nom);
printf("Prenom: %s\n", proprio->prenom);
printf("Adresse: %s\n", proprio->adresse);
printf("Nombre de voiture posseder: %d\n\n", proprio->nbVoiture);
// ensuite ces voitures
int nbCar;
for(nbCar=0;nbCar<proprio->nbVoiture;nbCar++){
printf("Marque : %s\n", tabVoiture[nbCar].nomMarque);
printf("Modele : %s\n", tabVoiture[nbCar].nomModele);
printf("Couleur : %s\n",tabVoiture[nbCar].couleur);
printf("Plaque : %s\n", tabVoiture[nbCar].plaque);
}
// on vide la mémoire
free(proprio);
for(nbCar=0;nbCar<proprio->nbVoiture;nbCar++){
free(tabVoiture + nbCar);
}
}
void addOwner()
{
proprietaire* proprio = (proprietaire*)malloc(sizeof(proprietaire));
if(proprio == NULL){
perror("L'allocation n'a pu etre réalisee\n");
exit(1);
}
int fd=open(PATH_FILE_OWNER, O_RDWR|O_CREAT, S_IRUSR|S_IWUSR);
struct flock verrou;
verrou.l_type=F_WRLCK;
verrou.l_whence=verrou.l_start=verrou.l_len=0;
while((fcntl(fd, F_SETLK, &verrou) )== -1 && (errno == EACCES || errno == EAGAIN)){
sleep(5);
printf("Verrouiller\n");
}
int idDispo = FALSE,
id;
while(idDispo == FALSE)
{
cleanBuffer();
printf("Entrez un identifiant non utilise\n");
scanf("%d", &id);
printf("id: %d\n", id);
// verifie si l'id est utilisé
int trouve = FALSE, temp;
while((temp = read(fd, proprio, sizeof(proprietaire))) != 0 && trouve == FALSE)
{
// I have add this for verify the error, it is right ? (if yes I ll do every where :)
if(temp < 0){
printf("Boucle %d\n", temp);
perror("erreur");
printf("errno=%d\n", errno);
exit(1);
}
if(proprio->identifiant == id){
trouve = TRUE;
}
}
// si l'id est utilisé redemande un autre id et refait une recherche,
// sinon sort de la boucle et continue
if(trouve == TRUE){
printf("Identifiant deja utilise\n");
} else {
idDispo = TRUE;
}
}
// demande le reste des info et initialise la structure
proprio->identifiant = id;
printf("Entrez son nom:\n");
scanf("%s",proprio->nom);
printf("Entrez son prenom:\n");
scanf("%s",proprio->prenom);
printf("Entrez son adresse:\n");
scanf("%s",proprio->adresse);
proprio->nbVoiture = 0;
// test affichage
printf("Id : %d\n", proprio->identifiant);
printf("Nom: %s\n", proprio->nom);
printf("Prenom: %s\n", proprio->prenom);
printf("Adresse: %s\n", proprio->adresse);
printf("Nombre de voiture posseder: %d\n\n", proprio->nbVoiture);
// j'enregistrer le proprietaire
lseek(fd,0,SEEK_END);
write(fd, proprio , sizeof(proprio));
// je deverrouille
verrou.l_type = F_UNLCK;
if (fcntl(fd, F_SETLK, &verrou) == -1){
perror("Impossible de deverouiller le record");
exit(1);
}
close(fd);
free(proprio);
}
void addCar()
{
voiture* car = (voiture*)malloc(sizeof(voiture));
if(car == NULL){
perror("L'allocation n'a pu etre réalisee\n");
exit(1);
}
int fd=open(PATH_FILE_CAR, O_APPEND|O_CREAT, S_IRUSR|S_IWUSR);
struct flock verrou;
verrou.l_type=F_WRLCK;
verrou.l_whence=verrou.l_start=verrou.l_len=0;
int res, id;
while( res == 0 )
{
printf("Entrer l'identifiant du proprietaire\n");
scanf("%d", &id);
res = addCarToOwner(1, id);
}
if(res == 1)
{
printf("Id valide\n");
car->idProprietaire = id;
printf("Entrez sa marque:\n");
scanf("%s",car->nomMarque);
printf("Entrez son modele:\n");
scanf("%s",car->nomModele);
printf("Entrez sa couleur:\n");
scanf("%s",car->couleur);
printf("Entrez son numero de plaque:\n");
scanf("%s",car->plaque);
// je verrouille le fichier
while ( (fcntl(fd, F_SETLK, &verrou) )== -1 && (errno == EACCES || errno == EAGAIN) ){
sleep(5);
}
// j'enregistre la voiture
lseek(fd,0,SEEK_END);
write(fd , car, sizeof(car));
// je deverrouille le fichier
verrou.l_type = F_UNLCK;
if (fcntl(fd, F_SETLK, &verrou) == -1){
perror("Impossible de deverouiller le record");
exit(1);
}
}
free(car);
close(fd);
}
void updateOwner()
{
proprietaire* proprio = (proprietaire*)malloc(sizeof(proprietaire));
if(proprio == NULL){
perror("L'allocation n'a pu etre réalisee\n");
exit(1);
}
int fd=open(PATH_FILE_OWNER, O_RDWR|O_CREAT, S_IRUSR|S_IWUSR);
struct flock verrou;
verrou.l_type=F_WRLCK;
verrou.l_whence=verrou.l_start=verrou.l_len=0;
printf("Id du proprietaire: \n");
int id; scanf("%d",&id);
while((fcntl(fd, F_SETLK, &verrou) )== -1 && (errno == EACCES || errno == EAGAIN)){
sleep(5);
}
// je cherche la personne concerner et la modifie si elle existe
int trouve = FALSE;
while(read(fd, proprio, sizeof(proprietaire)) != 0 && trouve == FALSE){
if(proprio->identifiant == id){
trouve = TRUE;
printf(" L'adresse est %s\n Entrez la nouvelle adresse:\n", proprio->adresse);
scanf("%s", proprio->adresse);
lseek(fd, -sizeof(proprio) , SEEK_CUR);
write(fd, proprio , sizeof(proprio));
}
}
if(trouve == FALSE) printf("ID invalide\n");
// je deverrouille le fichier
verrou.l_type = F_UNLCK;
if (fcntl(fd, F_SETLK, &verrou) == -1)
perror("Impossible de deverouiller le record");
close(fd);
free(proprio);
}
void updateCar()
{
voiture* car = (voiture*)malloc(sizeof(voiture));
if(car == NULL){
perror("L'allocation n'a pu etre réalisee\n");
exit(1);
}
int fd=open(PATH_FILE_OWNER, O_RDWR|O_CREAT, S_IRUSR|S_IWUSR);
struct flock verrou;
verrou.l_type=F_WRLCK;
verrou.l_whence=verrou.l_start=verrou.l_len=0;
char numPlaque[TAILLE_NOM_PLAQUE];
printf("Entrez la plaque d'immatriculation du véhicule");
scanf("%s", numPlaque);
// je verouille
while((fcntl(fd, F_SETLK, &verrou) )== -1 && (errno == EACCES || errno == EAGAIN)){
sleep(5);
}
// je recherche la voiture portant ce numero de plaque
int trouve = FALSE;
while(read(fd, car, sizeof(voiture)) != 0 && trouve == FALSE){
// si je la trouve je modifie sa couleur
if(strcmp(numPlaque, car->plaque) == 0){
trouve = TRUE;
printf("Entrez la nouvelle couleur");
scanf("%s", car->couleur);
lseek(fd, -sizeof(car) , SEEK_CUR);
write(fd , car , sizeof(car));
}
}
// je deverrouille le fichier
verrou.l_type = F_UNLCK;
if (fcntl(fd, F_SETLK, &verrou) == -1){
perror("Impossible de deverouiller le record");
exit(1);
}
if(trouve == FALSE){
printf("Voiture inconnue");
}
free(car);
}
void deleteOwner(){
proprietaire* proprio = (proprietaire*)malloc(sizeof(proprietaire));
if(proprio == NULL){
perror("L'allocation n'a pu etre réalisee\n");
exit(1);
}
int fd=open(PATH_FILE_OWNER, O_RDONLY|O_CREAT, S_IRUSR);
int fdNew=open("tempOwner.dat", O_WRONLY|O_CREAT, S_IWUSR);
int id;
printf("Entrez l'identifiant du proprietaire a supprimer\n");
scanf("%d", &id);
int trouve = FALSE;
while(read(fd, proprio, sizeof(proprietaire)) != 0)
{
if(proprio->identifiant == id){
trouve = TRUE;
} else {
write( fdNew, proprio, sizeof(proprietaire));
}
}
if(trouve == TRUE){
rename("tempOwner.dat", PATH_FILE_OWNER);
deleteCarID(id);
printf("Supression du proprietaire\n");
} else {
printf("id invalide");
}
free(proprio);
}
void deleteCarID(int id){
voiture* car = (voiture*)malloc(sizeof(voiture));
if(car == NULL){
perror("L'allocation n'a pu etre réalisee\n");
exit(1);
}
int fd=open(PATH_FILE_CAR, O_RDONLY|O_CREAT, S_IRUSR);
int fdNew=open("tempCar.dat", O_WRONLY|O_CREAT, S_IWUSR);
int trouve = FALSE;
while(read(fd, car, sizeof(voiture)) != 0)
{
if(!car->idProprietaire == id){
trouve = TRUE;
write( fdNew, car, sizeof(proprietaire));
}
}
if(trouve == TRUE){
rename("tempCar.dat", PATH_FILE_CAR);
printf("Supression des voitures\n");
}
free(car);
}
void deleteCar(){
voiture* car = (voiture*)malloc(sizeof(voiture));
if(car == NULL){
perror("L'allocation n'a pu etre réalisee\n");
exit(1);
}
char numPlaque[TAILLE_NOM_PLAQUE];
printf("Entrez le numero de plaque de la voiture a supprimer\n");
scanf("%s", numPlaque);
int fd=open(PATH_FILE_CAR, O_RDONLY|O_CREAT, S_IRUSR);
int fdNew=open("tempCar.dat", O_WRONLY|O_CREAT, S_IWUSR);
int trouve = FALSE;
while(read(fd, car, sizeof(voiture)) != 0)
{
if(strcmp(numPlaque, car->plaque) == 0){
trouve = TRUE;
} else {
write(fdNew, car, sizeof(proprietaire));
}
}
if(trouve == TRUE){
rename("tempCar.dat", PATH_FILE_CAR);
printf("Supression des voitures\n");
addCarToOwner(-1, car->idProprietaire);
}
free(car);
}
// -1 pas de fichier
// 0 id correspond pas
// 1 ok
int addCarToOwner(int nb, int id){
proprietaire* proprio = (proprietaire*)malloc(sizeof(proprietaire));
if(proprio == NULL){
perror("L'allocation n'a pu etre réalisee\n");
exit(1);
}
int fd=open(PATH_FILE_OWNER, O_RDWR|O_CREAT, S_IRUSR|S_IWUSR);
struct flock verrou;
verrou.l_type=F_WRLCK;
verrou.l_whence=verrou.l_start=verrou.l_len=0;
int res = 0,
trouve = FALSE;
res = 0;
// je verrouille le fichier des proprietaires
while((fcntl(fd, F_SETLK, &verrou) )== -1 && (errno == EACCES || errno == EAGAIN)){
sleep(5);
}
// je cherche le proprietaire dans le fichier
while(read(fd, proprio, sizeof(proprietaire)) != 0 && trouve == FALSE){
if(proprio->identifiant == id){
trouve = TRUE;
res = 1;
if(nb>0){
proprio->nbVoiture++;
} else {
if(proprio->nbVoiture>0){
proprio->nbVoiture--;
}
}
lseek(fd, -sizeof(proprio) , SEEK_CUR);
write(fd, proprio , sizeof(proprio));
}
}
// je deverrouille le fichier
verrou.l_type = F_UNLCK;
if (fcntl(fd, F_SETLK, &verrou) == -1){
perror("Impossible de deverouiller le record");
exit(1);
}
close(fd);
free(proprio);
return res;
}
void cleanBuffer(){
while( getchar() != '\n');
}
P.S我的借口是我的英语,并且没有尊重我的问题的语法。我下次会尝试做得更好。我实际上只是要求函数addOwner();在您的帮助下,如果可能的话,我会尝试调试我的所有程序。
对你所有人来说,这很好。)
答案 0 :(得分:2)
像这样打开文件:
fd = open(PATH_FILE_OWNER, O_RDWR|O_CREAT, S_IRUSR|S_IWUSR);
请注意,您仍需要指定访问模式(O_RDWR),并且新创建的文件需要文件模式标志。这应该可以解决你的问题。
此外,您应该为open()
以及之前的malloc()
添加错误检查。
修改强>
您在编写数据时遇到了进一步的问题。写入不完整的记录是因为您只写sizeof(proprio)
个字节。 proprio
被声明为结构的指针,因此它的大小是指针的大小(64位机器上的8个字节)。将您的写入更改为:
ssize_t n = write(fd, proprio , sizeof(proprietaire));
这样您就可以编写struct proprietaire
所需的字节数(64位机器为88字节)。检查write()
的返回值以确保写入正确的字节数或检查错误非常重要。
答案 1 :(得分:1)
您需要检查open()的返回码。如果您的文件尚未存在,则打开将失败,然后您的read()调用将因EBADF而失败。
听起来您想要在open()调用中添加O_CREAT标志,以便在文件不存在的情况下创建该文件。
此时,我不认为你的锁与你的问题有任何关系。