gpt4 book ai didi

c - 带锁的 C 读写 (POSIX)

转载 作者:行者123 更新时间:2023-11-30 18:40:01 26 4
gpt4 key购买 nike

您好,我是信息学学生,我尝试编写一个锁定/解锁文件夹的程序。

我把完整的程序放给你,你可以试试。我可以编译并运行它,但我总是被阻止。我不知道如何读取文件(我总是返回 -1 和 read..)

我不要求我们更正我的所有代码,只是为了向我展示我在 POSIX 方面做错了什么

这是我的探针,读取(返回-1),我希望我的程序创建该文件(如果不存在),但我不知道是否可能。
如何验证文件是否打开?我没有找到办法。该函数在文件“PATH_FILE_OWNER”中添加一个结构所有者,在添加锁之前,验证所有者是否已经具有与新所有者相同的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 我为我的英语辩解,并且不尊重我提问的语法。下次我会努力做得更好。我实际上只要求 function addOwner();如果可能的话,在您的帮助下,我将尝试调试我的所有程序。

谢谢你,你们都很好:)

最佳答案

像这样打开文件:

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() 的返回值以确保写入的字节数正确或检查是否有错误非常重要。

关于c - 带锁的 C 读写 (POSIX),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27589897/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com