gets() 仅读取换行符时会保存什么

2024-01-04

这是描述gets()来自普拉塔的C 底漆+:

通常,它从系统的标准输入设备获取一个字符串 你的键盘。因为字符串没有预定的长度,gets()需要一种方法来知道何时停止。它的方法是读取字符 直到到达换行符(\n) 字符,您生成的 按 Enter 键。它需要所有字符达到(但不是 包括)换行符,添加一个空字符(\0),并给出 字符串到调用程序。

这让我很好奇当gets()仅读入换行符。所以我写了这个:

  int main(void)
  {
    char input[100];

    while(gets(input))
    {
      printf("This is the input as a string: %s\n", input);
      printf("Is it the string end character? %d\n", input == '\0');
      printf("Is it a newline string? %d\n", input == "\n");
      printf("Is it the empty string? %d\n", input == "");
    }

    return 0;
  }

这是我与该程序的交互:

$ ./a.out
This is some string
This is the input as a string: This is some string
Is it the string end character? 0
Is it a newline string? 0
Is it the empty string? 0

This is the input as a string:
Is it the string end character? 0
Is it a newline string? 0
Is it the empty string? 0

当我按下回车键时,第二个块确实是有趣的事情。到底是什么input在这种情况下?这似乎不是我的猜测:\0 or \n or "".


这部分在描述中gets可能会令人困惑:

它需要所有字符直到(但不包括)换行符

或许更好的说法是takes所有角色包括换行符但是stores所有字符不包括换行符。

所以如果用户输入some string, the gets函数将读取some string和来自用户终端的换行符,但仅存储some string在缓冲区中 - 换行符丢失。这很好,因为无论如何没有人想要换行符 - 它是一个控制字符,而不是用户想要输入的数据的一部分。

Therefore, if you only press enter, gets interprets it as an empty string. Now, as noted by some people, your code has multiple bugs.


printf("This is the input as a string: %s\n", input);

这里没问题,尽管您可能想用一些人工字符分隔字符串以更好地进行调试:

printf("This is the input as a string: '%s'\n", input);


printf("Is it the string end character? %d\n", input == '\0');

不好:您想在这里检查 1 个字节,而不是整个缓冲区。如果你尝试将整个缓冲区与 0 进行比较,答案总是false因为编译器会转换\0 to NULL并将比较解释为“缓冲区是否存在?”。

正确的方法是:

printf("Does the first byte contain the string end character? %d\n", input[0] == '\0');

这仅比较 1 个字节\0.


printf("Is it a newline string? %d\n", input == "\n");

不好:这将缓冲区的地址与"\n"- 答案总是false。 C 中比较字符串的正确方法是strcmp:

printf("Is it a newline string? %d\n", strcmp(input, "\n") == 0);

注意特殊用法:strcmp当字符串相等时返回 0。


printf("Is it the empty string? %d\n", input == "");

这里同样的错误。使用strcmp这里也:

printf("Is it the empty string? %d\n", strcmp(input, "") == 0);


顺便说一句,正如人们常说的,gets不能以安全的方式使用,因为它不支持缓冲区溢出保护。所以你应该使用fgets http://en.cppreference.com/w/c/io/fgets相反,尽管它不太方便:

char input[100];
while (fgets(input, sizeof input, stdin))
{
    ...
}

这可能会导致混乱:fgets不会从它读取的输入中删除换行字节。所以如果你更换gets在你的代码中fgets,你会得到不同的结果。幸运的是,您的代码将清楚地说明其中的差异。

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

gets() 仅读取换行符时会保存什么 的相关文章

