而它等待被提取到变量

大多数有某种用户界面的程序需要处理用户输入。在项目中,你一直在写,你一直在使用std::cin要求用户输入文本输入。因为文本输入是自由格式的(用户可以输入任何东西),所以用户很容易输入不期望的输入。
在编写程序时,应始终考虑用户将如何(无意或以其他方式)滥用程序。一个写得很好的程序会预见用户会如何滥用它,或者是优雅地处理这些情况,或者防止它们发生在第一位(如果可能的话)。一个程序,处理错误的情况下,据说是强大的。
在这节课中,我们来看看具体的办法,用户可以通过标准输入无效的文本输入::CIN,并告诉你一些不同的方式来处理这些情况。
std::cin,缓冲,和提取
为了探讨std::cin和运算符> >可以失败,它首先有助于了解它们是如何工作的一点点。
当我们使用运算符来获取用户输入并将其输入变量时,这称为“提取”。运算符在此上下文中使用,因此称为提取运算符。
当用户输入响应提取操作输入,数据被放置在一个缓冲区::性病在CIN。缓冲区(也称为数据缓冲区)仅仅是一块内存,用来暂时存储数据,而它是从一个地方移动到另一个地方的。在这种情况下,缓冲区被用来保存用户输入,而它等待被提取到变量。

使用提取运算符时,会发生下列过程:

#include <iostream>
 
double getDouble()
{
    std::cout << "Enter a double value: ";
    double x;
    std::cin >> x;
    return x;
}
 
char getOperator()
{
    std::cout << "Enter one of the following: +, -, *, or /: ";
    char op;
    std::cin >> op;
    return op;
}
 
void printResult(double x, char op, double y)
{
    if (op == '+')
        std::cout << x << " + " << y << " is " << x + y << '\n';
    else if (op == '-')
        std::cout << x << " - " << y << " is " << x - y << '\n';
    else if (op == '*')
        std::cout << x << " * " << y << " is " << x * y << '\n';
    else if (op == '/')
        std::cout << x << " / " << y << " is " << x / y << '\n';
}
 
int main()
{
    double x = getDouble();
    char op = getOperator();
    double y = getDouble();
 
    printResult(x, op, y);
 
    return 0;
}

现在我们的程序将按照预期的工作,即使我们输入“5 * 7”的第一个输入-将提取5,其余的字符将被删除从输入缓冲区。由于输入缓冲区是空的,用户将被正确地要求输入下一次提取操作进行!
错误案例3:提取失败
现在考虑下面执行的计算器程序:
输入双值
你不应该惊讶的程序并没有像预期的那样,但它如何失败是有趣的:
输入双值
输入下列内容之一:+,-,*,/或:输入双值:
和程序突然结束。
这看起来与外部输入的情况非常相似,但有点不同。让我们仔细看看。
当用户输入“a”时,该字符被放置在缓冲区中。然后运算符>尝试将“a”改为变量x,这是double型。由于“a”不能转换为双,运算符不能提取。两件事情发生在这一点上:一个是在缓冲区中,左和std::cin进入“故障模式”。
一旦在“故障模式”,未来的输入提取请求将默默失败。因此,在我们的计算器程序,输出提示仍然打印,但任何要求进一步提取被忽略。该程序只运行到结束,然后终止(不打印结果,因为我们从来没有读过一个有效的数学运算)。
幸运的是,我们可以检测提取是否失败并修复它:
### 使用 Excel VBA 实现将提取的文件名复制到剪贴板 为了实现将提取的文件名复制到剪贴板的功能,可以通过调用 Windows API 函数 `GlobalLock` 和 `OpenClipboard` 来操作剪贴板。以下是具体的方法: #### 方法概述 通过创建一个字符串变量来存储文件名,并利用 Windows API 函数将其内容放置在剪贴板上。 ```vba Private Declare PtrSafe Function GlobalUnlock Lib "kernel32" (ByVal hMem As LongPtr) As Long Private Declare PtrSafe Function GlobalLock Lib "kernel32" (ByVal hMem As LongPtr) As LongPtr Private Declare PtrSafe Function GlobalAlloc Lib "kernel32" (ByVal wFlags As Long, ByVal dwBytes As Long) As LongPtr Private Declare PtrSafe Function CloseClipboard Lib "user32" () As Long Private Declare PtrSafe Function OpenClipboard Lib "user32" (ByVal hwnd As Long) As Long Private Declare PtrSafe Function EmptyClipboard Lib "user32" () As Long Private Declare PtrSafe Function lstrcpy Lib "kernel32" (ByVal lpwDest As Any, ByVal lpwSrc As Any) As LongPtr Private Declare PtrSafe Function SetClipboardData Lib "user32" (ByVal wFormat As Long, ByVal hMem As LongPtr) As LongPtr Sub CopyFileNameToClipboard(fileName As String) Dim hGlobalMemory As LongPtr Dim lpGlobalMemory As LongPtr Dim PCopy As Integer ' 打开剪贴板并清空旧数据 If OpenClipboard(0&) = 0 Then Exit Sub Call EmptyClipboard() ' 分配全局内存块用于保存新数据 hGlobalMemory = GlobalAlloc(&H40&, Len(fileName) + 1&) lpGlobalMemory = GlobalLock(hGlobalMemory) ' 复制文件名到分配好的内存空间中 Call lstrcpy(lpGlobalMemory, fileName) Call GlobalUnlock(hGlobalMemory) ' 设置新的剪贴板内容为上述内存地址的数据 PCopy = SetClipboardData(1&, hGlobalMemory) Call CloseClipboard() End Sub ``` 此代码片段展示了如何声明必要的API函数以及编写子程序 `CopyFileNameToClipboard` 来完成这一功能[^1]。 当需要实际应用时,只需调用这个过程并将目标文件名称作为参数传递给它即可。例如,在某个按钮点击事件其他触发条件下执行如下命令: ```vba Call CopyFileNameToClipboard("C:\example.txt") ``` 这会把路径 `"C:\example.txt"` 放入系统的剪贴板里等待进一步处理。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值