c - 如何编写一个从文件描述符中读取并返回一行的函数,而 C 中没有'\n'
问题描述
我只被允许使用 malloc、read 和 free。我还可以使用 string.h 中的函数
该程序应使用以下方法编译:
gcc -Wall -Wextra -Werror -D BUFFER_SIZE=32 get_next_line.c
包括:
#include <string.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/uio.h>
#include <fcntl.h>
#define BUFFER_SIZE 32
该函数的原型应为:
int get_next_line(int fd, char **line);
解决方案
也许我会做类似的事情:
#include <string.h> // strlen()
#include <unistd.h> // read(), write(), close()
#include <stdlib.h> // EXIT_SUCCESS, realloc(), free()
#include <fcntl.h> // O_RDONLY
#define EOF (-1) // Flag to indicate that the end-of-file was encountered.
extern int errno; // Used to detect, and report, error information.
/*----------------------------------------------------------------------------
** Read a line from specified file (fd), and return the line in allocated
** memory. The caller is responsible for freeing the returned memory.
**
** Return codes:
** -------------
** -1 EOF Encountered the end of the file (fd).
** 0 EXIT_SUCCESS Success.
** >1 (errno value) Failure.
*/
int get_next_line(int fd, char **line)
{
int rCode = EXIT_SUCCESS;
size_t lineOffset = 0;
while(!rCode)
{
char *newBuf = NULL;
int bytes;
char ch;
bytes=read(fd, &ch, sizeof(ch)); // Read one byte from file (fd).
switch(bytes)
{
case (-1): // Check for read() error condition.
rCode=errno; // Return errno to caller.
break; // Return from the function.
case 0: // Check for end-of-file condition.
rCode = EOF; // Return EOF flag to caller.
ch = '\0'; // Pretend to have read '\0'.
// No break. Fall through to default case.
default: // read() was successful.
newBuf=realloc(*line, lineOffset+2); // Modify line's memory allocation as needed.
if(!newBuf) // Check for realloc() error condition.
{
rCode=errno; // Return errno to caller.
break; // Return from the function.
}
*line = newBuf; // realloc() was successful. Reset line pointer.
if('\n' == ch) // If newline was read, throw it away
{
(*line)[lineOffset] = '\0'; // Instead of a newline, terminate the line,
break; // and return from the function.
}
(*line)[lineOffset++] = ch; // Append the character read from the file to the allocated memory.
(*line)[lineOffset] = '\0'; // Terminate the string in allocated memory.
continue; // Go back to the top of the while() loop, and read another byte.
}
break;
}
return(rCode);
}
/*----------------------------------------------------------------------------
** Program start.
*/
int main(int argC, char *argV[])
{
int rCode=EXIT_SUCCESS;
int fd = (-1);
char *line_A = NULL;
if(2 != argC)
{
char *msg = "Missing filename, or too many command-line arguments.\n";
write(2, msg, strlen(msg));
goto CLEANUP;
}
errno=EXIT_SUCCESS;
fd=open(argV[1], O_RDONLY);
if((-1) == fd)
{
char *msg = "open() failed.\n";
write(2, msg, strlen(msg));
goto CLEANUP;
}
while(EOF != rCode)
{
rCode=get_next_line(fd, &line_A);
if(rCode > 0)
goto CLEANUP;
write(1, line_A, strlen(line_A));
write(1, "\n", 2);
}
CLEANUP:
if(line_A)
free(line_A);
if((-1) != fd)
close(fd);
return(rCode);
}
推荐阅读
- enums - Rust 枚举的问题
- list - Ocaml:即使已经找到,也要重复图中的路径
- postgresql - 使用荷兰语语言环境将字符串转换/转换为数字
- loops - DELPHI 10.3 - 循环直到按键小问题
- c++ - c ++ 11中'sizeof ...'运算符有什么用?(不是 sizeof 运算符)
- mongodb - 我如何解决错误:MongoTimeoutError:服务器选择在 30000 毫秒后超时,无法连接到服务器 127.0.0.1:27017
- r - R:箱线图:在重复测量的情况下在每个主题之间画线
- c# - C# HttpClient 在第二次运行时为空
- wordpress - 在 woocommerce 的购物车和结帐页面中显示自定义数据
- javascript - Vuex 更好的映射方式?