getchar
getchar——读取字符的函数
int getchar(void)
返回类型为int,参数为void.
有人可能会有疑惑,getchar既然是读取字符的,为什么返回类型是int呢?
1、getchar其实返回的是字符的ASCII码值(整数)。
2、getchar在读取结束或者失败的时候,会返回EOF。
EOF意思是end of file,本质上是-1.
下面我们一起来看看下面这段代码什么意思
#include<stdio.h>
int main()
{
int ch = 0;
while ((ch = getchar()) != EOF)
{
putchar(ch);
}
return 0;
}
意思是
getchar先读取一个字符放到ch里面去,如果这个字符不等于EOF,就进入循环,打印这个字符。当getchar读到文件末尾或者结束时,它会返回一个EOF,此时结束循环。
我们来运行试一下

输入A,输出A;输入b,输出b…
当我们想要结束时,输入ctrl+Z,再按回车即可。
注意,如果上面的代码不用while循环的话,输入123,putchar()只会输出1。因为一个getchar一次只能读取一个字符。
我们再来看看下面这段代码
#include<stdio.h>
int main()
{
char password[20] = {0};
printf("请输入密码:>");
scanf("%s", password);
printf("请确认密码(Y/N):>");
int ch = getchar();
if (ch == 'Y')
{
printf("确认成功\n");
}
else
{
printf("确认失败\n");
}
return 0;
}
按理说,我们是想要输入密码,然后再输入N或者Y,根据我们输入的是N还是Y打印“确认成功”或“确认失败”。
我们来运行一下,看看是否是这样

可以看到,我们还没有输入Y或N,他就立马跳出来了一个“确认失败”
为什么会是这样呢?

我们来看看它其中的原理:
scanf和getchar都是输入函数,它们都是从键盘上来读取我们的数据,但它们不是直接从键盘上来读取我们的数据。它们和键盘之间有一个区域叫缓冲区。
输入函数先来看缓冲区中是否有数据,如果有,它直接就拿走了,不需要从键盘输入,如果缓冲区什么都没有,则需要从键盘输入,再拿走。

明白这个道理后,我们回到上面那串代码。
最开始缓冲区里没有东西,所以我们这行代码
scanf("%s", password);
就是从键盘输入密码,我们输入123456。为了让123456放进去,我们还敲了一个回车,所以缓冲区里为
123456\n
接下来就是scanf来读缓冲区里的字符串了,scanf读取的方式是读取\n之前的内容,所以读取的是123456.
printf("请确认密码(Y/N):>");后,就是下面这行代码:
int ch = getchar();
getchar用来接收字符,

getchar看到缓冲区中有数据(\n),直接取走,不需要从键盘输入。自然也就出现了我们上面运行结果的那一幕:还没输入N或Y,就立马跳出“确认失败”了。
那么我们怎么解决这个问题呢?
很自然就能想到需要先把缓冲区里清空。
那我们就在前面加一个getchar把缓冲区中的“\n”给清理掉。
即代码变为
#include<stdio.h>
int main()
{
char password[20] = {0};
printf("请输入密码:>");
scanf("%s", password);
getchar();//把缓冲区中的\n清理掉
printf("请确认密码(Y/N):>");
int ch = getchar();
if (ch == 'Y')
{
printf("确认成功\n");
}
else
{
printf("确认失败\n");
}
return 0;
}
运行一下即可发现,现在能够得到我们的理想结果。

不过又有一个问题,当我们输入密码为123456 789时(中间有一个空格),还没等我们输入N或Y,又立马跳出了“确认失败”。
这又是怎么回事呢?我们一起来看看
首先缓冲区里没有东西,我们需要通过键盘输入密码123456 789,

然后scanf就来取缓冲区中的数据,当它读到空格的时候,它就不再读了(这是scanf的一个作用性质)。
所以scanf就只取走了123456,而缓冲区中还剩下(空格) 789\n。

再往下,运行到getchar();这行代码,然而这里只有一个getchar,它只能读取一个字符,也就是只读了空格,缓冲区中还剩789\n。

再往下,就是我们的这行代码int ch = getchar();
getchar()一来就取走了缓冲区中的7,根本不需要我们从键盘输入N或Y。运行时自然它就自动跳出了“确认错误”。
所以我们需要把缓冲区中的东西先全部清走。
那我们就用一个循环,只要没读到\n,我们就一直用getchar读。
即
//把缓冲区中的内容全读走
while ( getchar() != '\n')
{
;
}
整段代码如下:
#include<stdio.h>
int main()
{
char password[20] = {0};
printf("请输入密码:>");
scanf("%s", password);
//把缓冲区中的内容全读走
while ( getchar() != '\n')
{
;
}
printf("请确认密码(Y/N):>");
int ch = getchar();
if (ch == 'Y')
{
printf("确认成功\n");
}
else
{
printf("确认失败\n");
}
return 0;
}
运行一下

