为未知长度的令牌分配足够的内存

时间:2010-08-14 06:34:45

标签: c

由于各种原因,我不在这里讨论,我在C中编写一个简单的标记化器。下面是一个示例,我在从输入流中读取字符时根据需要以预定的增量调整标记缓冲区的大小。它最终将达到最大令牌的大小,这显然可以容纳更小的令牌。这是一种可接受的方法吗?如果没有,确定为每个令牌分配的正确内存量的最佳方法是什么?

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

#define BUFF_CHUNK_SIZE 4

int main() {
    int c, i, n;
    char *buffer;

    i = 0;
    n = BUFF_CHUNK_SIZE;
    buffer = (char *)calloc(n, sizeof(char));

    while ((c = getchar()) != EOF) {
        if (isalnum(c)) {
            buffer[i] = (char)c;
            i++;
            if (i == n) {
                n += BUFF_CHUNK_SIZE;
                buffer = (char *)realloc(buffer, n * sizeof(char));
            }
        }
        else {
            if (i == 0) {
                continue;
            }
            i = 0;
            printf("%s\n", buffer);
            memset(buffer, 0, sizeof(char) * n);
        }
    }
    return 0;
}

2 个答案:

答案 0 :(得分:5)

这是非常正确的方法 - 有两个调整。

首先,代替添加常量BUFF_CHUNK_SIZE乘以通常更好。这意味着长度为N的长字符串上的realloc数量与log N成比例而不是N - 这意味着在realloc()中花费的时间与N log N成正比比N 2 。常量是什么并不重要--1.5可能是一个不错的选择(n += n / 2;)。

其次,在较长的程序中,您应该检查realloc()是否失败。

答案 1 :(得分:0)

realloc是对的,但你应该使用char作为token-separator?!

#define BUFF_CHUNK_SIZE 4
#define TOKSEP ";"

char *getOneToken(char *s,size_t n)
{
  int c;
  char *p=s;
  while( p-s < n-1 && !feof(stdin) && ((c=getchar())=='\n'?c=getchar():1) )
    if( isalnum(c) )
      *p++=c;
  *p=0;
  return s;
}

main() 
{
  char *buffer=calloc(1,1),
        tok[BUFF_CHUNK_SIZE+1];

  while( *getOneToken(tok,sizeof tok) )
  {
    buffer=realloc(buffer,strlen(buffer)+strlen(tok)+2);
    if( *buffer ) strcat(buffer,TOKSEP);
    strcat(buffer,tok);
  }

  puts(buffer);
  free(buffer);
  return 0;
}