सी

2011-01-27 6 views
27

में चरित्र द्वारा फ़ाइल चरित्र को पढ़ना हे सब, मैं सी में एक बीएफ दुभाषिया लिख ​​रहा हूं और मैंने फ़ाइलों को पढ़ने में समस्या में भाग लिया है। मैं पहली स्ट्रिंग को पढ़ने के लिए स्कैनफ़ का उपयोग करता था, लेकिन तब आपके पास बीएफ कोड में रिक्त स्थान या टिप्पणियां नहीं हो सकती थीं।सी

अभी मेरे पास है जो मेरे पास है।

char *readFile(char *fileName) 
{ 
    FILE *file; 
    char *code = malloc(1000 * sizeof(char)); 
    file = fopen(fileName, "r"); 
    do 
    { 
    *code++ = (char)fgetc(file); 

    } while(*code != EOF); 
    return code; 
} 

मैं जानता हूँ कि समस्या यह है कि मैं कोड सूचक करने के लिए फ़ाइल में अगले चार बताए कर रहा हूँ में उठता है, लेकिन मैं सिर्फ यह सुनिश्चित करें कि क्या है नहीं कर रहा हूँ।
मेरे सूचक ज्ञान की कमी है जो इस अभ्यास का मुद्दा है। दुभाषिया ठीक काम करता है, सभी पॉइंटर्स का उपयोग करते हुए, मुझे बस इसमें फाइलें पढ़ने में समस्या आ रही है।

(मैं केवल बाद में फ़ाइल में पढ़ने के लिए जा रहा हूं "+ -> < []।" फाइल में बाद में, हालांकि अगर किसी के पास ऐसा करने का अच्छा तरीका है, तो यह अच्छा होगा अगर आप मुझे बताएंगे !)

धन्यवाद अग्रिम में

उत्तर

32

वहाँ चीजों के एक नंबर अपने कोड के साथ गलत कर रहे हैं:

char *readFile(char *fileName) 
{ 
    FILE *file; 
    char *code = malloc(1000 * sizeof(char)); 
    file = fopen(fileName, "r"); 
    do 
    { 
     *code++ = (char)fgetc(file); 

    } while(*code != EOF); 
    return code; 
} 
  1. क्या होगा अगर फ़ाइल से अधिक 1,000 बाइट्स है?
  2. आप code वृद्धि हो रही है हर बार जब आप एक चरित्र पढ़ा है, और आप code वापस लौटने फोन करने वाले (भले ही यह अब स्मृति ब्लॉक की पहली बाइट पर इशारा करते हुए के रूप में यह malloc द्वारा दिया गया था) के लिए।
  3. आप fgetc(file) से char के परिणाम कास्टिंग कर रहे हैं। char पर परिणाम कास्टिंग करने से पहले आपको EOF की जांच करने की आवश्यकता है।

malloc द्वारा लौटा गया मूल सूचक बनाए रखना महत्वपूर्ण है ताकि आप इसे बाद में मुक्त कर सकें। हम फ़ाइल आकार उपेक्षा, तो हम निम्न के साथ अभी भी इस लक्ष्य को हासिल कर सकते हैं:

char *readFile(char *fileName) 
{ 
    FILE *file = fopen(fileName, "r"); 
    char *code; 
    size_t n = 0; 
    int c; 

    if (file == NULL) 
     return NULL; //could not open file 

    code = malloc(1000); 

    while ((c = fgetc(file)) != EOF) 
    { 
     code[n++] = (char) c; 
    } 

    // don't forget to terminate with the null character 
    code[n] = '\0';   

    return code; 
} 

विभिन्न सिस्टम कॉल है कि आप एक फ़ाइल के आकार दे देंगे कर रहे हैं; एक आम एक stat है।

+0

फ़ाइल में वर्णों की संख्या को गिनने का सबसे आसान तरीका क्या है, इसलिए मैं इसे "1000" सेट कर सकता हूं? इसके अलावा मुझे बिल्कुल यकीन नहीं है कि आपका नंबर 2 से क्या मतलब है, मैं समझता हूं कि मैं इस तरह से गलत कर रहा हूं, लेकिन मैं इसे कैसे संशोधित करूं? –

+0

@pwnmonkey: मेरा मतलब यह है कि आप 'कोड' वापस कर रहे हैं, जबकि यह फ़ाइल के * अंत * को इंगित कर रहा है, न कि यह शुरुआत की ओर इशारा करता है। – dreamlax

+0

ओह ठीक है आपने इसे संपादित किया, धन्यवाद! –

2

मुझे लगता है कि सबसे महत्वपूर्ण समस्या यह है कि आप code incrementing रहे हैं आप में सामान को पढ़ने के रूप में, और उसके बाद code के अंतिम मूल्य लौटने, यानी आप स्ट्रिंग के अंत के लिए सूचक लौट जाने वाली राशि है। आप शायद लूप से पहले code की एक प्रति बनाना चाहते हैं, और इसके बदले में वापस आएं।

इसके अलावा, सी तारों को निरस्त करने की आवश्यकता है। आपको यह सुनिश्चित करना है कि आप सीधे अंतिम चरित्र है कि आप में पढ़ा के बाद एक '\0' जगह बनाने की जरूरत है

नोट:। तुम बस fgets() का उपयोग एक हिट में पूरे लाइन प्राप्त करने के लिए कर सकता है।

+0

या पूरी फ़ाइल को पढ़ने के लिए फ़्रेड का उपयोग करें। –

+0

ठीक है लेकिन मैं कुछ भी बाहर करने जा रहा हूं जो बीएफ कोड नहीं है, इसलिए इसे एक रन में जाना आसान है। –

1

