파일에서 한 줄을 읽으려면이 함수를 작성했습니다.
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];
filePointer = fopen("file.txt", "r");
while(fgets(buffer, bufferLength, filePointer)) {
printf("%s\n", buffer);
}
fclose(filePointer);
답변
당신의에서 readLine
기능, 당신은에 대한 포인터 반환 line
(첫 번째 문자로, 엄밀히 말하면 포인터를하지만, 차이는 여기에 무관) 배열. 이 변수는 자동 변수이므로 (즉, “스택”) 함수가 반환 될 때 메모리가 회수됩니다. printf
스택에 자체 물건을 넣었 기 때문에 횡설수설 한 것을 볼 수 있습니다 .
함수에서 동적으로 할당 된 버퍼를 반환해야합니다. 당신은 이미 하나를 가지고 있습니다 lineBuffer
. 원하는 길이로 자르기 만하면됩니다.
lineBuffer[count] = '\0';
realloc(lineBuffer, count + 1);
return lineBuffer;
}
ADDED (댓글의 후속 질문에 대한 응답) : 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
답변
readLine()
정의되지 않은 동작을 일으키는 지역 변수에 대한 포인터를 반환합니다.
당신을 돌아 다니려면 :
- 호출자 함수에서 변수를 작성하고 주소를
readLine()
line
사용을 위한 메모리 할당malloc()
-이 경우line
에는 영구적입니다- 일반적으로 나쁜 습관이지만 전역 변수를 사용하십시오.
답변
fgets()
파일 핸들에서 줄을 읽는 데 사용 합니다.
답변
예제에 몇 가지 잘못된 점이 있습니다.
- printfs에 \ n을 추가하는 것을 잊었습니다. 또한 오류 메시지는 stderr로 이동해야합니다.
fprintf(stderr, ....
- (더 크지 않지만)
fgetc()
보다는을 사용 하는 것이 좋습니다getc()
.getc()
매크로fgetc()
입니다, 적절한 기능입니다 getc()
반환int
그래서는ch
로 선언되어야한다int
. 와의 비교EOF
가 올바르게 처리 되므로 중요 합니다. 일부 8 비트 문자 세트0xFF
는 유효한 문자로 사용 되며 (ISO-LATIN-1이 예일 수 있음)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
.
