确定数组的长度以提高内存效率

时间:2012-01-24 08:12:36

标签: c memory

用C语言编写一个函数:

  • 将存储在字符串中的句子作为唯一参数(例如,“这是一个短句子。”)。
  • 返回一个字符串,该字符串由每个单词中的字符数(包括标点符号)组成,空格分隔数字。 (例如,“4 2 1 5 9”)。

我写了以下程序:

 int main()    
    {  
            char* output;  
            char *input = "My name is Pranay Godha";  
            output = numChar(input);  
            printf("output : %s",output);  
            getch();  
            return 0;  
    }  


char* numChar(char* str)   
{   
        int len = strlen(str);  
    char* output = (char*)malloc(sizeof(char)*len);   
    char* out = output;  
    int count = 0;  

    while(*str != '\0')  
    {
        if(*str != ' ' )
        {
            count++;
        }
        else
        {

            *output = count+'0';
            output++;
            *output = ' ';
            output++;
            count = 0;

         }
         str++;
   }  
   *output = count+'0';  
   output++;  
   *output = '\0';  
   return out;  
}  

我只是想知道我为输出字符串分配了len的内存量,我觉得这比我应该分配的更多,因此会浪费一些内存。你能告诉我我能做些什么来提高记忆效率吗?

2 个答案:

答案 0 :(得分:6)

我看到很多小错误。如果我是你的导师,我会把你的解决方案评为“C-”。这里有一些关于如何将其变成“A +”的提示。

 char* output = (char*)malloc(sizeof(char)*len); 

上述两个主要问题。首先,你忘了“释放”你分配的内存。但这很容易被原谅。

实际真正的错误。如果你的字符串只有1个字符长(例如“x”),你只能分配一个字节。但是您可能需要将两个字节复制到字符串缓冲区中。一个'1'后跟一个空终止'\ 0'。最后一个字节被复制到无效的内存中。 :(

另一个错误:

*output = count+'0'; 

“count”大于9时会发生什么?如果“count”为10,那么* output将被赋予冒号,而不是“10”。

首先编写一个只计算字符串中单词数的函数。将此函数的结果分配给变量调用num_of_words。

由于您可能会有超过9个字符的单词,因此某些单词将有两个或更多个数字用于输出。而且你需要考虑每个数字之间的“空间”。并且不要忘记尾随的“空”字节。

如果你考虑一个1字节无符号整数在字符串表示中最多可以有3个字符('0'..'255')不包括空字符或负数的情况,那么sizeof(int )* 3是整数表示的最大字符串长度的合理估计(不包括空字符)。因此,您需要分配的内存量是:

 num_of_words = countWords(str);
 num_of_spaces = (num_of_words > 0) ? (num_of_words - 1) : 0;
 output = malloc(num_of_spaces + sizeof(int)*3*num_of_words + 1); // +1 for null char

所以这是一个相当不错的内存分配估计,但它肯定会在所有场景中分配足够的内存。

我认为你的程序中还有其他一些错误。首先,如果每个单词之间有多个空格,例如

"my     gosh"

我希望您的程序能够打印“2 4”。但是您的代码会打印其他内容。如果字符串中有前导或尾随空格,则可能存在其他错误。并且内存分配估计不考虑在这些情况下插入的额外垃圾字符。

更新

鉴于你坚持并试图在下面的答案中找到更好的解决方案,我会给你一个提示。我编写了一个函数,用于打印字符串中所有单词的长度。它实际上并没有分配字符串。它只是打印它 - 好像有人在你的函数要返回的字符串上调用了“printf”。你的工作是推断这个函数的工作原理 - 然后修改它以返回一个新的字符串(包含所有单词的整数长度),而不是只打印它。我建议你修改这个函数中的主循环,以保持字数的运行总和。然后分配一个size =(word_count * 4 * sizeof(int)+ 1)的缓冲区。然后再次循环输入字符串,将每个单词的长度附加到您分配的缓冲区中。祝你好运。

void PrintLengthOfWordsInString(const char* str)
{
    if ((str == NULL) || (*str == '\0'))
    {
        return;
    }

    while (*str)
    {
        int count = 0;

        // consume leading white space
        while ((*str) && (*str == ' '))
        {
            str++;
        }

        // count the number of consecutive non-space chars
        while ((*str) && (*str != ' '))
        {
            count++;
            str++;
        }

        if (count > 0)
        {
            printf("%d ", count);
        }
    }
    printf("\n");
}

答案 1 :(得分:1)

只要句子中的单词都不超过9个字符,输出数组的长度只需要是句子中的单词数,乘以2(以考虑空格),加上额外的一个用于null终止符。

所以对于字符串

My name is Pranay Godha

...你只需要一个长度为11的数组。

如果任何单词是十个字符或更多,您需要通过确定所需数字的长度来计算您的数组需要多少额外char。 (例如,长度为10个字符的单词显然需要两个char来存储数字10。)

真正的问题是,这一切都值得吗?除非你特别要求(作业?)使用输出数组中所需的最小空间,否则我会注意分配一个适当大的数组并在写入时执行一些边界检查。