C字符串与cin.ignore()一起产生的一个好玩的错误

今天看到了如下的一段程序,程序运行后得到的结果和我们需要的结果不一样。

#include <iostream>

using namespace std;
void main()
{
    char name[10];
    char age[2];
    cout<<"姓名 ";
    cin.getline(name,10);
    cout<<"年龄 "; 
    cin.ignore();
    cin.getline(age,1);
    cout<<"姓名 "<<name<<"  年龄 "<<age
          <<endl<<endl;
}

执行程序后会发现:年龄的输出是空的!

而当把 cin.getline(age,1)该为 cin.getline(age,2),若输入25,年龄的输出是5而不是2,而当把cin.ignore()注释掉,然后加上cin.getline(age,2),输出的结果才是对的。

我把这个问题做了如下分析:

分析1:
char name[10],age[2]这些是C字符串,或者成为字符串数组。它有一个很重要的准则就是:必须以"/0"结尾!它是以'/0'来判断字符串数组中数据结束的位置的。
对C字符串的赋值方法一般有两种:
(1)直接给它赋一个字符串:例如,char name[10]="kiwi";这种赋值方法会自动在C字符串末尾添'/0'.所以这里的name[10]在内存中是这样存储的:k i w i /0 /0 /0 /0 /0 /0 。但如果令:char name[10]="abcdefghijk";那么数组在内存中是这样存储的:
a b c d e f g h i /0 。  不过这样的赋值会产生溢出的错误
(2)以数组的方式为它初始化:例如:name[0]='k';name[1]='i';name[2]='w';name[3]='i',name[4]='/0';必须要有name[4]='/0',否则会产生错误!

分析2:
cin.ignore()的意思是删除输入流中的首个字符。但这里遇到的情况与我们平时遇到的情况有些不同,cin.ignore()在输入流的上面,但是即使这样,它也要等到输入流中有字符后删除其首个字符,不管是在它上面输入字符还是在它的下面输出字符。

下面这段程序中
cout<<"姓名 ";
cin.getline(name,10);
cout<<"年龄 ";
cin.ignore();
cin.getline(age,2);  //注意是2
cout<<"姓名 "<<name<<"  年龄 "<<age;
执行结果:
姓名 kiwi
年龄 25
姓名 kiwi    年龄 5

为什么年龄变成了5呢?因为先执行cin.getline(name,10),输入流中的kiwi都被name读走了,输入流中已经没有字符可以ignore了。所以cin.ignore()要等待输入流中出现字符的时候,删除其首个字符。也就是说,接下去执行cin.getline(age,2)的时候我们往输入流中输入流25,那么cin.ignore()就删除了输入流中的首个字符2,此时输入流中只剩下5了,存入了age中,而age[2]在内存中存储是这样的:5 /0 .
所以age的输出结果是5了。

再看一段程序:
cout<<"姓名 ";
cin.getline(name,10);
cout<<"年龄 ";
cin.ignore();
cin.getline(age,1);  //注意是1
cout<<"姓名 "<<name<<"  年龄 "<<age;

执行结果:
姓名 kiwi
年龄 25
姓名 kiwi    年龄

为什么这里的年龄没有输出呢?其实道理和前面一样的,只不过当cin.ignore()删除了输入流中的2时,输入流中剩下5。但是cin.getline(age,1)只允许在age中存入一个字符,那么不会存入5,只会存入'/0'.所以输出是空的。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值