दो की या तो चाल करना चाहिए -

char *readFile(char *fileName) 
{ 
    FILE *file; 
    char *code = malloc(1000 * sizeof(char)); 
    char *p = code; 
    file = fopen(fileName, "r"); 
    do 
    { 
    *p++ = (char)fgetc(file); 
    } while(*p != EOF); 
    *p = '\0'; 
    return code; 
} 

char *readFile(char *fileName) 
{ 
    FILE *file; 
    int i = 0; 
    char *code = malloc(1000 * sizeof(char)); 
    file = fopen(fileName, "r"); 
    do 
    { 
    code[i++] = (char)fgetc(file); 
    } while(code[i-1] != EOF); 
    code[i] = '\0' 
    return code; 
} 

अन्य पोस्टर की तरह ही बताया है, तो आप यह सुनिश्चित करें कि फ़ाइल आकार 1000 अक्षरों से अधिक नहीं है की जरूरत है।साथ ही, जब आप इसका उपयोग कर रहे हों तो स्मृति को मुक्त करना याद रखें।

1

यहां समस्या दो गुना है - ए) आप मूल्य को पढ़ने से पहले पॉइंटर बढ़ाते हैं, और बी) आप इस तथ्य को अनदेखा करते हैं कि fgetc() एक char के बजाय int int देता है।

पहले आसानी से तय हो गई है:

char *orig = code; // the beginning of the array 
// ... 
do { 
    *code = fgetc(file); 
} while(*code++ != EOF); 
*code = '\0'; // nul-terminate the string 
return orig; // don't return a pointer to the end 

दूसरी समस्या और अधिक सूक्ष्म है - fgetc EOF मूल्य sonthat किसी पूर्णांक किसी भी संभव chsr मूल्य से प्रतिष्ठित किया जा सकता देता है। इसे ठीक करने से ईओएफ चेक के लिए एक अस्थायी int का उपयोग होता है और संभवतः एक नियमित रूप से लूप को करने/बजाय करने के बजाए।

+1

यदि 'EOF' -1 और -128 के बीच कुछ भी है, तो वह *' char' मान के रूप में प्रतिनिधित्व योग्य है (कार्यान्वयन के सादे 'char' प्रकार पर हस्ताक्षर किए गए हैं)। इस मामले में, 'int' से' char' में रूपांतरण पूरी तरह से परिभाषित किया जाता है जब मान 'char' द्वारा प्रदर्शित किया जा सकता है, जो' EOF' के मामले में हो सकता है। – dreamlax

+0

मैं हस्ताक्षरित का उपयोग कर रहा हूँ। –

2

यहाँ सब कुछ है, लेकिन वैध brainfuck पात्रों की अनदेखी करने के एक आसान तरीका है:

#define BF_VALID "+-><[].," 

if (strchr(BF_VALID, c)) 
    code[n++] = c; 
+0

हाँ, मैं पहले इसका उपयोग कर रहा था, लेकिन समस्या यह है कि अगर फ़ाइल में नई लाइनें हैं तो यह स्ट्रिंग के भीतर उन नई पंक्तियों को रखती है। यदि मैं एक पंक्ति में एक फ़ाइल में शुद्ध बीएफ कोड लिखना चाहता हूं, या इसे कंसोल पर प्रिंट करना चाहता हूं तो कौन सा बुरा है। –

+1

@pwnmonkey: नहीं, यह किसी भी नए अक्षरों को गंतव्य स्ट्रिंग में संग्रहीत नहीं करेगा (यदि आपने 'BF_VALID' में' \ n' जोड़ा है, तो यह होगा)। – caf

2

फ़ाइल खोला जा रहा है और समारोह भी

+0

हाँ मुझे पता है, मैंने पहले ही इसे बदल दिया था लेकिन मुझे बताने के लिए धन्यवाद। –

7

@dreamlax से ऊपर कोड पर विस्तार करने के लिए प्रत्येक कॉल के लिए बंद नहीं

char *readFile(char *fileName) { 
    FILE *file = fopen(fileName, "r"); 
    char *code; 
    size_t n = 0; 
    int c; 

    if (file == NULL) return NULL; //could not open file 
    fseek(file, 0, SEEK_END); 
    long f_size = ftell(file); 
    fseek(file, 0, SEEK_SET); 
    code = malloc(f_size); 

    while ((c = fgetc(file)) != EOF) { 
     code[n++] = (char)c; 
    } 

    code[n] = '\0';   

    return code; 
} 

यह आपको फ़ाइल की लंबाई देता है, फिर चरित्र द्वारा चरित्र को पढ़ने के लिए आगे बढ़ता है।

+0

क्या आप समझा सकते हैं कि कैसे fseek और ftell काम करते हैं? मुझे लगता है कि फ़ाइल के पात्रों की गणना करने के लिए आपको किसी प्रकार की लूप की आवश्यकता होगी। – cokedude

+1

एक कर्सर को पुनर्स्थापित करने के तरीके के रूप में 'fseek' के बारे में सोचें। fseek (फ़ाइल, 0, SEEK_END); कर्सर को फ़ाइल के अंत में रखता है, फिर 'ftell' आपको बताता है कि कर्सर कहां है। यह आपको फ़ाइल का आकार देता है। 'fseek (फ़ाइल, 0, SEEK_SET);' कर्सर को फ़ाइल की शुरुआत में वापस रखता है ताकि इसे पढ़ा जा सके। यदि आप ऐसा नहीं करते हैं, तो आप अंत से फ़ाइल को पढ़ना शुरू कर देंगे, जो त्रुटियों का कारण बन जाएगा और पूरे ऑपरेशन को बर्बाद कर देगा। – Justin