2012-11-24 33 views
2

程序應根據員工ID修改或刪除特定記錄,修改部分將修改後的記錄作爲新文件寫入文件末尾,刪除部分只工作一次,然後給我一個分段錯誤。編輯/修改和刪除從隨機訪問文件中的記錄C

修改:

我如何可以修改代碼改寫編輯的記錄在同一位置?

#include <stdio.h> 
#include <string.h> 
#include <stdlib.h> 
#include <stdlib.h> 

struct record_em{ 
    int id; 
    char name[20]; 
    int salary; 
    int age; 
}; 

int main(void) 
{ 
    struct record_em employee; 
    FILE *fp; 
    int n; 
    int ch; 
    fp = fopen("empRecord.dat","rb+"); 

    printf("Enter Id Number:\n"); 
    scanf("%d",&n); 
    rewind(fp); 
    while (!feof(fp)){ 

     fscanf(fp,"%d %s %d %d", &employee.id, employee.name, &employee.salary, &employee.age); 

     if (employee.id==n){ 
      printf("%d %s %d %d \n",employee.id, employee.name, employee.salary,employee.age); 
      printf("\n Do you want to change the name ?\n"); 
      scanf("%d",&ch); 

      if (ch==1){ 
       printf("Enter new name:\n"); 
       scanf("%s",employee.name); 
      } 
      printf("\n Do you want to change the salary ?(y/n)\n"); 
      scanf("%d",&ch); 

      if (ch==2){ 
       printf("Enter new salary:\n"); 
       scanf("%d",&employee.salary); 
      } 
      printf("\n Do you want to change the age ?(y/n)\n"); 
      scanf("%d",&ch); 

      if (ch==3){ 
       printf("Enter new age:\n"); 
       scanf("%d",&employee.age); 
      } 
      fseek(fp,-sizeof(employee),SEEK_CUR); 
      fprintf(fp, "%d %s %d %d\n", employee.id, employee.name, employee.salary, employee.age); 
      exit(0); 
     } 
    } 
    printf("Record Not Found \n"); 
    return 0; 
} 

刪除:

我如何修改代碼,使其刪除記錄,因爲我想盡可能多的時間?

#include <stdio.h> 
#include <string.h> 
#include <stdlib.h> 
#include <stdlib.h> 

struct record_em{ 
    int id; 
    char name[20]; 
    int salary; 
    int age; 
}; 

int main() 
{ 
    struct record_em employee; 
    FILE *fp, *ft; 
    int n; 
    fp = fopen("empRecord.dat","r"); 
    ft = fopen("Temp.dat","wb+"); 

    printf("\nEnter ID of employee to delete "); 

    scanf("%d",&n); 
    rewind(fp); 
    while (!feof(fp)){ 
     fscanf(fp,"%d %s %d %d", &employee.id, employee.name, &employee.salary, &employee.age); 

     if(employee.id!=n){ 
      fprintf(ft, "%d %s %d %d\n", employee.id, employee.name, employee.salary, employee.age); 
     } 
    } 

    fclose(fp); 
    fclose(ft); 
    remove("empRecord.dat"); 
    rename("Temp.dat","EempRecord.dat"); 

    return 0; 
} 
+0

您可以保存信息塊的偏移量並覆蓋該偏移量的更改數據。請檢查fseek()。 –

+0

@tAmirNaghizadeh Um。不,他不能。這個記錄定義雖然固定在他的代碼的「struct」中,但是由於他將它寫入磁盤(因爲它是文本翻譯)而不同。使字符串表示*這些字段中的任何*大於先前的字段,並且至少覆蓋一個後續記錄中的數據。 – WhozCraig

+0

Right ..,由於換行符被換行符隔開,所以他可以在'getline()'報告的每一行的第一個重新編碼中使用'strcmp()'。 –

回答

1

使用C函數操作二進制文件並不好,這些C函數用於處理文本文件fprintf。

例如,在你的代碼中,我看到:

fseek(fp,-sizeof(employee),SEEK_CUR); 
fprintf(fp, "%d %s %d %d\n", employee.id, employee.name, employee.salary, employee.age); 

