[英]remove() in c doesn't work from function
我試圖刪除一個文件,然后從一個不起作用的函數重命名已刪除文件名稱中的臨時文件。 請幫我
boolean delete_user(char user_name[256]) //only for Admin
{
boolean status = FALSE;//what does the function return
User_Data *ud = NULL;
boolean found_user = FALSE;
FILE *new_file = NULL;
FILE *fp = NULL;
char user_name_to_copy[256];
char password_to_copy[256];
char old_file_name[256];
ud = find_user(user_name);
if (ud == NULL) {
printf("The username wasn't found!\n");
return FALSE;
}
if (!strcmp(ud->permission_type, "Admin")) {
printf("Cant delete an admin.");
return FALSE;
} else {
// the user to delete was found
new_file = fopen("duplicate.txt", "wt");
strcpy(old_file_name, ud->permission_type);
strcat(old_file_name, "s.txt"); //the name of the file is in plural and ends with .txt
fp = fopen(old_file_name, "rt");
while (!feof(fp)) {
//copy all the users except the user to delete the new file
fscanf(fp, "%s %s\n", user_name_to_copy, password_to_copy);
if (strcmp(user_name_to_copy, user_name)) {
fprintf(new_file, "%s %s\n", user_name_to_copy, password_to_copy);
}
}
fclose(fp);
fclose(new_file);
printf(" %d ", remove(old_file_name));
rename("duplicate.txt", old_file_name);
remove("duplicate.txt");
return TRUE;
}
}
當我從另一個函數調用它時,此函數不起作用,但從主函數可以正常工作。
您的代碼中存在多個問題:
您不檢查fopen()
成功打開了文件。
連接字符串以計算權限文件時,不會阻止潛在的緩沖區溢出。
您應該將數組大小傳遞給fscanf
以防止潛在的緩沖區溢出。
您應該使用strerror(errno)
輸出有意義且信息豐富的錯誤消息,以及失敗原因。
復制權限文件的循環不正確: 為什么“while(!feof(file))”總是錯誤的?
即使您無法重命名但仍設法刪除原始文件,您也會刪除重復的文件:兩個文件都可能丟失。 相反,如果重命名操作成功,則刪除重復文件是多余的。
以下是如何改進代碼:
#include <errno.h>
#include <string.h>
boolean delete_user(char user_name[256]) { //only for Admin
boolean status = FALSE; // the function return value
User_Data *ud = NULL;
boolean found_user = FALSE;
FILE *new_file = NULL;
FILE *fp = NULL;
char user_name_to_copy[256];
char password_to_copy[256];
char old_file_name[256];
ud = find_user(user_name);
if (ud == NULL) {
printf("User '%s' was not found!\n", user_name);
return FALSE;
}
if (!strcmp(ud->permission_type, "Admin")) {
printf("Cannot delete user '%s', user has admin status.\n", user_name);
return FALSE;
}
// the user to delete was found
new_file = fopen("duplicate.txt", "wt");
if (new_file == NULL) {
printf("Cannot open file 'duplicate.txt': %s\n"
strerror(errno));
return FALSE;
}
// the name of the file is in plural and ends with .txt
snprintf(old_file_name, sizeof old_file_name, "%ss.txt", ud->permission_type);
fp = fopen(old_file_name, "rt");
if (fp == NULL) {
printf("Cannot open user file '%s': %s\n"
old_file_name, strerror(errno));
return FALSE;
}
// copy all the users except the user to delete the new file
while (fscanf(fp, "%255s %255s\n", user_name_to_copy, password_to_copy) == 2) {
if (strcmp(user_name_to_copy, user_name)) {
fprintf(new_file, "%s %s\n", user_name_to_copy, password_to_copy);
}
}
fclose(fp);
fclose(new_file);
if (remove(old_file_name)) {
printf("Error removing file '%s': %s\n",
old_file_name, strerror(errno));
remove("duplicate.txt");
return FALSE;
}
if (rename("duplicate.txt", old_file_name)) {
printf("Error renaming file 'duplicate.txt' to '%s': %s\n",
old_file_name, strerror(errno));
// keep duplicate.txt
return FALSE;
}
// duplicates.txt was successfully renamed, no need to remove it.
return TRUE;
}
筆記:
rename()
可能無法將重復文件從當前目錄移動到該目錄。 如果這是失敗的原因,則應使用適當的診斷運行代碼。 printf(" %d ", remove(old_file_name));
rename("duplicate.txt", old_file_name);
remove("duplicate.txt");
此代碼大多是冗余的。
沒有必要刪除
(事實證明這是一個POSIX的東西,C標准不保證它)。 沒有必要刪除old_file_name
,
rename
將會
old_file_name
它。
duplicate.txt
,它已被重命名。
if( remove(old_file_name) != 0 ) {
fprintf( stderr, "Could not remove %s: %s", old_file_name, strerror(errno) );
}
if( rename("duplicate.txt", old_file_name) != 0 ) {
fprintf( stderr, "Could not rename %s to %s: %s", "duplicate.txt", old_file_name, strerror(errno) );
}
您需要檢查每個文件操作 。 這包括fopen
和fscanf
。
此外,您可能會將文件向后移動。 它rename( old, new )
但它看起來像你寫的rename( new, old )
。 如果您沒有將它們顛倒過來,請考慮使代碼更易於理解的變量名稱。
fp = fopen(old_file_name, "rt");
while (!feof(fp)) {
//copy all the users except the user to delete the new file
fscanf(fp, "%s %s\n", user_name_to_copy, password_to_copy);
if (strcmp(user_name_to_copy, user_name)) {
fprintf(new_file, "%s %s\n", user_name_to_copy, password_to_copy);
}
}
此代碼存在問題。 如上所述,它無法檢查fopen
和fscanf
是否成功。 使用fscanf
是一個問題,如果它無法匹配,它不會使文件指針前進。 你可以一遍又一遍地閱讀同一行,每次都失敗。 通常,請避免使用fscanf
和scanf
。
相反,用fgets
讀取整行並用sscanf
解析它。 一定要檢查sscanf
是否成功,否則你會打印出亂碼。 請注意, sscanf
已經限制了它將讀取的字符串大小以防止緩沖區溢出。
FILE *fp = open_file(old_file_name, "rt");
char line[1024];
while (fgets(line, 1024, fp)) {
//copy all the users except the user to delete the new file
if( sscanf(fp, "%255s %255s\n", user_name_to_copy, password_to_copy) != 2 ) {
fprintf(stderr, "Couldn't understand line '%s'\n", line);
continue;
}
if (strcmp(user_name_to_copy, user_name)) {
fprintf(new_file, "%s %s\n", user_name_to_copy, password_to_copy);
}
}
fclose(fp);
由於檢查文件是否打開是多余的,我建議寫一個小功能來做到這一點。
FILE *open_file(char *filename, char *mode) {
FILE *fp = fopen(filename, mode);
if( fp == NULL ) {
fprintf(
stderr, "Could not open '%s' for '%s': %s\n",
filename, mode, strerror(errno)
);
exit(1);
}
return fp;
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.