从 stdin、C 读取未知行数

2024-04-15

我在读取未知大小的标准输入时遇到问题。事实上,它是 .txt 文件中的一个表,我通过调用参数 '

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


int main(int argc,char *argv[])
{

   char words[10][1024];
   int i=0;
   while(feof(stdin)==0)
   {
      fgets(words[i],100,stdin); 
      printf("%s", words[i]);
      i++;
   }
   return 0;
}

但有一个问题,我不知道行数,在本例中是 10(我们知道行中的字符数 - 1024)。 如果有人知道解决方案,那就太好了。提前致谢。


您触及了困扰所有新 C 程序员的问题之一。如何动态分配所需的所有内存以摆脱静态限制,同时仍然跟踪内存中的“内容”集合。当您需要从输入中读取未知数量的“事物”时,通常会出现此问题。初始选项是(1)声明一些足够大的限制(违背目的),或者(2)根据需要动态分配指针。

显然,目标是(2)。然而,你随后遇到了问题“我如何跟踪我分配的内容?”这本身就是困扰初学者的一个问题。问题是,如果我使用一堆指针动态分配,**如何迭代列表以获取我的“东西”?另外,您必须初始化一些初始数量的指针(除非使用链表等高级数据结构),所以下一个问题是“我用完了怎么办?”

通常的解决方案是分配一组初始指针,然后当达到限制时,重新分配到原始指针的两倍,然后继续。 (正如格雷森在回答中指出的那样)。

然而,还有一个技巧可以迭代列表以获取您的“东西”这是值得理解的。是的,您可以分配malloc并跟踪所使用的指针数量,但您可以将自己从绑定中解放出来counter通过最初分配到您的指针列表calloc。这不仅分配空间,而且还将分配的指针设置为NULL(或 0)。这允许您使用简单的方法迭代列表while (pointer != NULL)。这提供了很多好处当涉及到将指针集合传递给函数等时。缺点(最小的缺点)是您需要编写一个使用的重新分配方案calloc在需要时分配新空间。 (真糟糕,我变得更聪明了——但我必须努力做到这一点......)

您可以评估是否使用malloc/realloc现成的,或者是否使用重新分配calloc and a custom reallocate function取决于您的要求。无论如何,了解两者只会为您的编程工具箱添加更多工具。

好吧,闲聊够了,这些废话的例子在哪里?

以下两个示例都只是从任何文本文件中读取所有行并将这些行(带有指针索引号)打印回标准输出。两者都期望您提供要读取的文件名作为命令行上的第一个参数。两者之间唯一的区别是第二个有重新分配calloc完成是一个custom reallocation function。他们都分配255最初的指针数量,每次达到限制时将指针数量加倍。 (为了好玩,你可以设置MAXLINES像一些小东西10并强制重复重新分配进行测试)。

第一个在 main() 中重新分配的示例

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

#define MAXLINES 255

void free_buffer (char **buffer)
{
    register int i = 0;

    while (buffer[i])
    {
        free (buffer[i]);
        i++;
    }

    free (buffer);

}

