为什么内存不分配?

时间:2015-05-17 06:49:29

标签: c arrays memory malloc word

我的任务是允许用户输入任何输入并打印字母和单词的出现次数。我们还要打印出字母中有多少个字母,两个,三个等字母。

单词函数在处理指针数组时有访问冲突。看起来malloc()函数没有正确地将内存分配给我的指针数组,我不确定我是否正确编码。

我实际上尝试将内存分配给数组的索引word[0],并且该索引具有正确分配的内存,但是当我使用循环时它永远不会工作,当我将鼠标悬停在数组上并检查每个索引它说" Bad PTR"。

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


void findLetters(char *ptr);
void findWords(char *point);


int main()
{
    char textStream[100]; //up to 98 characters and '\n\ and '\0'

    printf("enter some text\n");
    if (fgets(textStream, sizeof (textStream), stdin)) //input up to 99 characters
    {
        findLetters(textStream);
        findWords(textStream);
    }
    else
    {
        printf("fgets failed\n");
    }

    return 0;
}

void findLetters(char *ptr) //find occurences of all letters
{ /*Works fine*/ }

void findWords(char *point)
{
    int i = 0;
    int k = 0;
    int count = 0;
    int j = 0;
    int space = 0;
    int c = 0;
    char *word[50];
    char word1[50][100];
    char* delim = "{ } . , ( ) ";

    for (i = 0; i< sizeof(point); i++) //counts # of spaces between words
    {
        if ((point[i] == ' ') || (point[i] == ',') || (point[i] == '.'))
        {
            space++;
        }
    }
    char *words = strtok(point, delim);
    for(;k <= space; k++)
    {
        word[k] = malloc((words+1) * sizeof(*words));
    }

        while (words != NULL)
        {
            printf("%s\n",words);
            strcpy(words, word[j++]);
            words = strtok(NULL, delim);
        }

    free(words);
}

我的代码有什么问题?

3 个答案:

答案 0 :(得分:3)

 while (words != NULL)
 {
      printf("%s\n",words);
      strcpy(words, word[j++]);
      words = strtok(NULL, delim);
 }

free(words);

想想这段代码在做什么;它循环到words == NULL,然后尝试free (words),如果循环终止,则为NULL。所以,您正在尝试free NULL指针。

顺便说一句。您不需要释放strtok的返回值:Do I need to free the strtok resulting string?

编辑:解决方案是:

  1. for (i = 0; i< sizeof(point); i++)应为for (i = 0; i< strlen(point); i++) - sizeof(char*)不是字符串的长度, 但系统上的字符指针大小(4或8)。
  2. 在上面的for循环之后用以下内容替换所有内容:

    char *words = strtok(point, delim);
    for (; k <= space && words != NULL; k++)
    {
        if (k >= 50)    //size of the word array
        {
            puts ("Too many words!");
            return;
        }      
    
        word[k] = malloc(strlen(words) + 1);
    
        strcpy(word[k], words);
        words = strtok(NULL, delim);
    }
    
    for (int i = 0; i < k; i++)
        free(word[i]);
    
  3. 该代码来自Cool Guy的答案,除了他有一个错误 - 代码正在递增k两次。

    请注意,这段代码实际上是毫无意义的,它只是分配了一些内存,在那里复制了一些内容,并且在没有做任何事情的情况下释放了内存,但我假设你想在findWords函数中做其他事情之后。

答案 1 :(得分:2)

strtok'\0'替换所有分隔符(=它修改输入字符串)。

因此,如果您想构建一个包含指向输入数组中所有单词的指针的数组,您只需编写以下代码:

void findWords(char *point)
{
    int count = 0;
    char *word[50];
    char* delim = "{ } . , ( ) ";
    char *words = strtok(point, delim);

    count = 0;
    while (words != NULL)
    {
        word[count] = words;
        count++;

        printf("%s\n",words);
        words = strtok(NULL, delim);

        if (count >= 50)   // word is limited to char *word[50] !!!
        {
             printf("too much words!\n");
             break;
        }
    }

    /*
    ** now count contains the number of words and
    ** word[0 .. (count - 1)] contains the words
    */
}

无需分配内存。

运行这个小测试

char test1[] = "hallo test, 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50";
char test2[] = "hallo test (2)";

findWords(test1);
findWords(test2);

显示以下内容(离开函数findWords之前的断点): debugging function findWords

在功能findWords内,word的内容是正确的。

答案 2 :(得分:1)

尝试替换

for(;k <= space; k++)
{
    word[k] = malloc((words+1) * sizeof(*words));
}

    while (words != NULL)
    {
        printf("%s\n",words);
        strcpy(words, word[j++]);
        words = strtok(NULL, delim);
    }

free(words);

for(;k <= space && words != NULL; k++)
{
    //word[k] = malloc((words+1) * sizeof(*words)); //Doesn't do what you think; You need strlen
    word[k] = malloc( strlen(words) + 1); //+1 for the NUL-terminator

    printf("%s\n",words);
    strcpy(word[k], words); //Arguments were mixed up. You want the opposite
    words = strtok(NULL, delim);
}

for(int i = 0; i < k; i++)
    free(word[i]);       //Free each index as you've allocated each of them not `words`

另外,

for (i = 0; i< sizeof(point); i++)

应该是

for (i = 0; i< strlen(point); i++)

或更好

int len = strlen(point);
for (i = 0; i < len; i++)

因为sizeof(point)给出的char*大小不是您想要的。因此,请使用strlen