在c

时间:2019-03-10 09:12:48

标签: c tokenize dynamic-memory-allocation double-pointer

这个问题是this question的继续。

代码如下:

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

int main(void)
{
    int ch;
    char *ptrChFromFile;
    char **ptrWords;
    int strSize = 1;
    int i;
    int j = 0;
    int numberOfWords = 1;

    ptrChFromFile = malloc(sizeof(char));

    if (ptrChFromFile == NULL)
    {
        puts("COULDN'T ALLOICATE MEMORY");
        exit(EXIT_FAILURE);
    }

    while ((ch = getchar()) != '\n')
    {
        ptrChFromFile = realloc(ptrChFromFile, (strSize+1) * sizeof(char));

        if (ptrChFromFile == NULL)
        {
            puts("failed to allocate memory");
            exit(EXIT_FAILURE);
        }

        if (ch == ' ')
        {
            numberOfWords++;
        }

        ptrChFromFile[strSize] = ch;
        strSize++;
    }

    ptrChFromFile[strSize] = 0;

    ptrWords = malloc(sizeof(char*) * numberOfWords); //creates number of slots in ptr

    if (ptrWords == NULL)
    {
        puts("failed to allocate memory");
        exit(EXIT_FAILURE);
    }

    for (i = 0; i < numberOfWords; i++) // allocates number of bytes in each slot.
    {
        ptrWords[i] = malloc(sizeof(char*)* strSize);
        if (ptrWords[i] == NULL)
        {
            puts("failed to allocate memory");
            exit(EXIT_FAILURE);
        }
    }

    for (i = 0; i < strSize; i++)
    {
        if (ptrChFromFile[i] != ' ')
        {
            ptrWords[j] = &ptrChFromFile[i];
        }
        else
        {
            ptrWords[j] = 0;
            j++;
        }
    }

    for (i = 0; i < numberOfWords; i++) // free's each slot in ptrWords
    {
        free(ptrWords[i]);
    }

    free(ptrChFromFile);
    free(ptrWords);
    return 0;
}

我正在尝试动态分配我的双字符指针ptrWords。让我解释一下我的思考过程:

ptrWords = malloc(sizeof(char*) * numberOfWords); //creates number of slots in ptr

这将在ptrWords中创建插槽(索引)数。因此,如果我有3个单词,ptrWords应该看起来像这样:

ptrWords [索引0]

ptrWords [索引1]

ptrWords [索引2]

for (i = 0; i < numberOfWords; i++) // allocates number of bytes in each slot.
{
    ptrWords[i] = malloc(sizeof(char*)* strSize);
    if (ptrWords[i] == NULL)
    {
        puts("failed to allocate memory");
        exit(EXIT_FAILURE);
    }
}

此for循环将内存分配给ptrWords中的每个插槽,该内存等于输入文件中字符的总数。因此,例如,如果输入文件中总共有26个字符,则ptrWords中的每个插槽将分配有26个字节。

ptrWords [索引0]具有26个字节的内存

ptrWords [索引1]具有26个字节的内存

ptrWords [索引2]具有26个字节的内存

我认为我对ptrWords的内存分配是正确的,但是我不确定。

for (i = 0; i < strSize; i++)
{
    if (ptrChFromFile[i] != ' ')
    {
        ptrWords[j] = &ptrChFromFile[i];
    }
    else
    {
        ptrWords[j] = 0;
        j++;
    }
}

此for循环应该从ptrChFromFile中获取字符,并将其作为单独的单词存储在ptrWords中。我的循环逻辑如下:

1)只要ch不等于空格,就可以将该字符存储在ptrWords的第一个位置(索引0)。

2)如果ch确实等于一个空格,则在其位置放置一个终止字符('\ 0'),然后将j递增1以移至ptrWords中的下一个索引以存储下一个单词。

我已经使用调试器来逐步执行代码,但是我仍然无法弄清出什么毛病,因此,我们将不胜感激。

谢谢


我的实现:

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