int main (int argc, char **argv) {

    if (argc < 2) {
        fprintf (stderr, "Error: insufficient input. Usage: %s input_file\n", argv[0]);
        return 1;
    }

    char *line = NULL;      /* forces getline to allocate space for buf */
    ssize_t read = 0;       /* number of characters read by getline     */
    size_t n = 0;           /* limit number of chars to 'n', 0 no limit */
    char **filebuf = NULL;
    char **rtmp = NULL;
    int linecnt = 0;
    size_t limit = MAXLINES;
    size_t newlim = 0;

    FILE *ifp = fopen(argv[1],"r");
    if (!ifp)
    {
        fprintf(stderr, "\nerror: failed to open file: '%s'\n\n", argv[1]);
        return 1;
    }

    filebuf = calloc (MAXLINES, sizeof (*filebuf)); /* allocate MAXLINES pointers           */

    while ((read = getline (&line, &n, ifp)) != -1) /* read each line in file with getline  */
    {
        if (line[read - 1] == 0xa) { line[read - 1] = 0; read--; } /* strip newline         */

        if (linecnt >= (limit - 1))                 /* test if linecnt at limit, reallocate */
        {
            newlim = limit * 2;                     /* set new number of pointers to 2X old */
            if ((rtmp = calloc (newlim, sizeof (*filebuf))))    /* calloc to set to NULL    */
            {
                /* copy original filebuf to newly allocated rtmp */
                if (memcpy (rtmp, filebuf, linecnt * sizeof (*filebuf)) == rtmp)
                {
                    free (filebuf);                 /* free original filebuf                */
                    filebuf = rtmp;                 /* set filebuf equal to new rtmp        */
                }
                else
                {
                    fprintf (stderr, "error: memcpy failed, exiting\n");
                    return 1;
                }
            }
            else
            {
                fprintf (stderr, "error: rtmp allocation failed, exiting\n");
                return 1;
            }
            limit = newlim;                         /* update limit to new limit    */
        }

        filebuf[linecnt] = strdup (line);           /* copy line (strdup allocates) */

        linecnt++;                                  /* increment linecnt            */
    }

    fclose(ifp);

    if (line) free (line);                          /* free memory allocated to line    */

    linecnt = 0;                                    /* reset linecnt to iterate filebuf */

    printf ("\nLines read in filebuf buffer:\n\n"); /* output all lines read            */
    while (filebuf[linecnt])
    {
        printf (" line[%d]: %s\n", linecnt, filebuf[linecnt]);
        linecnt++;
    }

    printf ("\n");

    free_buffer (filebuf);                          /* free memory allocated to filebuf */

    return 0;
}

在自定义函数中重新分配的第二个示例

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

#define MAXLINES 255

/* function to free allocated memory */
void free_buffer (char **buffer)
{
    register int i = 0;

    while (buffer[i]) 
    { 
        free (buffer[i]); 
        i++; 
    }

    free (buffer);

}

/* custom realloc using calloc/memcpy */
char **recalloc (size_t *lim, char **buf)
{
    int newlim = *lim * 2;
    char **tmp = NULL;

    if ((tmp = calloc (newlim, sizeof (*buf))))
    {
        if (memcpy (tmp, buf, *lim * sizeof (*buf)) == tmp)
        {
            free (buf);
            buf = tmp;
        }
        else
        {
            fprintf (stderr, "%s(): error, memcpy failed, exiting\n", __func__);
            return NULL;
        }
    }
    else
    {
        fprintf (stderr, "%s(): error, tmp allocation failed, exiting\n", __func__);
        return NULL;
    }

    *lim = newlim;

    return tmp;
}

int main (int argc, char **argv) {

    if (argc < 2) {
        fprintf (stderr, "Error: insufficient input. Usage: %s input_file\n", argv[0]);
        return 1;
    }

    char *line = NULL;      /* forces getline to allocate space for buf */
    ssize_t read = 0;       /* number of characters read by getline     */
    size_t n = 0;           /* limit number of chars to 'n', 0 no limit */
    char **filebuf = NULL;
    int linecnt = 0;
    size_t limit = MAXLINES;

    FILE *ifp = fopen(argv[1],"r");
    if (!ifp)
    {
        fprintf(stderr, "\nerror: failed to open file: '%s'\n\n", argv[1]);
        return 1;
    }

    filebuf = calloc (MAXLINES, sizeof (*filebuf)); /* allocate MAXLINES pointers           */

    while ((read = getline (&line, &n, ifp)) != -1) /* read each line in file with getline  */
    {
        if (line[read - 1] == 0xa) { line[read - 1] = 0; read--; } /* strip newline         */

        if (linecnt >= (limit - 1))                 /* test if linecnt at limit, reallocate */
        {
            filebuf = recalloc (&limit, filebuf);   /* reallocate filebuf to 2X size        */
            if (!filebuf)
            {
                fprintf (stderr, "error: recalloc failed, exiting.\n");
                return 1;
            }
        }

        filebuf[linecnt] = strdup (line);           /* copy line (strdup allocates)     */

        linecnt++;                                  /* increment linecnt                */
    }

    fclose(ifp);

    if (line) free (line);                          /* free memory allocated to line    */

    linecnt = 0;                                    /* reset linecnt to iterate filebuf */

    printf ("\nLines read in filebuf buffer:\n\n"); /* output all lines read            */
    while (filebuf[linecnt])
    {
        printf (" line[%d]: %s\n", linecnt, filebuf[linecnt]);
        linecnt++;
    }

    printf ("\n");

    free_buffer (filebuf);                          /* free memory allocated to filebuf */

    return 0;
}

