lro*_*ron 165 c file-io std line
我写了这个函数来从文件中读取一行:
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;
}
Run Code Online (Sandbox Code Playgroud)
该函数正确读取文件,并使用printf我看到constLine字符串也正确读取.
但是,如果我使用这样的功能:
while (!feof(myFile)) {
const char *line = readLine(myFile);
printf("%s\n", line);
}
Run Code Online (Sandbox Code Playgroud)
printf输出乱码.为什么?
mba*_*off 282
如果您的任务不是发明逐行读取功能,而只是逐行读取文件,您可以使用涉及该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);
}
Run Code Online (Sandbox Code Playgroud)
Gil*_*il' 20
在你的readLine
函数中,你返回一个指向line
数组的指针(严格地说,指向它的第一个字符的指针,但这里的差异是无关紧要的).由于它是一个自动变量(即它在"堆栈中"),因此在函数返回时回收内存.你看到胡言乱语,因为printf
它把自己的东西放在堆栈上.
您需要从函数返回动态分配的缓冲区.你已经拥有一个,它是lineBuffer
; 你所要做的就是将它截断到所需的长度.
lineBuffer[count] = '\0';
realloc(lineBuffer, count + 1);
return lineBuffer;
}
Run Code Online (Sandbox Code Playgroud)
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). */
Run Code Online (Sandbox Code Playgroud)
Rob*_*Rob 20
FILE* fp;
char buffer[255];
fp = fopen("file.txt", "r");
while(fgets(buffer, 255, (FILE*) fp)) {
printf("%s\n", buffer);
}
fclose(fp);
Run Code Online (Sandbox Code Playgroud)
Rev*_*Lab 13
//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
Run Code Online (Sandbox Code Playgroud)
qrd*_*rdl 10
readLine()
返回指向局部变量的指针,这会导致未定义的行为.
您可以:
readLine()
line
使用malloc()
- 在这种情况下line
将是持久的一个完整的fgets()
解决方案:
#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];
// -1 to allow room for NULL terminator for really long string
while (fgets(buffer, MAX_LEN - 1, fp))
{
// Remove trailing newline
buffer[strcspn(buffer, "\n")] = 0;
printf("%s\n", buffer);
}
fclose(fp);
return 0;
}
Run Code Online (Sandbox Code Playgroud)
输出:
First line of file
Second line of file
Third (and also last) line of file
Run Code Online (Sandbox Code Playgroud)
请记住,如果您想从标准输入(而不是本例中的文件)中读取,那么您所要做的就是将其stdin
作为fgets()
方法的第三个参数传递,如下所示:
while(fgets(buffer, MAX_LEN - 1, stdin))
Run Code Online (Sandbox Code Playgroud)
附录