小甲鱼C++快速入门 笔记(3)
本帖最后由 新手学习中 于 2014-7-27 15:25 编辑一、用户一次性输入数据,求和:
#include <stdio.h>#include <stdlib.h>
void main()
{
int i;
int sum = 0;
char ch;
printf("请输入一串整数和任意数目的空格: ");
while( scanf("%d", &i) == 1 )
{
sum += i;
while( (ch=getchar()) == ' ' )
;
// 屏蔽空格 ;
if( ch == '\n' )
{
break;
}
ungetc( ch, stdin );// 将变量ch 中存放的字符退回给stdin输入流。
}
printf("结果是: %d", sum);
printf("\n");
system("pause");
}
二、scanf("%d",&i)==1是什么
1、scanf的返回值
scanf函数规定,scanf有返回值,返回的是执行本函数一次所成功读取“数”的个数。(自动忽略缓冲区里的空格)
注意:如果第一个值读入失败,那么直接结束返回0.或者说,遇到读入失败,那么结束
scanf不再读下去,统计前面成功读入的个数,返回值。
2、scanf的缓冲区与用户输入的理解
scanf函数,只是读取输入流里符合要求的数据(自动忽略缓冲区里的空格),并不需要等待用户输入和回车结束。只有当输入流里无数据,或者不符合要求时,才会打开输入流输入开口,让用户往输入流里输入数据,以回车结束对输入流数据的输入。然后scanf函数再运行。执行scanf函数时,执行的并不是“录入用户输入的数”,而是缓冲区中“读取数”当然,缓冲区的数是由用户输入的,不过把scanf理解成“是记录用户输入的数”则会有差错。 scanf并不依赖回车结束。只有在无数据可读的情况下,才依赖回车。scanf函数,是读取输入流里的数据。只有当输入流里没数据时,它才会打开输入流的开口,让用户输入数据,直到回车,输入流开口关闭,函数才从输入流里读数据。准确的说,在无数据可读情况下,scanf打开输入流开口,等待用户输入,当用户输入符合一定要求时,以回车关闭输入流开口,scanf又开始运作,从输入流里读取数据。如果输入流 里本来就有符合要求的数据,那么scanf不会打开输入流开口,它会直接读取数据,运行函数,再执行下一流程,完全的后台操作。一般情况下,第一次执行,都是无数据的,所以就出现等待的情况。但如果一次性输入了两个数据,如: 如果我安排是用户输入2次的数据,也就是说开始运行一次scanf,代码中间又有一个scanf但是由于用户的失误,第一次输入的时候直接给了两个数。比如说14
那么运行时,就没有跳出第二次的scanf,而是直接两次的printf。
这种“程序错误”该如何避免呢?
#include <stdio.h>
void main()
{
int i,j;
scanf("%d", &i) ;
printf("%d",i);
scanf("%d", &j);
printf("%d",j);
}
用户第一次输入了8个数,回车。那么scanf设定是一次读取一个数,那么执行时它先从缓冲区里读取第一个数,第二次执行时,就读取缓冲区里第二个数。如果按照scanf是“记录用户输入的数”,那么每次循环用户都要输入数!这道题就难以理解为何能实现了!以下是百度网友回答:用户输入的数据被控制台放在键盘缓冲区中,敲入回车scanf(流输入,会把数据放在自已的缓冲区中,然后才开始真正的输入数据,够用则输入到变量中,多余数据放到流缓冲中结束输入,不够等待用户输入新数据并回车再从流缓冲中读数据直到够用为止!当流缓冲中有上次用户输入的没用完的数据时,直接从流缓冲中读取数据,再不需要回车了,除非流缓冲中的数据消耗完了,否则不用重新从键盘录入数据了!scanf本身的实现会有一个循环,流输入有一个结构记录键盘录入数据,只有回车才会更新数据,否则数据会一直存贮键盘缓冲区中
3、scanf运行原理导致的错误
如果我安排是用户输入2次的数据,也就是说开始运行一次scanf,代码中间又有一个scanf
但是由于用户的失误,第一次输入的时候直接给了两个数。比如说14
那么运行时,就没有跳出第二次的scanf,而是直接两次的printf。
这种“程序错误”该如何避免呢?
#include <stdio.h>
void main()
{
int i,j;
scanf("%d", &i) ;
printf("%d",i);
scanf("%d", &j);
printf("%d",j);
}
4、为何scanf有时回车没反应
比如scanf设定读取5个数。那么如果用户只输入4个数就回车,scanf不会结束运行,它在
等待,等待用户输入第5个数。用户输入了,然后回车,就OK了。
三、using namespace std是什么
这句话不用深究什么意思,解释也需要深入其汇编原理,只需要知道,程序开始就写这
一句。这是为了变量名不重复。
具体以下解释也不太准确,反正这个问题深入研究为什么比较复杂,目前的知识是理解不
了的。
1,C++中如果不写这句话,后面按照C去声明变量,那么会报错
2,因为一个程序可能有很多人去写,从而有大量的变量名,为了不重复,所以
C++中引入空间名。把std放在一个命名空间中,所有的函数,类都在这空间中。
3,如果不写,那么以后代码的变量名都需要std::cout这样来写,就很麻烦。
四、为何要用getchar()
1、为何要用getchar()
前面的scanf自己就带有从缓冲区顺序录入的功能,那么加上后面的sum = sum + i
不是就完成程序了么?
实际执行时,回车,无反应。
因为scanf循环最后一次后,发现没数据,就要求用户再次输入数据,用户输入,回车,
那么scanf再循环,再要求输入.......
所以,这里要使得scanf前面的while不循环,读到最后的时候就终止。这就需要在
scanf函数后面加上一点其他东西,来终止循环。而终止的标准是用户的回车,这里
就选择用getchar()函数。
2、getchar()函数潜规则
getchar()简易解释是:从缓冲区(输入流)中读入字符。
潜规则:
(1)、scanf在getchar前面,scanf提取一个数后,缓冲区中这个数就没有了,getchar只能从
这个数的后面提取。
(2)、scanf是提取数,自动排除空格,分隔符,以回车结束。getchar是读入字符,包含数字,空格,分隔符,还有最后的回车。如果对象是33,它会先提取3而不是33.
(3)、getchar提取了,缓冲区里被提取的字符也就没有了。
五、ungetc的作用
1、此程序的实现分析
(1),scanf第一次先运行,先读入第一个数。这个数就在缓冲区中没了。
(2),进行小循环的条件判断,因为第一个数没了,getchar只能读取第一个数后面的“字符”,也就是空格
(3),如果ch等于空格,那么不执行任何内容,再次进入小循环,调用getchar读入空格后面的字符。
(4),当读到不是空格的时候,跳出小循环,进入大循环中的下一步。但是!!!此时
ch已经被赋值了一个非空字符。而且缓冲区中的这个字符已经不在了!!!!
(5),利用ungetc把不在的非空字符给返回缓冲区中
(6),大循环一次结束。scanf再次读入。
(7),到了最后一个数,getchar把回车赋值给ch,这个时候直接break终止大循环,输出
sum的值。
2、ungetc功能
ungetc(ch,stdin);
表示将ch中的值返回给缓冲区(输入流stdin)
3、while的隐藏指令与空代码指令
while的隐藏指令
while (ch = getchar()==" ")
;
这里,用了空指令。
等于空格,啥都不执行。不等于呢?也不执行。那为何还要while循环呢?
也就是说,等于不等于,都不执行,不就等于没有这代码??
这是错误的。因为while的括号里面,还有一条指令: ch = getchar()
这是很容易被人遗忘的。不等于不执行。等于,则执行ch = getchar()
类似于for循环,特别容易让人忽略最后一步ch值的变化,以至于后面代码的出错
六、system("pause");是什么
命令行上输出一行类似于“Press any key to exit”的字,等待用户按一个键,然后返回。
七、我的错误
以下求和代码为何是这种结果??
: 输入:1 2 3 4 5 回车(无反应)再回车 结果:9
#include <stdio.h>#include <stdlib.h>
void main()
{
int i;
int sum = 0;
char ch;
printf("请输入一串整数和任意数目的空格: ");
while( scanf("%d", &i) == 1 )
{
sum += i;
while( getchar()== ' ' )
;// 屏蔽空格 ;
if( getchar() == '\n' )
{
break;
}
ungetc( getchar(), stdin );// 将变量ch 中存放的字符退回给stdin输入流。
}
printf("结果是: %d", sum);
printf("\n");
system("pause");
}
解析:这样将原程序ch替换成getchar(),因为我觉得ch是多此一举。可惜结果错了,我却找不出原因。
这样要注意,特别是条件句,循环句里,句子里面还有函数,虽然函数当做一个变量来处理,虽然可能条件句不成立不执行,循环不执行,但是函数却是执行了,函数一执行函数里面的变量可能就变了!
所以,一个条件句不执行,循环不执行,不代表什么都没有变!
我似乎已经第二次犯这个错误了。
还有一个问题,为何我要按两次回车才有结果??
这又是我对流程函数的不理解,因为scanf是包涵在while循环里面的。
八、VC++的调试功能如何用
在菜单 build 那里、具体难以文字描述
九、此求和程序C++实现代码
#include <iostream>
using namespace std;
int main()
{
int sum = 0;
int i;
cout << "请输入一串整数和任意数目的空格:";
while( cin >> i )
{
sum += i;
while( cin.peek() == ' ' )
{
cin.get();
}
if( cin.peek() == '\n' )
{
break;
}
}
cout << "结果是: " << sum << endl;
return 0;
}
十、与C不同点:cout与cin
cout 相当于 printf
cin相当于 scanf
scanf返回的是个数,或者0
而cin返回的是数的具体数值???或者0
cin.get()与cin.peek()
cin.get()相当于getchar()
cin.peek()从输入流中读取一个字符 但该字符并未从输入流中删除
要使用cin 需要#include <iostream>
十一、cin.get()与cin.peek的不同
cin.get()与cin.peek的不同:
一个是读取并删除 一个是读取不删除
举例:
#include <iostream>
using namespace std;
int main()
{
char p;
cout << "请输入一段文本: \n";
while( cin.peek() != '\n' )
{
p = cin.get();
cout << p;
}
cout << endl;
return 0;
}
这个程序中,如果cin.peek() 是读取删除,那么结果就会是残缺的。但是结果不残缺,说明cin.peek() 是读取不删除
读取不删除,这个功能大大简化了此程序。
十二、cin特性与再次发现scanf新特性
cin与scanf读取规律:
要求是输入整形,但是我们输入的是小数,那么结果是怎样呢?
比如输入3.15
cin 与scanf都是3
当定义输入2个整形变量,而实际是 3.15 5
结果是: 3垃圾值
也就是说,读第一个数,后面不符合,就停止,5也没有读出来3却是畸形的读出来。
十三、C与C++变量名位置的不同
C语言中,变量声明必须在前面。
而C++中,可以用到变量的时候再声明。
这样的好处是,可以让人看的明白,不然一大堆变量名放在前面,让人头晕
十四、const在这里效果等同于#define
#include <iostream>
using namespace std;
int main()
{
const int SIZE = 50;
char buf;
cout << "请输入一段文本: ";
cin.read( buf, 20 );
cout << "字符串收集到的字符数为: "
<< cin.gcount() << endl;
cout << "输入的文本信息是: ";
cout.write( buf, 20 );
cout << endl;
return 0;
}
#define SIZE 50(必须放在最前面)相当于 const intSIZE = 50(可以放在函数里面) 但是#define 与const 定义常量还有区别 。
十五、字符与字符串的难点区别
如果我们分配了10个字符串,那么实际只能用9个,还有一个是自动添加的/0
如:
#include <iostream>
using namespace std;
int main()
{
char buf;
cin.ignore(7);
cin.getline( buf, 10 );
cout << buf << endl;
return 0;
}
cin.ignore(7);表示忽略输入数据的前7个字符串(就是准7个)
cin.getline( buf, 10 );表示读取输入字符串的10个(按顺序,其实是9个)
这里只能读取9个因为字符串必须要以/0结尾,这是自动添加的。
十六、cin的其他5函数:
1、cin.read(); cout.write(); cin.gcount()
#include <iostream>
using namespace std;
int main()
{
const int SIZE = 50;
char buf;
cout << "请输入一段文本: ";
cin.read( buf, 20 );
cout << "字符串收集到的字符数为: "
<< cin.gcount() << endl;
cout << "输入的文本信息是: ";
cout.write( buf, 20 );
cout << endl;
return 0;
}
2、cout.precision() ;
#include <iostream>
#include <math.h>
using namespace std;
int main()
{
double result = sqrt(3.0);
cout << "对 3 开方保留小数点后0 ~ 9 位,结果如下: \n" << endl;
for( int i=0; i <= 9; i++ )
{
cout.precision(i);
cout << result << endl;
}
cout << "当前的输出精度为: " << cout.precision() << endl;
return 0;
}
3、cin.width();
#include <iostream>
using namespace std;
int main()
{
int width = 4;
char str;
cout << "请输入一段文本: \n";
cin.width(5);
while( cin >> str )
{
cout.width(width++);
cout << str << endl;
cin.width(5);
}
return 0;
}
**** Hidden Message *****
不错,谢谢楼主! O(∩_∩)O~真心不错啊O(∩_∩)O~ 怡静 发表于 2013-8-30 12:22 static/image/common/back.gif
不错,谢谢楼主!
哟哟~~~加分了~~~{:5_109:} 牡丹花下死做鬼 发表于 2013-8-30 12:47 static/image/common/back.gif
O(∩_∩)O~真心不错啊O(∩_∩)O~
小甲鱼C++信息量太大~~ 新手学习中 发表于 2013-8-30 18:52 static/image/common/back.gif
小甲鱼C++信息量太大~~
其实我也自己在写 但看到你的我自愧不如啊 {:5_100:} 牡丹花下死做鬼 发表于 2013-8-30 18:53 static/image/common/back.gif
其实我也自己在写 但看到你的我自愧不如啊
汗 别紧张 这是我以前写的,断断续续用了很久很久,效率是很低的。以至于后面小甲鱼C++教程我都没看了。话说你不是在写C语言吗?也在写C++? 新手学习中 发表于 2013-8-30 19:51 static/image/common/back.gif
汗 别紧张 这是我以前写的,断断续续用了很久很久,效率是很低的。以至于后面小甲鱼C++教程我都没看了。话 ...
学杂了 很多都一起的 O(∩_∩)O~ {:1_1:}看完再说
支持楼主~~哈哈哈哈哈哈 {:1_1:}不错,很好 去去去去去全球去去去去去去去去去去去去
不错,谢谢楼主!
不错,谢谢楼主! 先看看再说吧
好好看看 哈哈在!!!!!!!!!! {:5_103:}。。。。。。。。。。。。。。。。 谢谢楼主分享。。 看那一看{:1_1:} 感谢楼主分享,很喜欢这个教程