如何将字符串列表存入节点?

时间:2013-12-16 05:57:00

标签: c linked-list

我正在尝试将字符串传递给函数,并返回链表,每个节点都包含字符串。 所以,在main函数中,正如你所看到的那样

list = newTB("hello\ngood\nworld"); 

然后,newTB应该返回列表,就像..

[hello]-> [good]-> [world]->null

我的newTB函数必定存在错误,因为seg错误一直存在......

任何人都请帮帮我..

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#include "textbuffer.h"

#define MAX_TEXT 256

typedef struct textbuffer *TB;

struct textbuffer {
    char *texts;
    int count;     // counts how many nodes in the list
    TB next;
};

void printBuffer(TB tb){
    TB curr = tb;
    int i=0;
    while(curr != NULL){
        printf("POS %d : %s\n", i++, curr->texts);
        curr = curr->next;
    }
}

int linesTB(TB tb) {
    return (tb->count);
}

TB newTB (char text[]){
    TB newText = malloc(sizeof(struct textbuffer));
    char *cpy = (char *)malloc(MAX_TEXT * sizeof(char));
    strcpy(cpy,text);
    newText->count = 0;
    newText->next = NULL;
    int i = 0;
    int j = 0;

    while( cpy[i] != '\0') {
        if( j == 0) {
            newText->texts = (char *)malloc(MAX_TEXT * sizeof(char));
        }
        if(cpy[i] == '\n') {
            newText->count++;
            newText->next = malloc(sizeof(struct textbuffer));
            newText = newText->next;
            j = 0;   
        } else {
            newText->texts[j++] = cpy[i++];
        }
    }
    return newText;
}

void releaseTB (TB tb) {
    TB head = tb;
    TB tmp;

    while(head != NULL) {
        tmp = head;
        head = head->next;
        free(tmp->texts);
        free(tmp);

    }
}

int main(int argc, char * argv[]) {
    TB list = NULL;
    list = newTB("hello\ngood bye\nworld\n");

    printf("**THERE ARE %d LINES IN TEXTBUFFER**\n", linesTB(list));
    printBuffer(list);
    printf("%s\n",dumpTB(list));
    releaseTB(list);
    return 0;
}

3 个答案:

答案 0 :(得分:1)

有很多小问题,但这是最重要的问题:

    if(cpy[i] == '\n') {
        newText->count++;
        newText->next = malloc(sizeof(struct textbuffer));
        newText = newText->next;
        j = 0;   
    }

如果cpy[i]是换行符,则会生成newText。猜猜你不做什么:提前i。所以你一遍又一遍地运行这段代码,直到内存不足为止。

如果我要重写这个,我不会逐个字符地扫描代码,而是使用strchr()来查找换行符。此外,您已经复制了一次字符串(使用strdup将更有效和更容易),使用该重复字符串并将其删除并将其部分分配给textblock,以便每个textblock }不需要自己的字符串。

答案 1 :(得分:0)

您这里没有增加i。所以它只在那里循环。

if(cpy[i] == '\n') 
{
    newText->count++;
    newText->next = malloc(sizeof(struct textbuffer));
    newText = newText->next;
    j = 0;   
} 

我修改了代码,这就是我所做的。

TB newTB (char text[]){
    TB newText = (TB )malloc(sizeof(struct textbuffer));
    char *cpy = (char *)malloc(MAX_TEXT * sizeof(char));
    TB root = newText; // Store the first node to return 
    TB prv = newText; // not required. Added for testing by me
    int cnt = 0;
    strcpy(cpy,text);
    newText->count = 0;
    newText->next = NULL;
    int i = 0;
    int j = 0;


    while( cpy[i] != '\0') {
        if( j == 0) {
            prv->texts = (char *)malloc(MAX_TEXT * sizeof(char));
        }
        if(cpy[i] == '\n') {
            prv->texts[j++] = '\0'; // As Rohan suggested.
            //newText->count++;
            prv->next = (TB )malloc(sizeof(struct textbuffer));
            prv = prv->next;  // not required. Added for testing by me
            //newText = newText->next; 
            j = 0;   
            i++; // Increment i here
        } else {
            prv->texts[j++] = cpy[i++];
        }
    }
    return root; // Return the root node.
}

修改

//Printing the node
void printBuffer(TB tb){
    TB curr = tb;
    int i=0;
    while(curr->next != NULL){ // changed from curr!=NULL to curr->next!=NULL
        printf("POS %d : %s\n", i++, curr->texts);
        curr = curr->next;
    }
}

还添加了

prv->next = NULL; // Added this line in newTB  function
return root;

答案 2 :(得分:0)

newText->texts中逐个字符复制后,用'\0'终止它,以便它成为适当的空终止字符串。

       if(cpy[i] == '\n') {
            nextText->texts[j] = '\0'; //set null terminated string.
            newText->count++;
            newText->next = malloc(sizeof(struct textbuffer));
            newText = newText->next;
            j = 0;   
        } else {
            newText->texts[j++] = cpy[i++];
        }

否则,当您在newText->texts中打印字符串时,将找不到终止字符,并继续打印和访问无效内存,从而导致段错误。