我试图一次读取一行文件,缓冲区长度不同。我将文件desc传递给get_next_line函数并将该行分配给指针。问题是当缓冲区长度很长时,有时它打印文件的其余部分,当我传递2个不同的文件描述符时,我得到一个段错误。我认为这与在节点中保存字符串并在fd相同时查找相同节点有关。 我没有看到我在这里做错了什么。
get_next_line.c
#include "get_next_line.h"
#include <fcntl.h>
#include <stdio.h>
/*
** CREATE THE NEXT NODE TO ADD TO THE LINKEDLIST.
**
*/
t_node *create_node(char *buffer, int fd)
{
int i;
t_node *new;
i = 0;
while (*buffer != '\n')
buffer++;
if (*buffer == EOF)
return 0;
++buffer;
new = malloc(sizeof(t_node));
new->fd = fd;
new->next = NULL;
new->str = malloc(sizeof(char *));
while (buffer[i] != '\n')
{
new->str[i] = (char)malloc(sizeof(char));
new->str[i] = buffer[i];
i++;
}
return (new);
}
/*
** SEARCH THE LIST FOR FD AND GET THE OVERFLAP STRING FROM
** LAST READ.
*/
char *get_overlap(t_node **root, int fd)
{
t_node *conductor;
if (*root == NULL)
return (NULL);
conductor = *root;
while (conductor->fd != fd && conductor != 0)
conductor = conductor->next;
if (conductor == NULL)
return (NULL);
return (conductor->str);
}
/*
** CALL THE CREATE NODE FUNCTION AND ADD IT TO THE LINKEDLIST.
**
*/
void save_overlap(char buffer[], t_node **root, int fd)
{
t_node **conductor;
t_node *new;
new = create_node(buffer, fd);
if (*root == NULL)
*root = new;
else
{
conductor = root;
while (*conductor != NULL)
{
if ((*conductor)->fd == fd)
{
(*conductor)->str = new->str;
break;
}
if ((*conductor)->next == NULL)
{
(*conductor)->next = new;
break;
}
*conductor = (*conductor)->next;
}
}
}
/*
** PREPEND THE PREVIOUS OVERLAP IN BUFFER TO LINE STRING.
**
*/
void prepend_overlap(char *str, char ***line, int *i)
{
int b = *i;
while (str[b])
{
(**line)[b] = (char)malloc(sizeof(char));
(**line)[b] = str[b];
b++;
}
*i = b;
}
/*
** GET A SINGLE LINE AT A TIME FROM A FILE
** WHILE ALSO KEEPING TRACK OF THE FD.
*/
int get_next_line(const int fd, char **line)
{
char buffer[BUFF_SIZE + 1];
int i;
int j;
char *overlap_str;
static t_node *root;
i = 0;
j = 0;
overlap_str = get_overlap(&root, fd);
if(overlap_str != NULL)
prepend_overlap(overlap_str, &line, &i);
read(fd, buffer, BUFF_SIZE);
while (buffer[j] != '\n')
{
if (j == BUFF_SIZE)
{
(*line)[i] = (char)malloc(sizeof(char));
(*line)[i] = buffer[j];
j = 0;
read(fd, buffer, BUFF_SIZE);
continue;
}
(*line)[i] = (char)malloc(sizeof(char));
(*line)[i] = buffer[j];
i++;
j++;
}
(*line)[i] = '\0';
printf("%s\n", *line);
save_overlap(buffer, &root, fd);
return (0);
}
int main()
{
int fd = open("test", O_RDONLY);
//int fdt = open("test2", O_RDONLY);
char *line;
get_next_line(fd, &line);
get_next_line(fd, &line);
}
get_next_line.h
#ifndef GET_NEXT_LINE_H
# define GET_NEXT_LINE_H
# define BUFF_SIZE 32
#include <fcntl.h>
int get_next_line(const int fd, char **line);
typedef struct s_node
{
int fd;
char *str;
struct s_node *next;
}t_node;
#endif
它适用于单个文件描述符,例如我只能传递fd而不是fdt它会起作用,除非我将缓冲区大小设置为120或更高,例如,它将打印超出我想要的内容。我只想要'\ n'之前的那一行。
答案 0 :(得分:0)
new->str = malloc(sizeof(char *));
...
new->str[i] = (char)malloc(sizeof(char));
我不确定你在这里要做什么。 malloc(N * sizeof(char*))
可用于创建一个指向&#34;字符数组&#34;的指针数组,其大小为N
。基本上&#34;字符串数组&#34;或者&#34;二维字符数组&#34;。
malloc(sizeof(char))
只是malloc(1)
,或只是一个字节。如果new->str
是字符数组,那么str[i]
已经是一个字节,不应该使用malloc
设置
这样做是为了分配字符数组:
new->str = malloc(5);
strcpy(new->str, "1234");
这将为str
分配5个字节,然后复制&#34; 1234&#34;它,并在最后添加一个零,总共5个字节。
此外,您的链接列表也没有头脑。请尝试以下代码。
#include <stdlib.h>//*** don't forget the right header files
#include <stdio.h>
#include <string.h>
typedef struct s_node
{
char *str;
struct s_node *next;
}t_node;
void insert_node(t_node** head, char* buf)
{
t_node *node = malloc(sizeof(t_node));
node->next = 0;
//allocate memory for string and copy
node->str = malloc(strlen(buf) + 1); //+1 for nul-terminator
strcpy(node->str, buf);
if (*head == 0)
{
*head = node;
}
else
{
//find the end of the linked list
t_node *tail = *head;
while (tail->next)
tail = tail->next;
//make the end element point to new node
tail->next = node;
}
}
int main()
{
FILE *fd = fopen("test.txt", "r");
if (!fd)
{
printf("file error\n");
return 0;
}
//linked list identifier:
t_node *head = 0;
char buf[1000];
//read the file line by line
while(fscanf(fd, "%999s", buf) > 0)
{
//insert line in to linked list
insert_node(&head, buf);
}
//show the result of the linked list:
t_node *walk = head;
while (walk)
{
printf("[%s]\n", walk->str);
walk = walk->next;
}
return 0;
}
请注意,如果一行或多行超过1000个字符,则上述代码将失败。你可以增加缓冲区长度,或者有办法解决这个问题,但我保留原样以使示例变得简单。
确保编译器警告级别为4或最大值,并确保处理所有警告和错误。