파일을 한 줄씩 읽다
파일에서 행을 읽기 위해 이 함수를 썼습니다.
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() 입력에서 말미의 줄바꿈 문자를 제거하는 중
고객님의 고객명readLine
이 함수는 포인터를 반환한다.line
array(엄밀히 말하면 첫 번째 문자에 대한 포인터입니다만, 여기서의 차이는 없습니다).자동 변수(즉, "스택"에 있음)이기 때문에 함수가 반환되면 메모리가 회수됩니다.횡설수설하는 게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()
로컬 변수에 포인터를 반환하면 정의되지 않은 동작이 발생합니다.
이동 방법:
- 발신자 함수에 변수 생성 및 주소 전달
readLine()
- 메모리 할당 대상
line
사용.malloc()
- 이 경우line
지속할 것이다 - 글로벌 변수 사용(일반적으로 좋지 않은 방법임)
휴대성과 범용성을 제공하다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()
int
ch
.int
은 비교 이 되기 때문에EOF
올바르게 처리됩니다.에서는 "8"을 사용합니다.0xFF
및(ISO-LATIN-1)로 지정합니다.EOF
은 .0xFF
되어 있는char
.회선에 잠재적인 버퍼 오버플로가 있습니다.
lineBuffer[count] = '\0';
, "128" 입니다.
count
128달러line
는 로컬로 선언된 배열입니다.포인터를 반환할 수 없습니다.strncpy(count + 1)
'하다'입니다.count + 1
할 수 있지만, 이 가 눌러지면 됩니다.'\0'
신신 because because set youlineBuffer[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
'source' 카테고리의 다른 글
mysqldump 문제: "--defaults-extra-file" 옵션이 예상대로 작동하지 않습니다. (0) | 2022.10.19 |
---|---|
Pyplot을 사용하여 모든 하위구 위에 단일 주 제목을 설정하는 방법은 무엇입니까? (0) | 2022.10.19 |
행이 있는지 확인하기 위한 두 가지 방법 중 선택(하위 쿼리 수가 더 많은 경우와 왼쪽 조인 수가 더 많은 경우 (0) | 2022.10.19 |
Python - SQL 데이터베이스에 암호화 키 저장 (0) | 2022.10.19 |
MySQL/MariaDB의 PERCENTILE_CONT 대체 방법 (0) | 2022.10.19 |