這會給你帶來問題,因爲你是你的文件中行駛的二進制文件,然後在其上寫字。你應該使用fwrite函數。

我的建議:檢查您的整個程序,定義您的持久性策略並與此保持一致。

+0

當我使用fwrite我不能有一個純文本文件 – fatimah

+0

@fatimah這是你的值的文本內容的可變性,使這個任務比它需要更大的瑣事。使用固定的二進制記錄長度將使掃描記錄,在原地修改它們,並將它們標記爲已刪除*微不足道*。 – WhozCraig

+0

@WhozCraig我會嘗試使用一個固定的二進制記錄,看看會發生什麼:),非常感謝 – fatimah

1

我覺得這裏是你的問題,首先你有一個減號sizeof之前,這是一個有點怪異看到,和第二的SEEK_CUR讓你比你當前的文件進一步舉動是那麼看看這裏fseek(), rewind()

fseek(fp,-sizeof(employee),SEEK_CUR); //This is not the definitive read below. 
     ^------minus symbol. ^------- the type of seek. 

我建議你做一些修改:

  1. 使用常見Formatted File,使您的生活更輕鬆,記住「完美是簡單」。

  2. 使用SEEK_SET使用的相對位置從文件的開頭,第二次使用struct's size作爲參數sizeof

    fseek(fp, sizeof(struct record_em), SEEK_SET); 
    
  3. 使用member id作爲水槽的密鑰,並用一系列連續的數字,但很明顯,你應該已經創建了一個文件,100,1000名僱主。

    1 Andrew 20000 27 
    ^ ^ ^ ^_____ age 
    | |  |__________ salary (I would have used double here) 
    | |_________________ name 
    |_____________________ id (Key for the relative position from the beginning) 
    
  4. 你將不得不改變你的想法,當你想象「刪除」你會寫一個空格(與鑰匙的除外)例如記錄想象一下,可憐的安德魯被解僱,你會刪除他的紀錄。

    1 "Empty space" 0 0 
    ^  ^  ^ ^______ age (0 = nothing) 
    |  |   |__________ salary (0 = nothing) 
    |  |____________________ name ("" = nothing) 
    |____________________________ id (Key for the relative position from the beginning) 
    

PD:目前增加更多的信息。

+0

OP使用'fseek(fp,-sizeof(employee),<>);' 「倒帶」是完全錯誤的。他通過使用非成幀(無固定寬度)格式化輸出和輸入來編寫「文本」內容來使用可變長度的「記錄」。 '1 Al 25000 20 \ n'遠不及12345華盛頓125000 42 \ n'的長度,但這就是他的「唱片」如何表現。如果他使用固定記錄,那麼通過增加'sizeof(employee)'來移動會很有意義,但是他不是***。這使得通過'id'查找,修改和刪除特定記錄是一項重大任務。 – WhozCraig

1
SEEK_CUR 

offset是相對於當前文件指針的位置。所以,實際上,你可以說,「移動到我目前的位置加上30個字節」,或者,「移動到我的當前位置減去20個字節」。 例如。 fseek(fp, -30, SEEK_CUR) ref。 http://beej.us/guide/bgc/output/html/multipage/fseek.html

我不認爲他在使用sizeof()函數的負數時是錯誤的。 但你最好用sizeof(struct record_em)代替!

1

這裏是代碼的關鍵點:

void update(char filename[],char name[]) 
{ 
    int records=0; 
    FILE *fp = fopen(filename,"rb+"); 
    while(fread(&st,sizeof(st),1,fp)==1) 
    { 
     if(strcmp(name,st.name)==0) 
     { 
       printf("\nEnter new name: "); 
       scanf("%s",st.name); 
       printf("\nEnter new roll no.: "); 
       scanf("%d",&st.roll); 
       fseek(fp,sizeof(struct student)*records,SEEK_SET);//This is key line.. 
       fwrite(&st,sizeof(st),1,fp); 
     } 
     records++; // in the while loop... 
    } 
    fclose(fp); 
} 

下面是學生的結構:

struct student{ 
    int roll; 
    char name[20]; 
}st; 

這是修改/更新記錄的一般方法。您可以對您的員工結構使用相同的語法。