是我们想要的效果。
以上就是关于getchar的用法的实例解析。如果对你有帮助,记得点赞👍+关注哦!
我的主页还有其他文章,欢迎学习指点。
关注我,让我们一起学习,一起成长吧!
我有一个字符串input="maybe(thisis|thatwas)some((nice|ugly)(day|night)|(strange(weather|time)))"Ruby中解析该字符串的最佳方法是什么?我的意思是脚本应该能够像这样构建句子:maybethisissomeuglynightmaybethatwassomenicenightmaybethiswassomestrangetime等等,你明白了......我应该一个字符一个字符地读取字符串并构建一个带有堆栈的状态机来存储括号值以供以后计算,还是有更好的方法?也许为此目的准备了一个开箱即用的库?
我主要使用Ruby来执行此操作,但到目前为止我的攻击计划如下:使用gemsrdf、rdf-rdfa和rdf-microdata或mida来解析给定任何URI的数据。我认为最好映射到像schema.org这样的统一模式,例如使用这个yaml文件,它试图描述数据词汇表和opengraph到schema.org之间的转换:#SchemaXtoschema.orgconversion#data-vocabularyDV:name:namestreet-address:streetAddressregion:addressRegionlocality:addressLocalityphoto:i
我正在使用ruby1.9解析以下带有MacRoman字符的csv文件#encoding:ISO-8859-1#csv_parse.csvName,main-dialogue"Marceu","Giveittohimóhe,hiswife."我做了以下解析。require'csv'input_string=File.read("../csv_parse.rb").force_encoding("ISO-8859-1").encode("UTF-8")#=>"Name,main-dialogue\r\n\"Marceu\",\"Giveittohim\x97he,hiswife.\"\
我正在查看instance_variable_set的文档并看到给出的示例代码是这样做的:obj.instance_variable_set(:@instnc_var,"valuefortheinstancevariable")然后允许您在类的任何实例方法中以@instnc_var的形式访问该变量。我想知道为什么在@instnc_var之前需要一个冒号:。冒号有什么作用? 最佳答案 我的第一直觉是告诉你不要使用instance_variable_set除非你真的知道你用它做什么。它本质上是一种元编程工具或绕过实例变量可见性的黑客攻击
在我的应用程序中,我需要能够找到所有数字子字符串,然后扫描每个子字符串,找到第一个匹配范围(例如5到15之间)的子字符串,并将该实例替换为另一个字符串“X”。我的测试字符串s="1foo100bar10gee1"我的初始模式是1个或多个数字的任何字符串,例如,re=Regexp.new(/\d+/)matches=s.scan(re)给出["1","100","10","1"]如果我想用“X”替换第N个匹配项,并且只替换第N个匹配项,我该怎么做?例如,如果我想替换第三个匹配项“10”(匹配项[2]),我不能只说s[matches[2]]="X"因为它做了两次替换“1fooX0barXg
我有一个正在构建的应用程序,我需要一个模型来创建另一个模型的实例。我希望每辆车都有4个轮胎。汽车模型classCar轮胎模型classTire但是,在make_tires内部有一个错误,如果我为Tire尝试它,则没有用于创建或新建的activerecord方法。当我检查轮胎时,它没有这些方法。我该如何补救?错误是这样的:未定义的方法'create'forActiveRecord::AttributeMethods::Serialization::Tire::Module我测试了两个环境:测试和开发,它们都因相同的错误而失败。 最佳答案
我正在处理旧代码的一部分。beforedoallow_any_instance_of(SportRateManager).toreceive(:create).and_return(true)endRubocop错误如下:Avoidstubbingusing'allow_any_instance_of'我读到了RuboCop::RSpec:AnyInstance我试着像下面那样改变它。由此beforedoallow_any_instance_of(SportRateManager).toreceive(:create).and_return(true)end对此:let(:sport_
简而言之错误:NOTE:Gem::SourceIndex#add_specisdeprecated,useSpecification.add_spec.Itwillberemovedonorafter2011-11-01.Gem::SourceIndex#add_speccalledfrom/opt/local/lib/ruby/site_ruby/1.8/rubygems/source_index.rb:91./opt/local/lib/ruby/gems/1.8/gems/rails-2.3.8/lib/rails/gem_dependency.rb:275:in`==':und
我收到格式为的回复#我需要将其转换为哈希值(针对活跃商家)。目前我正在遍历变量并执行此操作:response.instance_variables.eachdo|r|my_hash.merge!(r.to_s.delete("@").intern=>response.instance_eval(r.to_s.delete("@")))end这有效,它将生成{:first="charlie",:last=>"kelly"},但它似乎有点hacky和不稳定。有更好的方法吗?编辑:我刚刚意识到我可以使用instance_variable_get作为该等式的第二部分,但这仍然是主要问题。
我正在使用ruby2.1.0我有一个json文件。例如:test.json{"item":[{"apple":1},{"banana":2}]}用YAML.load加载这个文件安全吗?YAML.load(File.read('test.json'))我正在尝试加载一个json或yaml格式的文件。 最佳答案 YAML可以加载JSONYAML.load('{"something":"test","other":4}')=>{"something"=>"test","other"=>4}JSON将无法加载YAML。JSON.load("