随机推荐

  • 使用 iText 在横向模式下绘制线条

    这是我用来画线的代码 double lineArray annotation getAsArray PdfName L asDoubleArray double x1 lineArray 0 rect getAsNumber 0 doubl
  • 对某一部分贪婪的正则表达式,对其他部分不贪婪的正则表达式

    我在 R 中使用正则表达式 但我希望它对左侧部分贪婪 对右侧部分非贪婪 假设我想提取单词 left 和 right 之间的文本 但我希望它是贪婪的 并继续在文本中查找单词 left 直到找到最后一次出现 但是 我也希望它不贪婪于 正确 并在
  • 将 SpatialPolygonsDataFrame 导出为 R 中的 geojson 或 topojson

    我正在尝试将伦敦地方当局的 geojson 转换为六角形图表 其中每个六边形代表一个地方当局 它在 R 中工作 但是当我尝试将生成的十六进制网格导出为 geojson 或 topojson 时 出现以下错误 Error in sp Spat
  • 实体框架 4.1 检索自引用数据

    我首先使用 Entity Framework 4 1 代码和 ASP NET MVC 3 并且我正在努力正确设置自引用 我有一个类别类 它必须是自我引用的 当表中ParentCategoryId为空时 类别可以是父类别 如果某个类别具有带值
  • 直接从 Outlook 拖放到 Web 表单

    我在网上搜索了一下 大部分答案都是无法完成 我的情况有点不同 因为我们正在开发的应用程序仅用于内部目的 并且可以允许浏览器中的任何安全级别 它也是基于内部网的 我还尝试查看是否有现成的 ActiveX 控件 但无法找到一个允许直接从 Out
  • Sympy - 改变绘图的 y 轴范围

    使用 Sympy 如何设置 y 轴的范围 plot x 2 2 我想让 y 轴从 0 到 7 当你绘图时 你可以使用 kwargsxlim and ylim设置轴限制 例如 gt gt gt plot x 2 2 xlim 3 3 ylim
  • 使用 Delphi 在运行时创建 TWebBrowser

    我有一个 TWebBrowser 对象 它在运行时创建并在后台使用 即不可见 问题是像 OnDocumentComplete 这样的事件在 Delphi2009 中不起作用或不会被触发 有什么建议吗 procedure TfrmMain F
  • 将文件写入通用应用程序数据文件夹被拒绝

    我使用以下函数将数据写入用户应用程序文件夹 private void WriteToLog string source string method string msg string LogFile Environment GetFolde
  • 对一系列门票进行排序[关闭]

    Closed 这个问题需要调试细节 help minimal reproducible example 目前不接受答案 这是问题陈述 您有一叠包含出发地和目的地的车票 您将获得出发城市和目的地城市 你如何从堆栈中找到你的路线 这是我的解决方
  • 哪个更好的Javascript对象模式[关闭]

    就目前情况而言 这个问题不太适合我们的问答形式 我们希望答案得到事实 参考资料或专业知识的支持 但这个问题可能会引发辩论 争论 民意调查或扩展讨论 如果您觉得这个问题可以改进并可能重新开放 访问帮助中心 help reopen questi
  • 使用“catch,when”捕获异常

    我在 C 中发现了这个新功能 它允许在满足特定条件时执行 catch 处理程序 int i 0 try throw new ArgumentNullException nameof i catch ArgumentNullException
  • 在 python 函数中使用 *args、**kwargs 时“获得关键字参数的多个值”

    传递命名参数时request通过 kwargs 我收到一个错误 Traceback most recent call last File testKwargs py line 9 in
  • Python re.findall

    我试图检索包含 名称 字段的所有标签 然后处理整个句子加上名称 这是我的测试代码 sourceCode
  • 无法将 4/23/12 12:00 AM 类型类 java.util.Date 转换为类 java.sql.Date

    我正在将我的项目从 WebSphere 7 迁移到 WebSphere 8 并且使用 JSF 1 2 我遇到了 IBM JSF html extended 标签和标准转换器的问题 这些转换器主要是 JSF 1 2 核心组件 我还将我的 Ja
  • 在R中绘制网络(控制边缘厚度加上不重叠的边缘)

    我需要使用 R 绘制一个具有 5 个节点和 20 个有向边 连接每 2 个节点的边 的网络 但我需要存在两个功能 能够控制每个边缘的厚度 边缘不重叠 即 从 A 到 B 的边缘不绘制在从 B 到 A 的边缘之上 我花了几个小时寻找解决方案
  • Scipy:ipython 笔记本中的并行计算?

    我正在做一个kernel density estimation数据集 点的集合 The estimation process没关系 问题是 当我试图获得density value对于每个点 速度都很慢 from sklearn neighb
  • 在 R 中对大数据进行 one-hot 编码的有效方法

    我正在尝试创建我的数据的独热表示 这是我的方法 data iris iris as data frame apply iris 2 function x as factor x head iris iris ohe lt data fram
  • 将控制值作为 html.Pagedlist 参数传递

    我正在使用分页列表来显示值列表 显示器工作正常 我使用提供的 Unobtrusive AJAX 来获取其他页面的数据 这就是我的分页控件的外观 Html PagedListPager Model CountryList page gt Ur
  • 如何在自定义容器视图控制器中实现交互式转换

    我实现了自己的自定义容器视图控制器 并尝试使其与 iOS 7 视图控制器转换兼容 我使我的自定义容器视图控制器符合UIViewControllerContextTransitioning我发送self当我打电话时transitionDura
  • gets() 仅读取换行符时会保存什么

    这是描述gets 来自普拉塔的C 底漆 通常 它从系统的标准输入设备获取一个字符串 你的键盘 因为字符串没有预定的长度 gets 需要一种方法来知道何时停止 它的方法是读取字符 直到到达换行符 n 字符 您生成的 按 Enter 键 它需要