【问题标题】:Read all data from stdin C从标准输入 C 读取所有数据
【发布时间】:2014-11-24 04:34:15
【问题描述】:

我编写了这个小函数来读取来自stdin 的所有数据。

我需要知道这个函数是否兼容 POSIX(我的意思是它可以在 Unix 和类 Unix 系统下工作)至少它可以在 Windows 上工作......

char* getLine()
{
    int i = 0, c;
    char* ptrBuff = NULL;

    while ((c = getchar()) != '\n' && c != EOF)
    {
        if ((ptrBuff = (char*)realloc(ptrBuff, sizeof (char)+i)) != NULL)
            ptrBuff[i++] = c;
        else
        {
            free(ptrBuff);
            return NULL;
        }
    }

    if (ptrBuff != NULL)
        ptrBuff[i] = '\0';

    return ptrBuff;
}

该函数从标准输入读取所有数据,直到获得'\n'EOF,并返回一个指向包含所有字符的新位置的指针。我不知道这是否是最优化或更安全的方法,也不知道这是否适用于 Unix 和类 Unix 系统......所以,我需要一点帮助。我该如何改进该功能?或者有没有更好的方法从stdin 获取所有数据而不在缓冲区上留下垃圾?我知道fgets() 是一个选项,但是如果用户输入大于预期,它可能会留下垃圾......另外,我想获取用户编写的所有字符。

编辑:

新版getLine()

char* readLine()
{
    int i = 0, c;
    size_t p4kB = 4096;
    void *nPtr = NULL;
    char *ptrBuff = (char*)malloc(p4kB);

    while ((c = getchar()) != '\n' && c != EOF)
    {
        if (i == p4kB)
        {
            p4kB += 4096;
            if ((nPtr = realloc(ptrBuff, p4kB)) != NULL)
                ptrBuff = (char*)nPtr;
            else
            {
                free(ptrBuff);
                return NULL;
            }
        }
        ptrBuff[i++] = c;
    }

    if (ptrBuff != NULL)
    {
        ptrBuff[i] = '\0';
        ptrBuff = realloc(ptrBuff, strlen(ptrBuff) + 1);
    }

    return ptrBuff;
}

最后编辑:

这是char* readLine() 函数的最终版本。现在我看不到更多的错误,也看不到改进它的最佳方法,如果有人知道更好的方法,请告诉我。

char* readLine()
{
    int c;
    size_t p4kB = 4096, i = 0;
    void *newPtr = NULL;
    char *ptrString = malloc(p4kB * sizeof (char));

    while (ptrString != NULL && (c = getchar()) != '\n' && c != EOF)
    {
        if (i == p4kB * sizeof (char))
        {
            p4kB += 4096;
            if ((newPtr = realloc(ptrString, p4kB * sizeof (char))) != NULL)
                ptrString = (char*) newPtr;
            else
            {
                free(ptrString);
                return NULL;
            }
        }
        ptrString[i++] = c;
    }

    if (ptrString != NULL)
    {
        ptrString[i] = '\0';
        ptrString = realloc(ptrString, strlen(ptrString) + 1);
    } 
    else return NULL;

    return ptrString;
}

【问题讨论】:

  • 查看这篇博文:powerfield-software.com/?p=65 - 它也被用作 SO 上几个问题的答案。
  • 是的,你的函数是 POSIX,我在 Linux 中用 gcc 测试过,似乎可以正常工作。
  • 像这样一次分配一个字节会导致二次性能——这是不好的。您应该一次分配数据块,每次需要更多空间时,分配的空间可能会加倍。您还应该注意,ptrBuff = realloc(ptrBuff, new_size); 在分配失败时会泄漏内存,因为您在指向先前内存分配的唯一指针上写入了 NULL。 free(ptrBuff); 是安全的,因为 free(NULL) 是无操作的。它不会释放内存,因为ptfBuff 不再指向它。使用void *new_space = realloc(ptrBuff, new_size); 并检查是否为空。
  • 顺带一提,简单的 POSIX 兼容解决方案是使用 getline()。这也会根据需要分配内存。
  • @JonathanLeffler 抱歉,我的错误是:if ((newSpace = realloc(ptrBuff, p4kb)) != NULL) 但我在调试时正在测试,看看会发生什么......现在我怀疑我是否需要使用 free() 函数与否,因为当realloc() 失败时,newSpace 将包含一个空指针,而ptrBuff 将包含最后一个具有有效数据的有效指针...

标签: c unix posix stdin getchar


【解决方案1】:

POSIX 兼容:是的!

你只打电话给getchar()malloc()realloc()free(),所有这些都是 标准 C 函数,因此在 POSIX 下也可用。据我所知,您也完成了所有必要的返回码检查。鉴于此,该代码在任何支持malloc()stdin 的环境中都很好。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2015-05-28
    • 2012-04-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-12-03
    • 1970-01-01
    相关资源
    最近更新 更多