সি লাইনে ফাইল লাইন পড়ুন


183

আমি এই ফাংশনটি একটি ফাইল থেকে একটি লাইন পড়তে লিখেছি:

const char *readLine(FILE *file) {

    if (file == NULL) {
        printf("Error: file pointer is null.");
        exit(1);
    }

    int maximumLineLength = 128;
    char *lineBuffer = (char *)malloc(sizeof(char) * maximumLineLength);

    if (lineBuffer == NULL) {
        printf("Error allocating memory for line buffer.");
        exit(1);
    }

    char ch = getc(file);
    int count = 0;

    while ((ch != '\n') && (ch != EOF)) {
        if (count == maximumLineLength) {
            maximumLineLength += 128;
            lineBuffer = realloc(lineBuffer, maximumLineLength);
            if (lineBuffer == NULL) {
                printf("Error reallocating space for line buffer.");
                exit(1);
            }
        }
        lineBuffer[count] = ch;
        count++;

        ch = getc(file);
    }

    lineBuffer[count] = '\0';
    char line[count + 1];
    strncpy(line, lineBuffer, (count + 1));
    free(lineBuffer);
    const char *constLine = line;
    return constLine;
}

ফাংশনটি ফাইলটি সঠিকভাবে পড়ে এবং প্রিন্টফ ব্যবহার করে দেখি কনস্টলাইন স্ট্রিংটিও সঠিকভাবে পড়তে পারে।

তবে আমি যদি ফাংশনটি ব্যবহার করি যেমন:

while (!feof(myFile)) {
    const char *line = readLine(myFile);
    printf("%s\n", line);
}

প্রিন্টফ আউটপুট গিব্বারিশ। কেন?


fgetsপরিবর্তে ব্যবহার করুন fgetc। আপনি লাইন বাই লাইনের পরিবর্তে চরিত্রটি পড়ছেন।
শিব

3
দ্রষ্টব্য এটি getline()পসিক্স ২০০ of এর একটি অংশ। এটি ছাড়া পসিক্সের মতো প্ল্যাটফর্ম থাকতে পারে, বিশেষত যদি তারা পোসিক্স বাকী ২০০ support সমর্থন না করে তবে পসিক্স সিস্টেমগুলির জগতের মধ্যে, getline()আজকাল বেশ পোর্টেবল।
জোনাথন লেফলার 21

উত্তর:


304

যদি আপনার কাজটি লাইন বাই লাইন পড়ার ফাংশনটি আবিষ্কার না করে তবে কেবল ফাইল লাইন বাই লাইন পড়ার জন্য, আপনি getline()ফাংশনটি যুক্ত একটি সাধারণ কোড স্নিপেট ব্যবহার করতে পারেন (ম্যানুয়াল পৃষ্ঠাটি এখানে দেখুন ):

#define _GNU_SOURCE
#include <stdio.h>
#include <stdlib.h>

int main(void)
{
    FILE * fp;
    char * line = NULL;
    size_t len = 0;
    ssize_t read;

    fp = fopen("/etc/motd", "r");
    if (fp == NULL)
        exit(EXIT_FAILURE);

    while ((read = getline(&line, &len, fp)) != -1) {
        printf("Retrieved line of length %zu:\n", read);
        printf("%s", line);
    }

    fclose(fp);
    if (line)
        free(line);
    exit(EXIT_SUCCESS);
}

82
এটি পোর্টেবল নয়।
জেরেমিপ

16
আরও স্পষ্টভাবে, এটি getlineGNU libc, যেমন লিনাক্সের ক্ষেত্রে নির্দিষ্ট। তবে, যদি অভিপ্রায়টি একটি লাইন-পঠন ফাংশন (সি শেখার বিপরীতে) থাকে তবে ওয়েবে বেশ কয়েকটি পাবলিক ডোমেন লাইন-রিডিং ফাংশন উপলব্ধ।
গিলস 'অশুভ হওয়া বন্ধ করুন'