int main(void)
{
    int ch;
    char *ptrChFromFile;
    char **ptrWords;
    int strSize = 1;
    int i;
    int j = 0;
    int k = 0;
    int numberOfWords = 1;

    ptrChFromFile = malloc(sizeof(char));

    if (ptrChFromFile == NULL)
    {
        puts("COULDN'T ALLOCATE MEMORY");
        exit(EXIT_FAILURE);
    }

    while ((ch = getchar()) != '\n')
    {
        ptrChFromFile = realloc(ptrChFromFile, (strSize+1) * sizeof(char));

        if (ptrChFromFile == NULL)
        {
            puts("failed to allocate memory");
            exit(EXIT_FAILURE);
        }

        if (ch == ' ')
        {
            numberOfWords++;
        }

        ptrChFromFile[strSize] = ch;
        strSize++;
    }

    ptrChFromFile[strSize] = 0;

    ptrWords = malloc(sizeof(char*) * numberOfWords); //creates number of slots in ptrWords

    for (i = 0; i < numberOfWords; i++) // allocates number of bytes in each slot.
    {
        ptrWords[i] = malloc(sizeof(char*)* strSize);
        if (ptrWords[i] == NULL)
        {
            puts("failed to allocate memory");
            exit(EXIT_FAILURE);
        }
    }

    if (ptrWords == NULL)
    {
        puts("failed to allocate memory");
        exit(EXIT_FAILURE);
    }

    for (i = 0; i < strSize; i++)
    {
        if (ptrChFromFile[i] != ' ')
        {
            ptrWords[j][k++] = ptrChFromFile[i];
        }
        else
        {
            ptrWords[j][k] = 0;
            ptrWords[j] = realloc(ptrWords[j], k+1);
            j++;
            k = 0;
        }
    }
    printf("%s", ptrWords[0]);

    free(ptrChFromFile);
    free(ptrWords);

    return 0;
}

示例输入:“嘿”

输出:嘿

¿嘿


当前代码版本:

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


int getStrLength(char *word)
{
    int lengthOfWord = 0;
    int i;

    for (i = 0; word[i] != 0; i++)
    {
        lengthOfWord++;
    }
    return lengthOfWord;
}

int compareWords(char *firstWord, char *secondWord)
{
    while (*firstWord && *firstWord == *secondWord)
    {
        firstWord++;
        secondWord++;
    }
    return *firstWord - *secondWord;
}

int main(void)
{
    int ch;
    char *ptrChFromFile;
    char **ptrWords;
    char **ptrCrunchWord;
    int strSize = 0;
    int i;
    int j = 0;
    int k = 0;
    int numberOfWords = 0;
    int defaultWordLength = 6;

    srand(time(0)); // Use current time as seed for random generator

    ptrChFromFile = malloc(sizeof(char));

    if (ptrChFromFile == NULL)
    {
        puts("COULDN'T ALLOCATE MEMORY");
        exit(EXIT_FAILURE);
    }

    while ((ch = getchar()) != '\n') // this reads in chars from file to ch variable
    {
        ptrChFromFile = realloc(ptrChFromFile, (strSize+1) * sizeof(char));

        if (ptrChFromFile == NULL)
        {
            puts("failed to allocate memory");
            exit(EXIT_FAILURE);
        }

        if (ch == ' ')
        {
            numberOfWords++;
        }

        ptrChFromFile[strSize] = ch;
        strSize++;
    }

    numberOfWords++;
    ptrChFromFile[strSize] = 0;

    ptrWords = malloc(sizeof(char*) * numberOfWords); //creates number of slots in ptrWords

    if (ptrWords == NULL)
    {
        puts("failed to allocate memory");
        exit(EXIT_FAILURE);
    }

    for (i = 0; i < numberOfWords; i++) // allocates number of bytes in each slot.
    {
        ptrWords[i] = malloc(strSize);
        if (ptrWords[i] == NULL)
        {
            puts("failed to allocate memory");
            exit(EXIT_FAILURE);
        }
    }

    for (i = 0; i < strSize; i++) // This inserts words in ptrWords separated by spaces.
    {
        if (ptrChFromFile[i] != ' ')
        {
            ptrWords[j][k++] = ptrChFromFile[i];
        }
        else
        {
            ptrWords[j][k] = 0;
            ptrWords[j] = realloc(ptrWords[j], k+1);
            j++;
            k = 0;
        }
    }
    // terminate and resize last word
    ptrWords[j][k] = 0;
    ptrWords[j] = realloc(ptrWords[j], k+1);
    j = 0;
    k = 0;

    // crunchWord code starts here:
      ptrCrunchWord = malloc(sizeof(char*));
      ptrCrunchWord[0] = malloc(strSize);

      if (ptrCrunchWord == NULL || ptrCrunchWord[0] == NULL)
       {
           puts("failed to allocate memory");
           exit(EXIT_FAILURE);
       }


    for (i = 0; i < numberOfWords; i++)
    {
        int randomIndex = rand() % numberOfWords;

    if (compareWords(ptrCrunchWord[i], ptrWords[randomIndex]) != 0) 
    {
        if (getStrLength(ptrWords[randomIndex]) >= defaultWordLength) 
        {
            ptrCrunchWord[i] = ptrWords[randomIndex]; // main problem here
        }
    }
}

    printf("The crunch word is: %s", ptrCrunchWord[0]);


    for (i = 0; i < numberOfWords; i++) // Free's allocated memory from all pointers
    {
        free(ptrWords[i]);
    }

    free(ptrChFromFile);
    free(ptrWords);
    free(ptrCrunchWord[0]);
    free(ptrCrunchWord);

    return 0;
}