看一下这两个例子。知道有很多很多方法来做到这一点。这些示例仅提供了一种方法,该方法提供了使用一些通常无法找到的额外技巧的示例。尝试一下。如果您需要更多帮助,请发表评论。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

从 stdin、C 读取未知行数 的相关文章

  • 为什么存在 async 关键字

    浏览 msdn 9 频道视频时 我发现以下未答复的评论 希望有人能解释一下 我不明白 async 关键字的意义 为什么不直接允许 任何时候方法返回任务时都会使用await关键字 就像迭代器一样 可以在任何返回 IEnumerable 的方法
  • 将字节数组转换为托管结构

    更新 这个问题的答案帮助我编写了开源项目GitHub 上的 AlicanC 现代战争 2 工具 https github com AlicanC AlicanC s Modern Warfare 2 Tool 你可以看到我是如何阅读这些数据
  • SSL/TLS/HTTPS 站点在 C#/.NET WebBrowser 控件中非常慢,但在 Internet Explorer 中则很好

    背景 我正在修改自动维基浏览器 http en wikipedia org wiki Wikipedia AutoWikiBrowser使用托管在安全服务器上的 MediaWiki 站点 我允许用户通过 C 应用程序中的 WebBrowse
  • 选择列表逻辑应位于 ASP.NET MVC、视图、模型或控制器中的什么位置?

    我觉得我的问题与这个问题很接近 但我想对这样的代码应该放在哪里进行更一般的讨论 Asp Net MVC SelectList 重构问题 https stackoverflow com questions 2149855 asp net mv
  • 带 If 的嵌套 For 循环的时间复杂度

    void f int n for int i 1 i lt n i if i int sqrt n 0 for int k 0 k lt pow i 3 k do something 我的思考过程 执行if语句的次数 sum i 1 to
  • HttpWebRequest vs Webclient(特殊场景)

    我知道这个问题之前已经回答过thread https stackoverflow com questions 1694388 webclient vs httpwebrequest httpwebresponse 但我似乎找不到详细信息 在
  • 2D morton 码编码/解码 64 位

    如何将给定 x y 的莫顿代码 z 顺序 编码 解码为 32 位无符号整数 生成 64 位莫顿代码 反之亦然 我确实有 xy2d 和 d2xy 但仅适用于 16 位宽的坐标 产生 32 位莫顿数 在网上查了很多 但没有找到 请帮忙 如果您可
  • OpenCV 2.4.3 中的阴影去除

    我正在使用 OpenCV 2 4 3 最新版本 使用内置的视频流检测前景GMG http docs opencv org modules gpu doc video html highlight gmg gpu 3a 3aGMG GPU算法
  • 默认析构函数做了多少事情

    C 类中的默认析构函数是否会自动删除代码中未显式分配的成员 例如 class C public C int arr 100 int main void C myC new C delete myC return 0 删除 myC 会自动释放
  • asp.net网格分页的SQL查询

    我在用iBatis and SQLServer 使用偏移量和限制进行分页查询的最佳方法是什么 也许我添加该列ROW NUMBER OVER ORDER BY Id AS RowNum 但这只会阻止简单查询的数据访问 在某些情况下 我使用选择
  • WPF。如何从另一个窗口隐藏/显示主窗口

    我有两个窗口 MainWindow 和 Login 显示登录的按钮位于主窗口 this Hide Login li new Login li Show 登录窗口上有一个检查密码的按钮 如果密码正确 我如何显示主窗口 将参数传递给 MainW
  • 初始化 LPCTSTR /LPCWSTR [重复]

    这个问题在这里已经有答案了 我很难理解并使其正常工作 基本上归结为我无法成功初始化这种类型的变量 它需要有说的内容7 2E25DC9D 0 USB003 有人可以解释 展示这种类型的正确初始化和类似的值吗 我已查看此站点上的所有帮助 将项目
  • 使用 iTextSharp 5.3.3 和 USB 令牌签署 PDF

    我是 iTextSharp 和 StackOverFlow 的新手 我正在尝试使用外部 USB 令牌在 C 中签署 PDF 我尝试使用从互联网上挖掘的以下代码 Org BouncyCastle X509 X509CertificatePar
  • 为什么 Linux 对目录使用 getdents() 而不是 read()?

    我浏览 K R C 时注意到 为了读取目录中的条目 他们使用了 while read dp gt fd char dirbuf sizeof dirbuf sizeof dirbuf code Where dirbuf是系统特定的目录结构
  • C语言声明数组没有初始大小

    编写一个程序来操纵温度详细信息 如下所示 输入要计算的天数 主功能 输入摄氏度温度 输入功能 将温度从摄氏度转换为华氏度 独立功能 查找华氏度的平均温度 我怎样才能在没有数组初始大小的情况下制作这个程序 include
  • 受限 AppDomain 中的代码访问安全异常

    Goal 我需要在权限非常有限的 AppDomain 中运行一些代码 它不应该访问任何花哨或不安全的内容 except对于我在其他地方定义的一些辅助方法 我做了什么 我正在创建一个具有所需基本权限的沙箱 AppDomain 并创建一个运行代
  • OSError: [WinError 193] %1 不是有效的 Win32 应用程序,同时使用 CTypes 在 python 中读取自定义 DLL

    我正在尝试编写用 python 封装 C 库的代码 我计划使用 CTypes 来完成此操作 并使用 Visual Studio 来编译我的 DLL 我从一个简单的函数开始 在 Visual Studio 内的标头中添加了以下内容 然后将其构
  • 在 Xamarin 中获取 OutOfMemoryException

    java lang OutOfMemoryError 考虑增加 JavaMaximumHeapSize Java 执行时内存不足 java exe 我的 Visualstudio Xamarin 项目出现内存不足异常 请帮助我如何解决此问题
  • 带有私有设置器的 EFCore Base 实体模型属性 - 迁移奇怪的行为

    实体模型继承的类内的私有设置器似乎会导致 EFCore 迁移出现奇怪的问题 考虑以下示例 其中有多个类 Bar and Baz 继承自Foo 跑步时Add Migration多次命令 添加 删除private修饰符 生成的模式在多个方面都是
  • C#中为线程指定特殊的cpu

    我有 2 个线程 我想告诉其中一个在第一个 cpu 上运行 第二个在第二个 cpu 上运行 例如在具有两个 cpu 的机器中 我怎样才能做到这一点 这是我的代码 UCI UCIMain new UCI Thread UCIThread ne

