我可以用什么代替scanf进行输入转换? 您所在的位置:网站首页 svf12n65f能用什么替代 我可以用什么代替scanf进行输入转换?

我可以用什么代替scanf进行输入转换?

2023-11-09 01:02| 来源: 网络整理| 查看: 265

在这个答案中,我将假设您正在阅读和解释文本行。也许您是在提示用户,该用户正在输入内容并单击RETURN。也许您正在从某种数据文件中读取结构化文本行。

由于您正在阅读文本行,因此围绕读取一行文本的库函数来组织代码是很有意义的。标准功能是fgets(),尽管还有其他功能(包括getline)。然后,下一步就是以某种方式解释该行文本。

这是调用fgets以读取一行文本的基本方法:

char line[512]; printf("type something:\n"); fgets(line, 512, stdin); printf("you typed: %s", line);

这只是读入一行文本并将其打印出来。如所写,它有一些限制,我们将在稍后讨论。它还具有一个非常好的功能:作为第二个参数传递给我们的数字512 fgets是line我们要查询的数组的大小 fgets读取。这个事实-我们可以知道fgets允许读取的数量-意味着我们可以确保fgets不会对数组进行过多读取而使数组溢出。

因此,现在我们知道了如何读取一行文本,但是如果我们真的想读取整数,浮点数,单个字符或单个单词怎么办?(也就是说,如果什么 scanf,我们正在努力改善呼叫使用了一个格式说明像过%d,%f,%c,或%s?)

很容易将文本行(字符串)重新解释为其中的任何一种。要将字符串转换为整数,最简单(尽管不完美)的方法是调用atoi()。要转换为浮点数,请使用atof()。(还有更好的方法,稍后我们将看到。)这是一个非常简单的示例:

printf("type an integer:\n"); fgets(line, 512, stdin); int i = atoi(line); printf("type a floating-point number:\n"); fgets(line, 512, stdin); float f = atof(line); printf("you typed %d and %f\n", i, f);

如果您希望用户键入单个字符(也许y或是 n/是/否),则可以从字面上直接获取该行的第一个字符,如下所示:

printf("type a character:\n"); fgets(line, 512, stdin); char c = line[0]; printf("you typed %c\n", c);

(当然,这忽略了用户键入多字符响应的可能性;它悄悄地忽略了键入的任何其他字符。)

最后,如果您想让用户键入一个绝对不包含空格的字符串,如果您想处理输入行

hello world!

作为字符串"hello"后跟其他内容(这是scanf格式%s所要完成的工作),那么,在这种情况下,我花了一点时间,毕竟,以这种方式重新解释该行并不是那么容易问题的一部分将不得不等待一段时间。

但是首先我想回到我跳过的三件事。

(1)我们一直在打电话

fgets(line, 512, stdin);

读取数组line,其中512是数组的大小,line因此fgets知道不会溢出该数组。但是要确保512是正确的数字(特别是要检查是否有人对程序进行了更改以更改大小),则必须将其读回line声明的位置。这很麻烦,因此有两种更好的方法来保持大小同步。您可以,(a)使用预处理器为尺寸命名:

#define MAXLINE 512 char line[MAXLINE]; fgets(line, MAXLINE, stdin);

或者,(b)使用C的sizeof运算符:

fgets(line, sizeof(line), stdin);

(2)第二个问题是我们没有检查错误。读取输入时,应始终检查是否存在错误。如果出于某种原因fgets无法读取您要求的文本行,则通过返回空指针来表明这一点。所以我们应该做类似的事情

printf("type something:\n"); if(fgets(line, 512, stdin) == NULL) { printf("Well, never mind, then.\n"); exit(1); }

最后,还有问题,为了读文本行, fgets读取字符,并将其填充到您的阵列,直到它找到\n终止行字符,并且它填充\n字符到您的数组,太。如果您稍微修改我们前面的示例,您会看到此信息:

printf("you typed: \"%s\"\n", line);

如果我运行此程序并在提示我时键入“ Steve”,则会打印出

you typed: "Steve "

这"在第二行是因为字符串它读取和打印退了出去竟是"Steve\n"。