11
আমি কেন এইটা করব? ম্যানুয়ালটি পড়ুন, প্রতিটি কলটিতে বাফার পুনরায় স্থানান্তরিত হয়, তারপরে এটি শেষে মুক্ত করা উচিত।
এমবাইটফ

29
if(line)চেক প্রযোজন নেই। কলিং free(NULL)মূলত একটি অনিচ্ছুক।
28:25

49
যারা বলেছিলেন যে এই গেটলাইনটি জিএনইউ লিবিসি-র সাথে সুনির্দিষ্ট, "গেটলাইন () এবং গেটডেলিম () উভয়ই মূলত জিএনইউ এক্সটেনশান ছিল P তারা পসিক্স ১.২-২০০৮ এ প্রমিত করা হয়েছিল।"
willkill07

37
FILE* filePointer;
int bufferLength = 255;
char buffer[bufferLength];

filePointer = fopen("file.txt", "r");

while(fgets(buffer, bufferLength, filePointer)) {
    printf("%s\n", buffer);
}

fclose(filePointer);

আমার জন্য এটি পরবর্তী প্রতিটি লাইন ওভাররাইটিংয়ের ফলাফল। উপরের উত্তরের ভিত্তিতে এই প্রশ্নটি দেখুন ।
সেজার কোবুজ

5
Theালাই কেন (FILE*) fp? fpইতিমধ্যে একটি হয় না FILE *এবং এটিও fopen()ফিরে আসে FILE *?
হিসাবরক্ষক

1
লাইনগুলি নির্দিষ্ট দৈর্ঘ্যের মধ্যে সীমাবদ্ধ থাকলে আপনি যদি ঠিক থাকেন তবে এটি সেরা উত্তর। অন্যথায় ব্যবহার getlineকরা একটি ভাল বিকল্প। আমি সম্মত the FILE *ালাই অপ্রয়োজনীয়।
থিসফায়ার

আমি অ-প্রয়োজনীয় ঢালাই সরিয়ে বাফার দৈর্ঘ্যের জন্য একটি পরিবর্তনশীল জুড়েছে এবং পরিবর্তিত fpকরা filePointerআরো স্বচ্ছতার জন্য।
রব

21

আপনার readLineকার্যক্রমে আপনি lineঅ্যারেতে একটি পয়েন্টার ফিরিয়ে দেন (কঠোরভাবে বলতে গেলে তার প্রথম চরিত্রের জন্য একটি পয়েন্টার, তবে পার্থক্যটি এখানে অপ্রাসঙ্গিক)। যেহেতু এটি একটি স্বয়ংক্রিয় পরিবর্তনশীল (যেমন এটি "স্ট্যাকের উপরে") রয়েছে, সুতরাং ফাংশনটি ফিরে আসার সাথে সাথে স্মৃতি পুনরুদ্ধার হয়। আপনি গীবির দেখতে পাচ্ছেন কারণ printfতার নিজস্ব স্ট্যাকগুলি স্ট্যাকের উপর রেখেছেন।

আপনাকে ফাংশন থেকে গতিশীলভাবে বরাদ্দ করা বাফারটি ফিরিয়ে দিতে হবে। আপনার ইতিমধ্যে একটি আছে, এটি lineBuffer; আপনাকে যা করতে হবে তা হ'ল এটি কাঙ্ক্ষিত দৈর্ঘ্যে ছিন্ন করা।

    lineBuffer[count] = '\0';
    realloc(lineBuffer, count + 1);
    return lineBuffer;
}

যুক্ত (মন্তব্যে ফলো-আপ প্রশ্নের প্রতিক্রিয়া): readLineলাইনটি তৈরি করে এমন অক্ষরগুলিতে একটি পয়েন্টার দেয়। এই পয়েন্টারটি হ'ল লাইনের বিষয়বস্তুগুলির সাথে আপনার কী কাজ করা উচিত। আপনি freeযখন এই চরিত্রগুলির দ্বারা নেওয়া স্মৃতি ব্যবহার করে শেষ করেছেন তখন আপনাকে কী পাস করতে হবে তাও । আপনি কীভাবে এই readLineফাংশনটি ব্যবহার করতে পারেন তা এখানে :

