2012-01-18 76 views
1

我的函數寫入到文件中:的fscanf()不與輸入工作

Record_t * load_Record(FILE * infile) 
{ 
    Record_t *r; 
    char title[TITLE_SIZE]; 
    char [MEDIUM_SIZE]; 
    int ID, rating; 
    if ((fscanf(infile,"%d: %s %d", &ID, medium, &rating) != 3 && fgets(title, TITLE_SIZE, infile))){ 
      return NULL; 
    } 
    printf("medium is: %s title is: %s\n", medium, title); 
    r = create_Record(medium, title); 
    set_Record_rating(r, rating); 
    return r; 
} 

其中Record_t定義爲:

typedef struct Record { 
    int ID; 
    char * title; 
    char * medium; 
    int rating; 
} Record_t; 

我的主要:

#include "Record.h" 

#include <stdlib.h> 

int main() 
{ 

    char * title = "The Queen"; 
    char * medium = "DVD"; 
    FILE * pfile ; 
    struct Record *t = create_Record(medium, title); //creates a record 
    struct Record *s; 
    set_Record_rating (t, 3); 
    print_Record(t); 
    pfile = fopen("output.txt", "w"); 
    save_Record(t, pfile); 
    fclose(pfile); 
    destroy_Record(t); //de-allocates memory 
    pfile = fopen("output.txt", "r"); 
    if(!(s = load_Record(pfile))){ 
     return 1; 
    } 
    print_Record(s); 
    fclose(pfile); 
    destroy_Record(s);  
    return 0; 
} 

輸出。 txt寫入文件後:

1: DVD 3 The Queen //checked for excess whitespace(has newline however) 

端子輸出:

1: The Queen DVD 3 
medium is: DVD title is: � //title being saved inappropriately 
          @ 
2: � 
    @ DVD 3 

現在我與fgets功能是錯誤的!出於某種原因,標題被不適當地保存

我對下列標誌編譯: GCC -ansi -std = C89 -pedantic -Wmissing的原型-Wall test.c的Record.c -o測試

其中test.c的是我的主要

+1

您尚未爲您的緩衝區分配任何內存,即「medium」。事實上,在使用它之前,你甚至不會初始化變量。 – 2012-01-18 02:11:38

回答

4
char * medium; 

這應該是

char medium[SOME_CONSTANT]; // or char* medium = malloc(x); if you need the 
          // memory to persist after the function returns 

所以你實際有medium指向你自己的一些記憶。現在,您的指針指向垃圾,並且您期望fscanf將字符串保存在指向的內存中。

如果一個函數似乎返回一個指向某個神奇創建的內存的指針,那麼最好檢查兩次文檔(除非該函數碰巧是愚蠢的strdup)。該函數實際上需要一個指向某個已分配內存的指針,或者返回一個指向指向由malloc家族中的某個人分配的內存塊的指針,在這種情況下,您需要負責解除分配它。

只有在極少數的情況下做函數返回一個指向內存不以預先分配的緩存中,並且不必malloc d它(尤其時返回的字符串是不可預知的大小就像是fscanf)。

+0

我將我的代碼更改爲包含以下內容: – Layla 2012-01-18 02:22:16

+0

@LeilaHejazi對不起,我看不到您寫的內容。 – 2012-01-18 02:25:14

+0

我把這個檢查改爲!= 3並且改變了'char medium [7]',但是現在出於某種原因,我的「標題」字符串沒有被正確地讀取.... 1:Queen DVD 3介質是:DVD標題是:(null)2:(null)DVD 3' – Layla 2012-01-18 02:31:30

2

您還沒有分配的緩衝區中:

char * medium; 

這只是創建一個指向字符叫做媒體,你沒有任何保留的內存空間來讀入。這將分配256個字節(允許你閱讀最多256個字符)的介質:

medium = malloc(256); 

或者你可以在棧上分配:

char medium[256]; 

鑑於你有,我想問題建議在堆棧上使用分配,然後只需將結構讀寫到文件中 - 這樣可以節省您不必自己分析字段等,但會損失磁盤空間(可能會寫出大量空白字符),但這種浪費在這種情況下可以忽略不計。

fwrite(t, sizeof(Record_t), 1, pFile); 
fread(t, sizeof(Record_t), 1, pFile); 
+0

是的,我把它改成'char medium [APPROPRIATE SIZE]'和介質正確讀取以及其他所有內容,但是應該通過fgets獲得的標題。它沒有讀入它爲空。併產生以下輸出我改變了檢查!= 3並改變'字符中等[7]',但現在由於某種原因,我的「標題」字符串沒有被正確讀取....'1:皇后DVD 3中:DVD標題是:(null)2:(null)DVD 3' – Layla 2012-01-18 02:33:16

+0

您是否爲標題設置了緩衝區?在你的代碼中,它仍然是一個未初始化的指針,它可能不會崩潰(取決於它指向的位置),但不是你想要的! – 2012-01-18 03:28:00

+0

是的,我做到了!我做了一個適當的大小,但是當我這樣做時,它只是給了我垃圾.....就像一個「 @' – Layla 2012-01-18 04:01:00

1

幾種方法:

  1. 您還沒有分配的空間爲它讀串入。您需要:

    char medium[100]; 
    
  2. 你不檢查錯誤正確:

    if (!(fscanf(infile,"%d: %s %d", &ID, medium, &rating) 
    

    應該是:

    if (fscanf(infile,"%d: %s %d", &ID, medium, &rating) != 3 ... 
    

    你需要明確測試你得到你所期望的所有值讀書。

這是在沒有對所有代碼進行深入分析的情況下對錶面進行刮擦。請注意,您需要確保您沒有試圖將medium返回給調用代碼。如果create_record()做了合理的工作,這應該是確定的。 create_record()未被告知記錄ID很奇怪。

+0

我改變了檢查!= 3,並改變了'char medium [7]',但現在爲某些原因,我的「標題」字符串沒有被正確讀取....'1:女王DVD 3 中等是:DVD標題是:(null) 2:(null)DVD 3 ' – Layla 2012-01-18 02:31:01

+0

此外,記錄是一個靜態變量,每當內存動態分配給一個新的「記錄「這樣每個」create_Record()「函數都會自動處理。 – Layla 2012-01-18 02:35:10

+1

不要忘記'%s'格式讀取數據(或EOF)中的第一個空格。雖然7個字節對於'The'來說已經足夠了,但它沒有足夠的空間來存放其他任何東西。我不相信你應該在這個時候使用'scanf()'。 – 2012-01-18 03:26:42