【问题标题】:C Best way to read series of characters without known lengthC 读取不知道长度的字符系列的最佳方法
【发布时间】:2016-12-19 12:27:17
【问题描述】:

我必须阅读一系列必须是括号的字符,但我不知道用户输入了多少个字符。所以我想每次添加输入时都使用realloc。 我必须使用scanf 来读取字符

我编写了这段代码,但我想知道是否有更安全或更好的方法。

char* read(void) 
{
    int  count = 0,
         valid = 1;
    char *str = NULL,
         *tmp = NULL;
    char input;

    printf("Digita sequenza di parentesi da analizzare: ");
    do
    {
        scanf("%c", &input);

        tmp = (char *)realloc(str, (++count) * sizeof(char));

        if(tmp != NULL) 
        {
            str = tmp;
            str[count-1] = input;

            /* check sul carattere letto verificando che sia una parentesi (escluso ENTER) */
            if((input != '(' &&
                input != ')' &&
                input != '[' &&
                input != ']' &&
                input != '{' &&
                input != '}' &&
                input != '\n') ||
                ((count == 1) &&
                (input == '\n')))
                valid = 0;
        }
        else 
        {
            valid = 0;
            free(str);
        }

    } while(input != '\n');

    /* TODO */
    /* str[count] = '\0'; */

    return (valid) ? str : NULL;
}

【问题讨论】:

  • 嗨,我认为有一个固定大小的缓冲区并在它满时填充它并重新分配更准确。
  • 通常单独跟踪“使用的字节数”和“可用的字节数”,一旦用完就将“可用的字节数”加倍。这减少了分配的数量,并提高了性能。不推荐为每个输入字符进行堆分配。

标签: c realloc


【解决方案1】:

我不建议在每次迭代时都进行重新分配。而是在开始时使用一些最佳大小的缓冲区,然后仅在超过此大小时才进行重新分配。如下:

#define DEFAULT_STEP_SIZE 64
char* read(void) 
{
    int  count = 0,
         valid = 1,
         num_alloc = 0;
    char *str = NULL,
         *tmp = NULL;
    char input;

    str = malloc(DEFAULT_STEP_SIZE * sizeof(char));
    if(str == NULL){
        return NULL;
    }
    num_alloc = 1;
    printf("Digita sequenza di parentesi da analizzare: ");
    do
    {
        scanf("%c", &input);

        if(count > num_alloc * DEFAULT_STEP_SIZE){
            ++num_alloc;
            tmp = (char *)realloc(str, (num_alloc * DEFAULT_STEP_SIZE) * sizeof(char));
            if(tmp == NULL){
                free(str);
                return NULL;
            }else{
                str = tmp;
            }
        }

        count++; 
        str[count-1] = input;

        /* check sul carattere letto verificando che sia una parentesi (escluso ENTER) */
        if((input != '(' &&
                    input != ')' &&
                    input != '[' &&
                    input != ']' &&
                    input != '{' &&
                    input != '}' &&
                    input != '\n') ||
                ((count == 1) &&
                 (input == '\n')))
            valid = 0;

    } while(input != '\n');

    /* TODO */
    /* str[count] = '\0'; */

    return (valid) ? str : NULL;
}

【讨论】:

  • 您面临的问题是什么?
  • 什么样的错误?我尝试了长字符串,但它仍然有效
  • 通过在 STEP 的大小处添加 +1 来求解,它来自我输入的最后一个 ENTER。
  • 是的。我必须用 '\0' 终止序列?
猜你喜欢
  • 1970-01-01
  • 2022-01-07
  • 1970-01-01
  • 1970-01-01
  • 2012-02-29
  • 2013-01-23
  • 2017-11-25
  • 2013-03-10
  • 1970-01-01
相关资源
最近更新 更多