char *line = readLine(file);
printf("LOG: read a line: %s\n", line);
if (strchr(line, 'a')) { puts("The line contains an a"); }
/* etc. */
free(line);
/* After this point, the memory allocated for the line has been reclaimed.
   You can't use the value of `line` again (though you can assign a new value
   to the `line` variable if you want). */

@ আয়রন: আমি আমার উত্তরে কিছু যুক্ত করেছি, তবে আমি নিশ্চিত নই যে আপনার অসুবিধা কী তাই এটি চিহ্ন থেকে দূরে থাকতে পারে।
গিলস 'অশুভ হওয়া বন্ধ করুন'

@ আয়রন: উত্তরটি হ'ল আপনি এটিকে মুক্ত করেন না। আপনি ডকুমেন্টটি (এপিআই ডকুমেন্টেশনে) ফিরে আসা বাফারকে ম্যাসাচ'র উত্তর দেওয়া হয়নি তা কলকারীদের দ্বারা মুক্ত করা দরকার। তারপরে আপনার রিডলাইন ফাংশনটি ব্যবহার করা লোকেরা (আশা করি!) গিলিস তার উত্তরে যুক্ত হওয়া স্নিপেটের অনুরূপ কোড লিখবে।
জেরেমিপ

14
//open and get the file handle
FILE* fh;
fopen_s(&fh, filename, "r");

//check if file exists
if (fh == NULL){
    printf("file does not exists %s", filename);
    return 0;
}


//read line by line
const size_t line_size = 300;
char* line = malloc(line_size);
while (fgets(line, line_size, fh) != NULL)  {
    printf(line);
}
free(line);    // dont forget to free heap memory

1
এই fopen_sকোডটিতে কিছু সমস্যা রয়েছে: কোডটি অপ্রয়োজনীয় করে তোলে। printfফর্ম্যাট স্পেসিফায়ারদের সন্ধান করবে এবং শতাংশের লক্ষণ এবং নীচের অক্ষর (গুলি) যেমনটি রয়েছে তেমন মুদ্রণ করবে না । নাল বাইটগুলি বাকী রেখার সমস্ত অক্ষর তৈরি করে দেবে। (আমাকে নাল বাইটগুলি ঘটতে পারে না বলুন!)
হ্যাজেলো

এবং যাইহোক, আপনি সমস্যার সমাধান করবেন না। ওপি বর্ণনা করে যে তার ফাংশনের রিটার্ন মান অদৃশ্য হয়ে যায়। আমি আপনাকে এই সমস্যার সমাধান করতে দেখছি না।
হ্যাজেলো

@ হার্টলি আমি জানি এটি একটি পুরানো মন্তব্য, তবে আমি এটি যুক্ত করছি যাতে কেউ তাঁর মন্তব্য না পড়ে এবং লুপে (লাইন) মুক্ত করার চেষ্টা না করে। লুপটি শুরু হওয়ার আগে লাইনের জন্য মেমরি কেবল একবার বরাদ্দ করা হয়, সুতরাং লুপটি শেষ হওয়ার পরে এটি কেবল একবার মুক্ত করা উচিত। যদি আপনি লুপের ভিতরে লাইনটি মুক্ত করার চেষ্টা করেন তবে আপনি অপ্রত্যাশিত ফলাফল পাবেন। কীভাবে মুক্ত () পয়েন্টারের সাথে আচরণ করে তার উপর নির্ভরশীল। যদি এটি কেবল মেমোরিটিকে অস্বীকার করে এবং কোডটি কাজ করতে পারে এমন পুরানো স্থানে নির্দেশকারীকে ছেড়ে যায়। যদি এটি পয়েন্টারকে অন্য মান নির্ধারণ করে তবে আপনি মেমরির একটি পৃথক অংশ ওভাররাইট করে ফেলবেন।
অ্যালানিয়ান