随机推荐

  • google.script.run.withSuccessHandler() 返回未定义

    我使用下面提供的代码在单独的 GS 文件中创建了一个数组 我尝试在 HTML 文件中调用它 我的目标是将数组的内容与参数进行比较email 但是 返回的值google script run withSuccessHandler is und
  • 来自浏览器的带有正文的异步 GET 请求

    好吧 我知道这是一个坏主意 不应该这样做 但为了这个问题 请假设没有其他方法 我得到的 API 端点需要以空对象作为主体的 GET 请求 有没有办法从浏览器执行异步请求 我在用着axios使用的库XMLHttpRequest在引擎盖下和MD
  • 如何在Qt中暂时断开与插槽的信号?

    我用信号连接一个插槽 但现在我想暂时断开它们的连接 这是我的班级声明的一部分 class frmMain public QWidget private QTimer myReadTimer private slots void on btn
  • POST 请求(Javascript)

    如何在 Javascript 中发出简单的 POST 请求而不使用表单且不回发 虽然我从 sundeep 答案中获取代码示例 但为了完整性而将代码发布在此处 var url sample url php var params lorem i
  • 如何在 Django 1.8 中使用 jinja2 作为模板引擎

    我一直在研究如何在 django 1 8 中使用 jinja2 但是没有将 django 与 jinja2 一起使用的完整源代码 我想知道你们是否知道在 django 中使用 jinja2 的过程 我查看了官方文档并查看了以下问题 如何设置
  • 按 Option 键隐藏/显示应用程序主菜单中的菜单项

    我想在应用程序的主菜单中添加一个很少使用的菜单项 我希望它默认隐藏 仅当用户按住 Option 键时才显示 我该怎么做呢 看来我应该处理flagsChanged 但它是NSResponder的方法和NSMenu不继承自NSResponder
  • 为什么使用 boost 后 C++ 比 python 快得多?

    我的目标是用 Python 编写一个用于频谱有限元的小型库 为此我尝试使用 Boost 通过 C 库扩展 Python 希望它能让我的代码更快 class Quad public Quad int int double integrate
  • 将 TDD 与 Web 应用程序开发集成的最佳实践? [关闭]

    Closed 这个问题是基于意见的 help closed questions 目前不接受答案 单元测试和 ASP NET Web 应用程序在我的团队中是一个模棱两可的点 通常情况下 良好的测试实践会被忽视 Web 应用程序最终会在没有测试
  • 如何对库进行临时签名?

    尝试运行链接到动态库的可执行文件 出现以下错误 Library not loaded Reason tried
  • 为什么小于不起作用?

    这看起来很简单 但为什么这种比较不起作用呢 if nmax lt num nmax num 我把它放在一个循环中 寻找最大的数字 第一个数字是105 然后是89 然后是99 然后是一大堆大于99的数字 第一个数字是要测试的数字 第二个数字是
  • GWT:对RichTextArea进行文本限制并阻止用户输入更多字符

    我正在使用 GWT RixhText Area 并希望在 richText Area 中限制 100 个字符 现在我正在做这个 description addKeyDownHandler new KeyDownHandler Overrid
  • Elastic Beanstalk 剥离 Sec-WebSocket-Accept 标头

    我正在尝试让 NET Core 应用程序在 elastic beanstalk 上运行 以从浏览器中的 javascript 接收 websockets 连接 当我在本地计算机上测试 AWS 之外的客户端和服务器时 我能够在两者之间建立 W
  • 数据流:将 Top 模块与 Python SDK 结合使用:单元素 PCollection

    我正在查看 incubator beam 存储库上的 word counting py 示例 从数据流文档链接 我想修改它以获得n 出现次数最多的 这是我的管道 counts lines split gt gt beam ParDo Wor
  • Java中如何初始化日期类型变量?

    import java util Date Date firstDate 我不知道如何初始化firstDate例如对于你说的字符串 String line1 First line 但是日期的格式是什么 你能给我一个例子吗 以下是 Oracl
  • Python 中海量 numpy 数组的内存高效排序

    我需要使用 numpy 对非常大的基因组数据集进行排序 我有一个 26 亿个浮点数的数组 维度 868940742 3 加载后 它会占用我机器上大约 20GB 的内存 我有一台 2015 年初的 13 英寸 MacBook Pro 配备 1
  • 谷歌闭包编译器和json

    我有一个 json 字符串 我会解析它 然后使用点符号访问对象的属性 然而 在 google 闭包编译器中 点符号 MyObject PropertyName 给出该属性未定义的警告 目前 我使用的解决方案是将我的代码转换为括号表示法 My
  • Shouldly 断言库如何知道断言所应用到的表达式?

    The 适用于 NET 的 Shouldly 断言库 http shouldly readthedocs io en latest 以某种方式知道断言方法被调用的表达式 因此它能够将其显示到消息中 我试图找出它是如何工作的 但迷失在源代码中
  • spring + SQLite在多线程应用程序中

    我正在开发一个使用 SQLite 数据库和 spring 的应用程序 当多个线程尝试修改数据库时遇到问题 我收到错误 数据库文件被锁定 我配置了一个数据源
  • python-requests 和 django - CSRF 验证失败。请求已中止

    我有一个 django 服务器来上传文件 当我使用浏览器时 我可以毫无问题地上传文件 但是如果我使用 python requests 命令 它会告诉我 CSRF 验证失败 请求被中止 python请求代码如下 upload via HTTP
  • 从 stdin、C 读取未知行数

    我在读取未知大小的标准输入时遇到问题 事实上 它是 txt 文件中的一个表 我通过调用参数 include