source

파일을 한 줄씩 읽다

gigabyte 2022. 10. 19. 21:08
반응형

파일을 한 줄씩 읽다

파일에서 행을 읽기 위해 이 함수를 썼습니다.

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;
}

이 함수는 파일을 올바르게 읽고 printf를 사용하여 constLine 문자열도 올바르게 읽혔는지 확인합니다.

단, 예를 들어 다음과 같은 기능을 사용하는 경우:

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

printf 출력은 횡설수설합니다. 왜요?

한 줄 한 줄 읽기 기능을 발명하는 것이 아니라 파일을 한 줄씩 읽는 것이 과제인 경우 일반적인 코드 스니펫을 사용할 수 있습니다.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);
}
FILE* filePointer;
int bufferLength = 255;
char buffer[bufferLength]; /* not ISO 90 compatible */

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

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

fclose(filePointer);

완전한 솔루션:

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

#define MAX_LEN 256

int main(void)
{
    FILE* fp;
    fp = fopen("file.txt", "r");
    if (fp == NULL) {
      perror("Failed: ");
      return 1;
    }

    char buffer[MAX_LEN];
    while (fgets(buffer, MAX_LEN, fp))
    {
        // Remove trailing newline
        buffer[strcspn(buffer, "\n")] = 0;
        printf("%s\n", buffer);
    }

    fclose(fp);
    return 0;
}

출력:

First line of file
Second line of file
Third (and also last) line of file

(이 경우처럼 파일이 아닌) 표준 입력에서 읽으려면 통과만 하면 됩니다.stdin세 번째 파라미터로서fgets()방법은 다음과 같습니다.

while(fgets(buffer, MAX_LEN, stdin))

부록

fgets() 입력에서 말미의 줄바꿈 문자를 제거하는 중

c에서 파일이 열려 있는지 여부를 검출하는 방법

고객님의 고객명readLine이 함수는 포인터를 반환한다.linearray(엄밀히 말하면 첫 번째 문자에 대한 포인터입니다만, 여기서의 차이는 없습니다).자동 변수(즉, "스택"에 있음)이기 때문에 함수가 반환되면 메모리가 회수됩니다.횡설수설하는 게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). */
//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

파일 핸들에서 행을 읽는 데 사용합니다.

이게 내 몇 시간이고...전체 파일을 한 줄씩 읽습니다.

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;
}

readLine()로컬 변수에 포인터를 반환하면 정의되지 않은 동작이 발생합니다.

이동 방법:

  1. 발신자 함수에 변수 생성 및 주소 전달readLine()
  2. 메모리 할당 대상line사용.malloc()- 이 경우line지속할 것이다
  3. 글로벌 변수 사용(일반적으로 좋지 않은 방법임)

휴대성과 범용성을 제공하다getdelim함수, msvc, clang, gcc를 통해 테스트 통과.

#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;
}

파일(input1)에서 내용을 읽고 가져오는 메서드를 구현합니다.txt)

#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);
}

이게 도움이 됐으면 좋겠다.해피 코딩!

처음부터 구현:

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);
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함수는 미리 정의된 버퍼를 채우고 버퍼를 반환합니다.이것이 대부분의 C 라이브러리가 동작하는 방법입니다.

제가 알고 있는 다른 방법이 있습니다.

  • , " "의char line[]스태틱)으로서static char line[MAX_LINE_LENGTH]> > > > > > > 하지 않고 레이스 가 발생할 수 있습니다.-> > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > >
  • malloc() line [ 를해, 비싼 char line이 너무 .malloc을 다른 하는 것(은 '버퍼 해방'을 호출하는 malloc ★★★★★★★★★★★★★★★★★」free은은 、 의의의퍼))))))

btw의 ', '연출'의 '연출'char*로로 합니다.const char*용장성이 있습니다.

btw2, 안 요.malloc()lineBuffer를 .char lineBuffer[128]롭지 않아도

는 ' 스택어레이을 btw3로 지정합니다).char arrayName[some_nonconstant_variable]무엇을 하고 있는지 정확히 모르는 경우는, C99에서만 동작합니다.

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);
    }
}

이거 어때요?

이 예에서는 몇 가지 문제가 있습니다.

  • 을 추가하는 . 오류 "stderr", "stderr"로 합니다. fprintf(stderr, ....
  • 것은 하는 것을 fgetc()getc()getc()fgetc()
  • getc()intch.int은 비교 이 되기 때문에 EOF올바르게 처리됩니다.에서는 "8"을 사용합니다.0xFF및(ISO-LATIN-1)로 지정합니다.EOF은 .0xFF 되어 있는 char.
  • 회선에 잠재적인 버퍼 오버플로가 있습니다.

    lineBuffer[count] = '\0';
    

    , "128" 입니다.count128달러

  • line는 로컬로 선언된 배열입니다.포인터를 반환할 수 없습니다.

  • strncpy(count + 1) '하다'입니다.count + 1할 수 있지만, 이 가 눌러지면 됩니다.'\0'신신 because because set you 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.

ANSI 함수를 사용하여 행을 읽어야 합니다(예: fgets).호출 후 호출 컨텍스트에 free()가 필요합니다.다음은 예를 제시하겠습니다.

...
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;
}

포인터를 자동변수로 되돌리는 실수를 했습니다.가변행은 스택에 할당되며 함수가 존속하는 동안에만 존속합니다.포인터가 반환되는 즉시 메모리가 다른 곳에 제공되기 때문에 포인터에 대한 반환은 허용되지 않습니다.

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

이를 피하려면 hip에 있는 메모리(예를 들어 lineBuffer)로 포인터를 반환해야 합니다.이 포인터를 반환한 후 free()를 호출하는 것은 사용자의 책임입니다.또는 회선 내용을 쓰는 메모리주소를 인수로 전달하도록 사용자에게 요구할 수도 있습니다.

저는 0번 그라운드 코드를 원하기 때문에 사전의 단어 내용을 한 줄씩 읽기 위해 이렇게 했습니다.

char temp_str [ 20 ]; // 파일 내의 한 줄 길이와 요건에 따라 버퍼 크기를 변경할 수 있습니다.

을 읽을 때마다 늘 문자를 사용하여 버퍼를 초기화했습니다.이 기능은 자동화할 수 있지만 개념 검증이 필요하고 Byte By Byte 프로그램을 설계하고 싶기 때문에

#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;
}

언급URL : https://stackoverflow.com/questions/3501338/c-read-file-line-by-line

반응형