我试图编写一个C程序来读取一个文件,将输入标记为一个双向链表,并用它做一些事情,即:对它进行排序,走它,写它......等等。 p>
md@ubuntu:~/Documents/testproject$ cat test.txt 2017-07-25,14:50:02:477, 12104,932,HOST, log message 1111111111111111111111111111 2017-07-26,14:50:02:478, 12104,932,HOST, log message 22222222222222222222222222222222222222 2017-07-27,14:50:03:095, 12104,932,HOST, log message 3333333333333333 2017-07-28,14:50:04:587, 12104,932,HOST, log message 444444444444444444444444444444444444444444444 2017-07-29,14:50:04:587, 12104,932,HOST, log message blah blah blahb 1234455e56456546 test test test ERrroRRRrrr$$4RRrr junk to be parsed out more junk 1234567
但是当我走过列表时,每个节点都包含最后一个条目。有什么迹象表明我在这里出错了吗?我在printf
函数中添加了createnewnode()
,似乎在struct节点中设置了正确的字符串。
md@ubuntu:~/Documents/testproject$ ./doubly test.txt *****CREATE NODE*****(2017-07-25,14:50:02:477,932,HOST, log message 1111111111111111111111111111 *****CREATE NODE*****(2017-07-26,14:50:02:478,932,HOST, log message 22222222222222222222222222222222222222 *****CREATE NODE*****(2017-07-27,14:50:03:095,932,HOST, log message 3333333333333333 *****CREATE NODE*****(2017-07-28,14:50:04:587,932,HOST, log message 444444444444444444444444444444444444444444444 *****CREATE NODE*****(2017-07-29,14:50:04:587,932,HOST, log message blah blah blahb 1234455e56456546 test test test ERrroRRRrrr$$4RRrr *****PRINT LINKED LIST***** 0x557237b1a760 1986300429 2017-07-29 14:50:04:587 932,HOST, log message blah blah blahb 1234455e56456546 test test test ERrroRRRrrr$$4RRrr 0x557237b1a720 1986300429 2017-07-29 14:50:04:587 932,HOST, log message blah blah blahb 1234455e56456546 test test test ERrroRRRrrr$$4RRrr 0x557237b1a6e0 1986300429 2017-07-29 14:50:04:587 932,HOST, log message blah blah blahb 1234455e56456546 test test test ERrroRRRrrr$$4RRrr 0x557237b1a6a0 1986300429 2017-07-29 14:50:04:587 932,HOST, log message blah blah blahb 1234455e56456546 test test test ERrroRRRrrr$$4RRrr 0x557237b1a250 1986300429 2017-07-29 14:50:04:587 932,HOST, log message blah blah blahb 1234455e56456546 test test test ERrroRRRrrr$$4RRrr
代码:
/*
Parse a delimited log file and tokenized values in a doubly linked list.
Do stuff with this doubly linked list of structures (ie: sort by time....etc)
*/
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <string.h>
#include <locale.h>
#include <errno.h>
#define __USE_XOPEN
#include <time.h>
#include <sys/time.h>
#define LINESIZE 1024
//Linked List structure
struct node
{
int jobid;
char* datestring;
char* timestring;
char* message;
struct node *prev; //previous node
struct node *next; //next node
};
typedef struct node node;
node *head = NULL; //declar pointer beginning of linked list
//prototypes for linked list functions
struct node* createnewnode(char* ds, char* ts, char* msg); //create a new node and return a pointer to it
void insert_at_head(char* ds, char* ts, char* msg);
void print_elements();
static void clean();
int parseFile(char* fname);
char **strsplit(const char* str, const char* delim, size_t* numtokens);
int lensum(char **input);
/* DOUBLY LINKED LISTS */
//Node Generator
struct node* createnewnode(char* ds, char* ts, char* msg)
{
node *newnode = malloc(sizeof(node)); //allocate memory on the heap and create a new node structure
//copy strings to local variables. Desperate hope to get this working, but probably not needed
char tds[LINESIZE], tts[LINESIZE],tmsg[LINESIZE];
strcpy(tds, ds);
strcpy(tts, ts);
strcpy(tmsg, msg);
#ifdef DEBUG
printf("*****CREATE NODE*****(%s,%s,%s\n",tds,tts,tmsg);
#endif
newnode->datestring = tds;
newnode->timestring = tts;
newnode->message = tmsg;
srand(time(NULL));
newnode->jobid = rand(); //set to random value to see if it changes between iterations
newnode->prev = NULL;
newnode->next = NULL;
return newnode;
}
//Insert Node at the beginning of the list
void insert_at_head(char* ds, char* ts, char* msg)
{
node *newnode = createnewnode(ds, ts, msg);
//If this is the first element being added to the linked list
if (head == NULL)
{
head = newnode;
return;
}
head->prev = newnode;
newnode->next = head;
head = newnode;
}
//print_elements() in linked list from the head to the tail (end)
void print_elements()
{
node *ptmp = head; //beginning of the list
if (ptmp == NULL)
{
printf("Warning: No elements in this list\n");
return;
}
#ifdef DEBUG
printf("\n*****PRINT LINKED LIST*****\n");
#endif
while(ptmp != NULL)
{
printf("%p %d %s %s %s\n",ptmp, ptmp->jobid, ptmp->datestring, ptmp->timestring, ptmp->message );
ptmp = ptmp->next;
}
return;
}
static void clean()
{
node *temp = NULL;
while(head != NULL)
{
temp = head;
head = head->next;
free(temp);
}
}
/* PARSE FILE */
int parseFile(char* fname)
{
FILE *in = fopen(fname, "r");
char line[LINESIZE];
struct tm date;
const char delim[] = ",";
char *tok;
char dbuf[LINESIZE], tbuf[LINESIZE], mbuf[LINESIZE];
while (fgets(line, sizeof(line), in) != NULL) {
if ((void *)strptime(line,"%Y-%m-%d",&date) != NULL)
{
tok = strtok(line, delim);
strcpy((char*)dbuf, tok);
tok = strtok(NULL, delim);
if (NULL != tok)
{
strcpy((char*)tbuf, tok);
tok = strtok(NULL,delim);
}
tok = strtok(NULL,"\n");
if (NULL != tok)
{
strcpy((char*)mbuf, tok);
}
insert_at_head(dbuf, tbuf, mbuf);
}
}
fclose(in); //close file pointer
return 0;
}
int main(int argc, char const *argv[])
{
parseFile("test.txt");
print_elements();
clean();
return 0;
}
答案 0 :(得分:1)
您的错误在于函数struct node* createnewnode(char* ds, char* ts, char* msg)
您在行
char tds[LINESIZE], tts[LINESIZE],tmsg[LINESIZE];
是函数的本地。离开函数时它会消失,所以后面的行
newnode->datestring = tds;
newnode->timestring = tts;
newnode->message = tmsg;
不会做你想要的。
您可以在堆上保留一些内存,例如:
//char tds[LINESIZE], tts[LINESIZE],tmsg[LINESIZE];
char *tds = malloc(LINESIZE); // can be fixed if length is fixed
char *tts = malloc(LINESIZE); // can be fixed if length is fixed
char *tmsg = malloc(LINESIZE); // the message is probably variable, so measure it
但你必须在以后释放这段记忆。
或者通过更改struct
例如:
struct node
{
int jobid;
char datestring[100];
char timestring[100];
char message[256];
struct node *prev; //previous node
struct node *next; //next node
};
但是这会使struct
的数量增加不小,而且灵活性会降低。例如,该消息可能需要超过256个字符。
或者使用混合方法并使用堆栈作为日期和时间字符串,如果它们总是具有相同的固定长度,则通过测量文件中条目的长度并相应地分配内存来获取消息的堆。清理时不要忘记释放堆内存!