这是最新的代码。我需要做的最后一件事是将所有大于或等于6的单词存储在ptrCrunchWord中。我的主要问题是在ptrCrunchWord [0]中为最后的紧缩词分配空间,并将这些词存储在索引0中。我仅在元素中分配空间,因为ptrCrunchWord中将仅存储一个词。我编写了两种方法,一种检查每个单词的长度,另一种方法比较两个单词以查看它们是否相同。最后,我需要打印紧缩单词,不带空格。

谢谢

1 个答案:

答案 0 :(得分:1)

此循环是错误的:

for (i = 0; i < strSize; i++)
{
    if (ptrChFromFile[i] != ' ')
    {
        ptrWords[j] = &ptrChFromFile[i];
    }
    else
    {
        ptrWords[j] = 0;
        j++;
    }
}

您不应该重新分配ptrWords[j],您应该将其复制到上一个循环中分配的内存中。您需要另一个变量k来保存要在目标数组中分配的索引。

int k = 0;
for (i = 0; i < strSize; i++)
{
    if (ptrChFromFile[i] != ' ')
    {
        ptrWords[j][k++] = ptrChFromFile[i];
    }
    else
    {
        ptrWords[j][k] = 0;
        j++;
        k = 0;
    }
}

您还为ptrWords分配了过多的内存。每个单词分配的字符与文件的整个大小一样多。到达每个单词的末尾时,在分配ptrWords[j][k] = 0之后,您可以使用以下方法将该分配缩小为单词的大小:

ptrWords[j] = realloc(ptrWords[j], k+1);

另一个问题是您初始化了strSize = 1;。这导致您将输入的第一个字符放入ptrChFromFile[1]而不是ptrChFromFile[0]中,因此第一个单词不能正确复制。应该将其初始化为int strSize = 0。但是要对此更改进行调整,您需要将所有ptrChFromFile分配增加1个字符(或在末尾再进行另一个realloc来为尾随的null添加空间)。

ptrWords[i]分配内存时,请勿乘以sizeof(char *)ptrWords是指针数组,ptrWords[i[char数组。

完成将初始输入读入ptrChFromFile的循环后,需要递增numberOfWords。否则,您将不会计算换行符之前的最后一个单词。

您不应该在释放所有ptrWords[i]的末尾删除循环。您用malloc分配的所有内容都需要释放。

这是工作版本:

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

int main(void)
{
    int ch;
    char *ptrChFromFile;
    char **ptrWords;
    int strSize = 0;
    int i;
    int j = 0;
    int k = 0;
    int numberOfWords = 1;

    ptrChFromFile = malloc(2);

    if (ptrChFromFile == NULL)
    {
        puts("COULDN'T ALLOCATE MEMORY");
        exit(EXIT_FAILURE);
    }

    while ((ch = getchar()) != '\n')
    {
        ptrChFromFile = realloc(ptrChFromFile, (strSize+2));

        if (ptrChFromFile == NULL)
        {
            puts("failed to allocate memory");
            exit(EXIT_FAILURE);
        }

        if (ch == ' ')
        {
            numberOfWords++;
        }

        ptrChFromFile[strSize] = ch;
        strSize++;
    }
    numberOfWords++; // increment for last word

    ptrChFromFile[strSize] = 0;

    ptrWords = malloc(sizeof(char*) * numberOfWords); //creates number of slots in ptrWords

    for (i = 0; i < numberOfWords; i++) // allocates number of bytes in each slot.
    {
        ptrWords[i] = malloc(strSize);
        if (ptrWords[i] == NULL)
        {
            puts("failed to allocate memory");
            exit(EXIT_FAILURE);
        }
    }

    if (ptrWords == NULL)
    {
        puts("failed to allocate memory");
        exit(EXIT_FAILURE);
    }

    for (i = 0; i < strSize; i++)
    {
        if (ptrChFromFile[i] != ' ')
        {
            ptrWords[j][k++] = ptrChFromFile[i];
        }
        else
        {
            ptrWords[j][k] = 0;
            ptrWords[j] = realloc(ptrWords[j], k+1);
            j++;
            k = 0;
        }
    }
    printf("%s\n", ptrWords[0]);

    for (i = 0; i < strSize; i++) {
        free(ptrWords[i]);
    }
    free(ptrChFromFile);
    free(ptrWords);

    return 0;
}