2
প্রিন্টফ (লাইন) ভুল! এটা করো না. এটি আপনার কোডটিকে একটি স্ট্রিং বিন্যাসের দুর্বলতায় উন্মুক্ত করে যেখানে আপনি মুদ্রণযোগ্য স্টাফের মাধ্যমে মেমরিতে সরাসরি অবাধে পড়তে / লিখতে পারবেন। যদি আমি ফাইলটিতে% n /% p স্থাপন করে এবং পয়েন্টারটিকে আমি নিয়ন্ত্রিত মেমরির (ফাইল থেকে স্ট্রিংয়ে) একটি ঠিকানার দিকে নির্দেশ করি তবে আমি সেই কোডটি কার্যকর করতে পারি।
অক্সগাস্ট

10

readLine() স্থানীয় পরিবর্তনশীলকে পয়েন্টার দেয়, যা অপরিবর্তিত আচরণের কারণ হয়।

কাছাকাছি যেতে আপনি করতে পারেন:

  1. কলার ফাংশনে ভেরিয়েবল তৈরি করুন এবং এর ঠিকানাটি এতে প্রেরণ করুন readLine()
  2. lineব্যবহারের জন্য মেমরি বরাদ্দ করুন malloc()- এক্ষেত্রে অবিচল lineথাকবে
  3. গ্লোবাল ভেরিয়েবল ব্যবহার করুন, যদিও এটি সাধারণত একটি খারাপ অভ্যাস


4

