IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> C++知识库 -> 【C语言陷阱】00_scanf函数输入含空格时的陷阱 -> 正文阅读

[C++知识库]【C语言陷阱】00_scanf函数输入含空格时的陷阱

前言

本文同时作为【C语言编码练习】的第00节,主要记录遇到的关于scanf函数输入含空格时的陷阱问题。

问题场景:

  • 将一句话的单词进行倒置,标点不倒置。比如 “I like beijing.”,经过处理后变为:“beijing. like I”。
    字符串长度不超过100。
  • 输入描述:
    输入一个仅包含小写字母、空格、‘.’ 的字符串,长度不超过100。
    ‘.’ 只出现在最后一个单词的末尾。
  • 输出描述:
    依次输出倒置之后的字符串,以空格分割。

问题描述

首先,写了问题简化的倒置如下:

#include<stdio.h>
#include<stdlib.h>

int main()
{
    char a[100];
    char *p=a;
    int count=0;
    printf("Please enter a string(<100):\n");
    gets(a);
    scanf("%s",&a);
    for(;*p!=0;p++)
    count++;
    printf("The string in reverse order is:\n");
    for(int i=0;i<count;i++){
        p--;
        printf("%c",*p);   
    }
    printf("\n");
    system("pause");
}

然后按题目要求写时发现这样问题,简化代码如下:

int main()
{
    char a[100];
    char *p=a;
    int count=0;
    printf("Please enter a string(<100):\n");
    scanf("%s",&a);
    for(;*p!='\0';p++)
    count++;
    printf("%d\n",a[3]); 

  • 以上代码输入’abc aabc’,a[3]及以后元素打印均为0.

原因分析:

  • scanf()函数原型:
int scanf(const char * restrict format,...);
  • scanf()遇见空格则会停止扫描。如下(5)说明。

(1)在高版本的 Visual Studio 编译器中,scanf 被认为是不安全的,被弃用,应当使用scanf_s代替 scanf。
(2) 对于字符串数组或字符串指针变量,由于数组名可以转换为数组和指针变量名本身就是地址,因此使用scanf()函数时,不需要在它们前面加上"&“操作符。
(3) scanf函数中没有类似printf的精度控制。
如: scanf(”%5.2f",&a); 是非法的。不能企图用此语句输入小数为2位的实数。
(4) scanf中要求给出变量地址,如给出变量名则会出错
如 scanf(“%d”,a);是非法的,应改为scanf(“%d”,&a);才是合法的。
(5) 在输入多个数值数据时,若格式控制串中没有非格式字符作输入数据之间的间隔,则可用空格,制表符或回车作间隔。
C编译在碰到空格,制表符,回车或非法数据(如对“%d”输入“12A”时,A即为非法数据)时即认为该数据结束。
(6) 在输入字符数据(%c)时,若格式控制串中无非格式字符,则认为所有输入的字符均为有效字符。


解决方案:

如果使用gets这个函数获得标准输入流(键盘)上的字符串的话就不会出现这种问题。

  • 作者使用gets重写如下:
    (本方法后半部分当时出于节省内存的目的,采用了直接输出打印的方式,导致程序可读性变差,若同前半部分一样先倒置在数组中,然后再打印,可提高可读性。在此不在赘述。)
#include<stdio.h>
#include<stdlib.h>

int main()
{
    char a[100],b[100];
    char *p=a;
    int count=0,dig=0,xx;
    
    printf("Please enter a string(<100):\n");
    gets(a);
    for(;*p!='\0';p++)
    count++;//长度
    printf("The string in reverse order is:\n");
    for(int i=0;i<count;i++)
    {
        p--; 
        b[i]=*p;   
    }
    
    while(dig<count)
    {
        for (; dig < count; dig++) 
        {
            int tmp = dig;
            while (dig < count && b[dig] != ' ')
                ++dig;
            xx=dig;
            for(int x=xx-1;(x+1)!=tmp;--x)
            {
                printf("%c",b[x]);
            volatile  int y=y;  
            }
            printf("%c",b[dig]);
            tmp=dig+1;
        }
    }
    printf("\n");
    system("pause");
}

网上答案(使用了库函数):

#include <iostream>
#include <string>
#include <algorithm>
using namespace std;

int main()
{
	string str;
	getline(cin, str);
	reverse(str.begin(), str.end()); // 先完全倒置一遍
	for (size_t i = 0; i < str.size(); ++i) {
		int tmp = i;
		while (i < str.size() && str[i] != ' ') // 注意别越界 查找单词分界
			++i;
		reverse(str.begin() + tmp, str.begin() + i); // 倒置每一个单词
	}
	cout << str << endl;
}
  C++知识库 最新文章
【C++】友元、嵌套类、异常、RTTI、类型转换
通讯录的思路与实现(C语言)
C++PrimerPlus 第七章 函数-C++的编程模块(
Problem C: 算法9-9~9-12:平衡二叉树的基本
MSVC C++ UTF-8编程
C++进阶 多态原理
简单string类c++实现
我的年度总结
【C语言】以深厚地基筑伟岸高楼-基础篇(六
c语言常见错误合集
上一篇文章      下一篇文章      查看所有文章
加:2022-09-13 10:54:41  更:2022-09-13 10:58:04 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年5日历 -2024/5/19 12:11:21-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码