深入scanf

作为一个初学者,只知道使用scanf的时候要用取地址符,但是,其中还有许多问题。

1.使用scanf的时候可以不用取地址符&吗?

单个字符、整数、小数、对应的格式控制符分别是 %c、%d、%f。

此时都需要用取地址符。

那么字符串呢?假设在我们不想用gets()。

此时定义一个字符串char url[30];

scanf("%s", url);

此时没有用取地址符,那么可不可以用取地址符呢?

scanf() 读取数据时需要的是数据的地址,整数、小数、单个字符都要加&取地址符,这很容易理解;

但是对于此处的 url 字符串,我们并没有加 &,这是因为,字符串的名字会自动转换为字符串的地址,所以不用再多此一举加 & 了。

当然,你也可以加上,这样虽然不会导致错误,但是编译器会产生警告。

2.缓冲区的scanf

下面用\r表示回车。

int a, b;
    scanf("%d", &a);
    scanf("%d", &b);
    printf("a=%d, b=%d\n", a, b);

输入1\r2\r,此时正常输出,那么看下面这个。

int a = 1, b = 2;
    scanf("a=%d", &a);
    scanf("b=%d", &b);
    printf("a=%d, b=%d\n", a, b);

输入a=1\r,此时,按下回车键,只有第一个 scanf() 成功读取了数据,第二个 scanf() 没有给予我们执行的机会,程序直接运行。

原因来自第一个 scanf() 执行完后,将 1 赋值给了 a,缓冲区中只剩下一个换行符\n;到了第二个 scanf(),发现缓冲区中有内容,但是又不符合控制字符串的格式,于是尝试忽略这个空白符。

究其根本为当控制字符串不是以格式控制符 %d、%c、%f 等开头时,空白符就不能忽略了,它会参与匹配过程,本例中第二个 scanf() 的开头并不是格式控制符,而是以b字符,所以不会忽略换行符。

如果我们换一种输入方式呢?

输入a=1 b=2\r

会发现结果和上面一致,第二个 scanf() 读取再次失败。

原因是开头的空格不能忽略,因此又和控制字符串不匹配,所以只能读取失败了

此时输入a=1b=2\r

不要让两份数据之间有空白符,会得到我们想要的结果。

最后我们得出结论:只有当控制字符串以格式控制符开头时,才会忽略换行符。

3.使用 scanf() 清空缓冲区

scanf("%*[^\n]"); scanf("%*c");

第一个 scanf() 将逐个读取缓冲区中\n之前的其它字符,% 后面的 * 表示将读取的这些字符丢弃,遇到\n字符时便停止读取。

此时,缓冲区中尚有一个\n遗留,第二个 scanf() 再将这个\n读取并丢弃,这里的星号和第一个 scanf() 的星号作用相同。

由于所有从键盘的输入都是以回车结束的,而回车会产生一个\n字符,所以将\n连同它之前的字符全部读取并丢弃之后,也就相当于清除了输入缓冲区。

int a = 1, b = 2;
   
    scanf("a=%d", &a);
    scanf("%*[^\n]"); scanf("%*c"); //在下次读取前清空缓冲区
    scanf("b=%d", &b);
    printf("a=%d, b=%d\n", a, b);

输入a=100\rb=200\r
输出a=100, b=200。

输入a=100b=200\rb=300\r
输出a=100, b=300。

此篇文章来自大一再学C时通过C语言中文网对scanf的深入。

4.用scanf如何代替gets

%s 控制符会匹配除空白符以外的所有字符,所以无法将多个单词存放到一个字符串中,因为单词之间就是以空格为分隔的,%s 遇到空格就读取结束了。

scanf存在一种匹配方式,[]包围起来的是需要读取的字符集合。

再使用连接符,scanf() 支持使用连字符-来表示一个范围内的字符。

%[a-z]表示读取 abc...xyz 范围内的字符,也即小写字母;

%[A-Z]表示读取 ABC...XYZ 范围内的字符,也即大写字母;

%[0-9]表示读取 012...789 范围内的字符,也即十进制数字。

%[a-zA-Z0-9]表示读取所有的英文字母和十进制数字;

int main(){
    char str[30];
    scanf("%[a-zA-Z0-9]", str);
    printf("%s\n", str);

    return 0;
}

此时就完美替代了gets()。

此篇文章来自大一再学C时通过C语言中文网对scanf的深入。

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值