উদাহরণ সহ কিছু জিনিস ভুল:

  • আপনি আপনার মুদ্রণগুলিতে \ n যুক্ত করতে ভুলে গেছেন। এছাড়াও ত্রুটি বার্তাগুলি স্ট্যাডারে যাওয়া উচিতfprintf(stderr, ....
  • (একটি বড় কথা নয়) fgetc()বরং ব্যবহারের কথা বিবেচনা করুন getc()getc()একটি ম্যাক্রো, fgetc()একটি সঠিক ফাংশন
  • getc()প্রত্যাবর্তন intতাই chএকটি হিসাবে ঘোষণা করা উচিত int। এটি গুরুত্বপূর্ণ কারণ যেহেতু তুলনাটি EOFসঠিকভাবে পরিচালনা করা হবে। কিছু 8 বিট অক্ষর সেট 0xFFবৈধ অক্ষর হিসাবে ব্যবহার করে (আইএসও-ল্যাটিন EOF-১ একটি উদাহরণ হতে পারে) এবং যা -1 হয়, এটিতে 0xFFনির্ধারিত হলে তা হবে char
  • লাইনে একটি সম্ভাব্য বাফার ওভারফ্লো রয়েছে

    lineBuffer[count] = '\0';

    যদি লাইনটি 128 টি অক্ষর দীর্ঘ countহয় তবে নির্ধারিত স্থানে 128 হয়।

  • অন্যরা যেমন উল্লেখ করেছে, lineএটি স্থানীয়ভাবে ঘোষিত অ্যারে। আপনি এটিতে কোনও পয়েন্টার ফিরিয়ে দিতে পারবেন না।

  • strncpy(count + 1)সর্বাধিক count + 1অক্ষরগুলি অনুলিপি করবে তবে এটি যদি হিট হয়ে যায় তবে শেষ হবে '\0' কারণ আপনি সেট করে lineBuffer[count]দিয়েছিলেন '\0'যে এটি কখনই পাবেন না count + 1। যাইহোক, যদি এটি হয়ে থাকে তবে এটি একটি সমাপ্তি স্থাপন করবে না '\0', সুতরাং আপনার এটি করা দরকার। আপনি প্রায়শই নীচের মতো কিছু দেখতে পান:

    char buffer [BUFFER_SIZE];
    strncpy(buffer, sourceString, BUFFER_SIZE - 1);
    buffer[BUFFER_SIZE - 1] = '\0';
  • যদি আপনি malloc()ফিরে আসার জন্য একটি লাইন থাকেন (আপনার স্থানীয় charঅ্যারের জায়গায় ), আপনার রিটার্নের ধরণটি char*হ'ল - ড্রপ করুন const


2
void readLine(FILE* file, char* line, int limit)
{
    int i;
    int read;

    read = fread(line, sizeof(char), limit, file);
    line[read] = '\0';

    for(i = 0; i <= read;i++)
    {
        if('\0' == line[i] || '\n' == line[i] || '\r' == line[i])
        {
            line[i] = '\0';
            break;
        }
    }

    if(i != read)
    {
        fseek(file, i - read + 1, SEEK_CUR);
    }
}

এটা কেমন?


2

এখানে আমার বেশ কয়েক ঘন্টা ... পুরো ফাইলটি লাইন দিয়ে পঠন।

char * readline(FILE *fp, char *buffer)
{
    int ch;
    int i = 0;
    size_t buff_len = 0;

    buffer = malloc(buff_len + 1);
    if (!buffer) return NULL;  // Out of memory

    while ((ch = fgetc(fp)) != '\n' && ch != EOF)
    {
        buff_len++;
        void *tmp = realloc(buffer, buff_len + 1);
        if (tmp == NULL)
        {
            free(buffer);
            return NULL; // Out of memory
        }
        buffer = tmp;

        buffer[i] = (char) ch;
        i++;
    }
    buffer[i] = '\0';

    // Detect end
    if (ch == EOF && (i == 0 || ferror(fp)))
    {
        free(buffer);
        return NULL;
    }
    return buffer;
}

void lineByline(FILE * file){
char *s;
while ((s = readline(file, 0)) != NULL)
{
    puts(s);
    free(s);
    printf("\n");
}
}

int main()
{
    char *fileName = "input-1.txt";
    FILE* file = fopen(fileName, "r");
    lineByline(file);
    return 0;
}

1
আপনি fgetcপরিবর্তে ব্যবহার করছেন কেন fgets?
থিসফায়ার

1
const char *readLine(FILE *file, char* line) {

    if (file == NULL) {
        printf("Error: file pointer is null.");
        exit(1);
    }

    int maximumLineLength = 128;
    char *lineBuffer = (char *)malloc(sizeof(char) * maximumLineLength);

    if (lineBuffer == NULL) {
        printf("Error allocating memory for line buffer.");
        exit(1);
    }

    char ch = getc(file);
    int count = 0;

    while ((ch != '\n') && (ch != EOF)) {
        if (count == maximumLineLength) {
            maximumLineLength += 128;
            lineBuffer = realloc(lineBuffer, maximumLineLength);
            if (lineBuffer == NULL) {
                printf("Error reallocating space for line buffer.");
                exit(1);
            }
        }
        lineBuffer[count] = ch;
        count++;

        ch = getc(file);
    }

    lineBuffer[count] = '\0';
    char line[count + 1];
    strncpy(line, lineBuffer, (count + 1));
    free(lineBuffer);
    return line;

}


char linebuffer[256];
while (!feof(myFile)) {
    const char *line = readLine(myFile, linebuffer);
    printf("%s\n", line);
}

নোট করুন যে 'লাইন' ভেরিয়েবল কলিং ফাংশনে ঘোষিত হয় এবং তারপরে পাস হয়ে যায়, সুতরাং আপনার readLineফাংশনটি পূর্বনির্ধারিত বাফারটি পূরণ করে এবং কেবল এটি ফিরিয়ে দেয়। বেশিরভাগ সি লাইব্রেরি এভাবেই কাজ করে।

অন্যান্য উপায় আছে, যা সম্পর্কে আমি সচেতন:

  • char line[]স্থির হিসাবে সংজ্ঞায়িত ( static char line[MAX_LINE_LENGTH] -> এটি ফাংশন থেকে ফিরে আসার পরে এটির মান ধারণ করবে)। -> খারাপ, ফাংশনটি তত্পর হয় না এবং বর্ণের পরিস্থিতি দেখা দিতে পারে -> আপনি যদি দুটি থ্রেড থেকে দু'বার কল করেন তবে ফলাফলটি ওভাররাইট হবে
  • malloc()চর লাইনটি [] যুক্ত করা, এবং কলিং ফাংশনগুলিকে মুক্ত করে -> অনেক ব্যয়বহুল mallocএস, এবং, বাফারকে অন্য কোনও কার্যে মুক্ত করার দায়িত্ব অর্পণ করা (সর্বাধিক মার্জিত সমাধানটি কল করা mallocএবং freeএকই ফাংশনে যে কোনও বাফারকে দেওয়া)

BTW, থেকে 'স্পষ্ট' ঢালাই char*করার const char*অপ্রয়োজনীয়।

বিটিডব্লু 2, লাইনফুফারের কোনও দরকার নেই malloc(), কেবল এটি সংজ্ঞায়িত করুন char lineBuffer[128], সুতরাং আপনার এটি মুক্ত করার দরকার নেই

বিটিডব্লিউ 3 'গতিশীল আকারের স্ট্যাক অ্যারে' ব্যবহার করবে না (অ্যারের হিসাবে সংজ্ঞা দিচ্ছে char arrayName[some_nonconstant_variable]), আপনি কী করছেন তা যদি আপনি সঠিকভাবে জানেন না, তবে এটি কেবল সি 99 এ কাজ করে।


1
নোট করুন যে 'লাইন' ভেরিয়েবল কলিং ফাংশনে ঘোষণা করা হয় এবং তারপরে পাস হয়ে যায় - আপনার সম্ভবত সেই ফাংশনে লাইনটির স্থানীয় ঘোষণা মুছে ফেলা উচিত ছিল। এছাড়াও, আপনাকে ফাংশনটি বলতে হবে যে বাফারটি আপনি কতটা দীর্ঘ সময় পার করছেন এবং আপনার যে বাফারটি পেরিয়ে গেছে তার জন্য লম্বা লাইনগুলি পরিচালনা করার জন্য একটি কৌশলটি
ভাবা উচিত

1

লাইন পড়ার জন্য আপনার এএনএসআই ফাংশন ব্যবহার করা উচিত, যেমন। fgets। কল করার পরে আপনার কলিং প্রসঙ্গে বিনামূল্যে () প্রয়োজন, যেমন:

...
const char *entirecontent=readLine(myFile);
puts(entirecontent);
free(entirecontent);
...

const char *readLine(FILE *file)
{
  char *lineBuffer=calloc(1,1), line[128];

  if ( !file || !lineBuffer )
  {
    fprintf(stderr,"an ErrorNo 1: ...");
    exit(1);
  }

  for(; fgets(line,sizeof line,file) ; strcat(lineBuffer,line) )
  {
    if( strchr(line,'\n') ) *strchr(line,'\n')=0;
    lineBuffer=realloc(lineBuffer,strlen(lineBuffer)+strlen(line)+1);
    if( !lineBuffer )
    {
      fprintf(stderr,"an ErrorNo 2: ...");
      exit(2);
    }
  }
  return lineBuffer;
}

1

পড়ার পদ্ধতিটি প্রয়োগ করুন এবং কোনও ফাইল থেকে ইনপুট পান (ইনপুট 1.টিএসটিএসটি)

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

void testGetFile() {
    // open file
    FILE *fp = fopen("input1.txt", "r");
    size_t len = 255;
    // need malloc memory for line, if not, segmentation fault error will occurred.
    char *line = malloc(sizeof(char) * len);
    // check if file exist (and you can open it) or not
    if (fp == NULL) {
        printf("can open file input1.txt!");
        return;
    }
    while(fgets(line, len, fp) != NULL) {
        printf("%s\n", line);
    }
    free(line);
}

এই সাহায্য আশা করি। শুভ কোডিং!


0

আপনি একটি স্বয়ংক্রিয় ভেরিয়েবলে পয়েন্টার ফিরিয়ে দেওয়ার ভুল করেছেন। ভেরিয়েবল লাইনটি স্ট্যাকের মধ্যে বরাদ্দ করা হয় এবং কেবল ফাংশন যতক্ষণ বেঁচে থাকে ততক্ষণ বেঁচে থাকে। আপনাকে এতে কোনও পয়েন্টার ফেরত দেওয়ার অনুমতি নেই, কারণ এটি ফিরে আসার সাথে সাথেই অন্য কোথাও মেমরি দেওয়া হবে।

const char* func x(){
    char line[100];
    return (const char*) line; //illegal
}

এড়াতে, আপনি হয় মেমোরিতে একটি পয়েন্টার ফিরিয়ে দেন যা হিপ উদাহরণস্বরূপ থাকে। লাইনবাফার এবং এটি করা হয়ে গেলে তাকে ফ্রি () কল করার দায়বদ্ধ হওয়া উচিত। বিকল্পভাবে আপনি ব্যবহারকারীকে আর্গুমেন্ট হিসাবে আপনাকে একটি মেমরি ঠিকানা লিখতে অনুরোধ করতে পারেন যাতে লাইন সামগ্রীটি লিখতে হয়।


অবৈধ এবং অপরিজ্ঞাত আচরণের মধ্যে পার্থক্য রয়েছে ^^
ফোং

0

আমি 0 নম্বর স্থল থেকে একটি কোড চাই তাই আমি অভিধানের শব্দের রেখার লিখিত বিষয়বস্তু পড়তে এটি করেছি।

চর টেম্পটার [20]; // আপনি আপনার প্রয়োজনীয়তা এবং কোনও ফাইলে একক লাইনের দৈর্ঘ্য অনুযায়ী বাফার আকার পরিবর্তন করতে পারেন।

নোট আমি প্রতিবার লাইন পড়ার সাথে নাল চরিত্রের সাহায্যে বাফারটি শুরু করেছি his এই ফাংশনটি অটোমেটেড হতে পারে তবে যেহেতু আমার ধারণার প্রমাণ প্রয়োজন এবং বাইট বাই একটি প্রোগ্রাম ডিজাইন করতে চান

#include<stdio.h>

int main()
{
int i;
char temp_ch;
FILE *fp=fopen("data.txt","r");
while(temp_ch!=EOF)
{
 i=0;
  char temp_str[20]={'\0','\0','\0','\0','\0','\0','\0','\0','\0','\0','\0','\0','\0','\0','\0','\0','\0','\0','\0'};
while(temp_ch!='\n')
{
  temp_ch=fgetc(fp);
  temp_str[i]=temp_ch;
  i++;
}
if(temp_ch=='\n')
{
temp_ch=fgetc(fp);
temp_str[i]=temp_ch;
}
printf("%s",temp_str);
}
return 0;
}

আপনার ব্র্যাকেটগুলি সঠিক জায়গায় থাকলে আপনার প্রোগ্রামটি কার্যকর হবে;) উদাহরণস্বরূপint main() {
dylnmc

ঘটনাচক্রে, আপনাকে সমস্ত 20 '\ 0' নির্দিষ্ট করার দরকার নেই। আপনি কেবল লিখতে পারেন: codechar temp_str [20] = {'\ 0'}; code সিটি প্রতিটি স্লট স্বয়ংক্রিয়ভাবে একটি নাল টার্মিনেটরের সাথে পূরণ করবে যেহেতু অ্যারের ঘোষণার কাজটি অ্যারেতে থাকা অ্যারে কম উপাদান দিয়ে শুরু করা থাকলে শেষ উপাদানটি বাকি উপাদানগুলি পূরণ করবে।
অ্যালানিয়ান

আমি বিশ্বাস করি char temp_str[20] = {0}যে নাল টার্মিনেটরগুলি সহ পুরো চরিত্রের অ্যারে পূরণ করে।
থু ইয়েন টুন

0

স্ক্র্যাচ থেকে আমার বাস্তবায়ন:

FILE *pFile = fopen(your_file_path, "r");
int nbytes = 1024;
char *line = (char *) malloc(nbytes);
char *buf = (char *) malloc(nbytes);

size_t bytes_read;
int linesize = 0;
while (fgets(buf, nbytes, pFile) != NULL) {
    bytes_read = strlen(buf);
    // if line length larger than size of line buffer
    if (linesize + bytes_read > nbytes) {
        char *tmp = line;
        nbytes += nbytes / 2;
        line = (char *) malloc(nbytes);
        memcpy(line, tmp, linesize);
        free(tmp);
    }
    memcpy(line + linesize, buf, bytes_read);
    linesize += bytes_read;

    if (feof(pFile) || buf[bytes_read-1] == '\n') {
        handle_line(line);
        linesize = 0;
        memset(line, '\0', nbytes);
    }
}

free(buf);
free(line);

আপনি কেন স্ট্যাকের পরিবর্তে গাদা (মলোক) ব্যবহার করছেন? দেখে মনে হচ্ছে এটির সাথে একটি সহজ স্ট্যাক ভিত্তিক সমাধান fgetsব্যবহার করা যেতে পারে।
থিসফায়ার

0

একটি পোর্টেবল এবং জেনেরিক getdelimফাংশন সরবরাহ করুন, পরীক্ষা এমএসভিসি, ঝনঝন, জিসিসি পেরিয়ে।

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

ssize_t
portabl_getdelim(char ** restrict linep,
                 size_t * restrict linecapp,
                 int delimiter,
                 FILE * restrict stream) {
    if (0 == *linep) {
        *linecapp = 8;
        *linep = malloc(*linecapp);
        if (0 == *linep) {
            return EOF;
        }
    }

    ssize_t linelen = 0;
    int c = 0;
    char *p = *linep;

    while (EOF != (c = fgetc(stream))) {
        if (linelen == (ssize_t) *linecapp - 1) {
            *linecapp <<= 1;
            char *p1 = realloc(*linep, *linecapp);
            if (0 == *p1) {
                return EOF;
            }
            p = p1 + linelen;
        }
        *p++ = c;
        linelen++;

        if (delimiter == c) {
            *p = 0;
            return linelen;
        }
    }
    return EOF == c ? EOF : linelen;
}


int
main(int argc, char **argv) {
    const char *filename = "/a/b/c.c";
    FILE *file = fopen(filename, "r");
    if (!file) {
        perror(filename);
        return 1;
    }

    char *line = 0;
    size_t linecap = 0;
    ssize_t linelen;

    while (0 < (linelen = portabl_getdelim(&line, &linecap, '\n', file))) {
        fwrite(line, linelen, 1, stdout);
    }
    if (line) {
        free(line);
    }
    fclose(file);   

    return 0;
}

কেন এটি যখন fgetsউপস্থিত থাকে?
থিসফায়ার

fgets লাইন ডিলিমিটারগুলি কাস্টমাইজ করতে বা বর্তমান লাইনগুলি সম্পর্কে কাস্টমাইজ করতে পারে?

getdelimকাস্টমাইজড ডিলিমিটারগুলির জন্য অনুমতি দেয়। এছাড়াও আমি লক্ষ্য করি যে একটি লাইনের দৈর্ঘ্যের সীমা নেই - এই ক্ষেত্রে আপনি স্ট্যাকটি ব্যবহার করতে পারেন getline। (উভয় এখানে বর্ণিত: man7.org/linux/man-pages/man3/getline.3.html )
theicfire

আপনি কি শুধু লিনাক্স সম্পর্কে কথা বলছেন, প্রশ্নটি সিতে লাইনটি কীভাবে পড়বেন সে সম্পর্কে?

এটি যে কোনও স্ট্যান্ডার্ড সি প্রয়োগের জন্য কাজ করে ( getdelimএবং getlinePOSIX.1-2-2008 তে প্রমিত করা হয়েছিল, অন্য কেউ এই পৃষ্ঠায় উল্লেখ করেছেন)। fgetsএছাড়াও স্ট্যান্ডার্ড সি, এবং লিনাক্স নির্দিষ্ট নয়
theicfire
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.