Потеря данных при попытке скопировать символ * в C - PullRequest
2 голосов
/ 21 марта 2019

Я работал над проектом на C, и у меня возникли проблемы при попытке скопировать char * с использованием strcpy / memcpy / strncpy, ни один из них, похоже, не работает.Возникающая проблема заключается в том, что слова длиной около 8 или более символов не копируются полностью.

typedef struct wordFrequency {
    char * word;
    int frequency;

struct wordFrequency *left, *right;
} *node;


node setnode(char * word) {

    node newNode = (node)malloc(sizeof(node));
    newNode->word = (char*)malloc(sizeof(word));

    strcpy(newNode->word, word); //This is where I'm having trouble

    newNode->frequency = 1;
    newNode->right = NULL;

    return newNode;
}

Приведенный выше код является основной причиной ошибки, но я нене знаю, где это исправить.Я пробовал возиться с размерами, но это не сработало.

Если возможно, кто-нибудь может объяснить мне способ скопировать все символы или если я не выделил достаточно места?

1 Ответ

2 голосов
/ 22 марта 2019

Эта программа представляет собой mcve , которая показывает, как правильно распределить и инициализировать каждый узел в вашем связанном списке:

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

#define ARRAY_SIZE(array) \
    (sizeof(array) / sizeof(array[0]))

typedef struct wordFrequency {
    char *word;
    int frequency;
    struct wordFrequency *left, *right;
} node;

node *setnode(char *word) {
    node *newNode = malloc(sizeof(node));
    newNode->word = malloc(strlen(word) + 1);
    strcpy(newNode->word, word);
    newNode->frequency = 1;
    newNode->right = NULL;
    return newNode;
}

int main() {
    char *wordList[] = {"one", "two", "three"};
    node nodeHead;
    node *nodePrev = &nodeHead;
    node *nodeNext;
    for (int index = 0; index < ARRAY_SIZE(wordList); index++) {
        nodeNext = setnode(wordList[index]);
        nodePrev->right = nodeNext;
        nodeNext->left = nodePrev;
        nodePrev = nodeNext;
    }
    for (node *nodePtr = nodeHead.right; nodePtr != NULL; nodePtr = nodePtr->right) {
        printf("word = %s, frequency = %d\n", nodePtr->word, nodePtr->frequency);
    }
    return 0;
}

выход

word = one, frequency = 1
word = two, frequency = 1
word = three, frequency = 1

Примечание

Эта программа не проверяет ошибки и не освобождает выделенную память. Этот код не должен использоваться в производственной среде.

Ответы на вопросы в комментариях

Я заменил *node на node в typedef, потому что это позволяет мне объявлять экземпляры node. Другой синтаксис позволяет указателям только на node.

Я использую экземпляр node вместо node * для nodeHead, потому что любая попытка изменить его адрес будет ошибкой.

Я использую nodePrev для обхода списка, а также для предоставления цели для left в возвращаемых узлах. Я инициализирую nodePrev на &nodeHead, потому что это начало списка. Я установил nodePrev на nodeNext, потому что именно так я решил просмотреть список во время инициализации. Я мог бы использовать

nodePrev = nodePrev->right;

и достиг того же эффекта.

Я реализовал обработку списка только для того, чтобы создать автономный пример, который работал бы без изменений. Вы можете смело игнорировать это.

Если вы хотите увидеть хороший код связанного списка, я рекомендую реализацию ядра Linux .

...