有时,多余的换行符无关紧要(例如当我们调用 atoi或时atof,因为它们都忽略了数字后的任何其他非数字输入),但有时却很重要。因此,通常我们希望剥离该换行符。有几种方法可以做到,我将在稍后介绍。(我知道我已经说了很多话。但是,我保证,我会回到所有这些事情上来的。)

在这一点上,您可能会想:“我以为您说的scanf 不好,否则这会更好。但是fgets开始看起来很麻烦。打电话scanf是如此简单!我不能继续使用它吗? ”

当然,scanf如果需要,您可以继续使用。(而且对于非常 简单的事情,从某些方面来说,它更简单。)但是,请不要因为它的17个怪癖和缺点之一使您失败而哭泣,或者由于输入您的信息而陷入无限循环没想到,或者当您不知道如何使用它来做更复杂的事情时。让我们看一下fgets的实际麻烦:

您始终必须指定数组大小。好吧,当然,这一点都不令人讨厌-这是一个功能,因为缓冲区溢出是一件很糟糕的事情。

您必须检查返回值。实际上,这很容易,因为要scanf正确使用它,您还必须检查其返回值。

您必须\n脱掉后背。我承认,这确实是一件令人讨厌的事。我希望有一个Standard函数,我可以为您指出这个小问题。(请没有人提出gets。)但是相比于scanf's17种不同的烦恼,我fgets每天都会采取这种烦恼。

那么如何做你带的是换行?三种方式:

(a)明显的方式:

char *p = strchr(line, '\n'); if(p != NULL) *p = '\0';

(b)狡猾而紧凑的方式:

strtok(line, "\n");

不幸的是,这并不总是可行。

(c)另一种紧凑而又模糊的方式:

line[strcspn(line, "\n")] = '\0';

而现在,这是的出路,我们可以回到另一件事我跳过了:的不完善atoi()和atof()。这些问题是,它们没有给您成功或失败成功的任何有用指示:它们静默地忽略尾随的非数字输入,并且如果根本没有数字输入,它们静默地返回0。首选的替代方法-也具有某些其他优点-是strtol和strtod。 strtol还可以让您使用10以外的底数,这意味着您可以(除其他外)获得%o或%x与scanf。但是,展示如何正确使用这些功能本身就是一个故事,对于已经变成零碎的叙述来说,这会太分心了,因此,我现在不再赘述。

您可能想解析的其余主要叙述性问题输入内容比单个数字或字符还要复杂。如果您想读取包含两个数字,多个空格分隔的单词或特定的框架标点符号的行,该怎么办?那就是事情变得有趣的地方,如果您尝试使用做事情的地方,事情可能会变得复杂scanf,并且既然您已经使用干净地阅读了一行文本,那么这里还有更多的选择fgets,尽管所有这些选择的全部内容可能会填满一本书,所以我们只能在这里刮擦表面。

我最喜欢的技术是将行划分为用空格分隔的“单词”,然后对每个“单词”做进一步的处理。这样做的一个主要标准功能是 strtok(它也有其问题,并且还对整个单独的讨论进行评分)。我自己的喜好是专用功能,用于构造指向每个分开的“单词”的指针的数组,这是我在本课程笔记中描述的功能 。无论如何,一旦你有“字”,你可以进一步处理每一个,也许与同atoi/ atof/ strtol/ strtod 我们已经看过的功能。

矛盾的是,尽管我们在这里花了很多时间和精力来弄清楚如何远离它scanf,但是处理刚刚阅读的文本行的另一种好方法 fgets是将其传递给sscanf。这样,您将获得的大多数优点scanf,而没有大多数缺点。

如果您的输入语法特别复杂,则可能适合使用“ regexp”库进行解析。

最后,您可以使用任何适合您的临时解析解决方案。您可以通过char *指针一次检查一行字符,以 检查所需字符。或者,您可以使用strchr或strrchr或strspn或strcspn或来搜索特定字符strpbrk。或者,您可以使用之前跳过的strtol或 strtod函数来解析/转换和跳过数字字符组。

显然还有更多可以说的,但希望本入门会帮助您入门。



【本文地址】

公司简介

联系我们

今日新闻

    推荐新闻

    专题文章
      CopyRight 2018-2019 实验室设备网 版权所有