PAT乙级 - 1067 试密码 (20分)

"博主分享了在编程中处理忘记密码登录限制的解决方案,从原始代码的不足到学习`scanf("%[^ ]%*c")`技巧的改进过程。通过实例阐述了如何正确读取用户输入并避免数组越界错误。最后强调了少用break语句的学习心得。"
摘要由CSDN通过智能技术生成

**

题目链接

**

题目:1067 试密码 (20分)

当你试图登录某个系统却忘了密码时,系统一般只会允许你尝试有限多次,当超出允许次数时,账号就会被锁死。本题就请你实现这个小功能。

输入格式:

输入在第一行给出一个密码(长度不超过 20 的、不包含空格、Tab、回车的非空字符串)和一个正整数 N(≤ 10),分别是正确的密码和系统允许尝试的次数。随后每行给出一个以回车结束的非空字符串,是用户尝试输入的密码。输入保证至少有一次尝试。当读到一行只有单个 # 字符时,输入结束,并且这一行不是用户的输入。

输出格式:
对用户的每个输入,如果是正确的密码且尝试次数不超过 N,则在一行中输出 Welcome in,并结束程序;如果是错误的,则在一行中按格式输出 Wrong password: 用户输入的错误密码;当错误尝试达到 N 次时,再输出一行 Account locked,并结束程序。

输入样例 1:
Correct%pw 3
correct%pw
Correct@PW
whatisthepassword!
Correct%pw

输出样例 1:
Wrong password: correct%pw
Wrong password: Correct@PW
Wrong password: whatisthepassword!
Account locked

输入样例 2:
cool@gplt 3
coolman@gplt
coollady@gplt
cool@gplt
try again

输出样例 2:
Wrong password: coolman@gplt
Wrong password: coollady@gplt
Welcome in

思路:这个题目并不是难,直接输入,然后比较密码的区别.

代码:

#include <iostream>
using namespace std;


int main()
{
	string a[15];
 	string s, x;
	int n, i, j, len1, len2, ok, ans = 0, flag = 1, cnt = 0;
	cin >> s >> n;
	len1 = s.size();

	while (cin >> x, x != "#" && flag)
	{
		a[cnt++] = x;
	}

	for (i = 0; flag && i < cnt; i++)
	{
		ok = 1;
		len2 = a[i].size();
		if (len1 != len2)
		{
			ok = 0;
			cout << "Wrong password: " << a[i] << endl;
			ans++;
		}

		for (j = 0; ok && j < len1; j++)
		{
			if (s[j] != a[i][j])
			{
				ok = 0;
				cout << "Wrong password: " << a[i] << endl;
				ans++;
			}
		}

		if (ok)
		{
			cout << "Welcome in" << endl;
			flag = 0;
		}
		else if (ans == n)
		{
			cout << "Account locked" << endl;
			flag = 0;
		}
	}
	return 0;
}

在这里插入图片描述
此时第二个测试点和最后一个测试点错误,且第五个错误是数组越界的问题,题目的N是小于10的,所以我刚开始判断的时候就以为只输入10个密码,但是N的实际意思是系统允许尝试的次数,意识是最多只能检测我输入密码的前10个,并不是密码只输入10个,当你把a数组范围调大一点的时候,就是答案错误了。所以我在仔细看了一下题目发现这一句话“随后每行给出一个以回车结束的非空字符串”,然后又百度了一下,查到了这个知识点:
*scanf("%[^\n]%*c",str)表示读入一行字符串。
表示"非",[\n]表示读入换行字符就结束读入。
表示该输入项读入后不赋予任何变量,即scanf("%[^\n]%c")表示跳过一行字符串。
所以我又写了一个版本,代码如下:

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

char a[25],b[10000];

int main()
{
	bool flag = true;
	int sum = 0, n;
    cin >> a >> n;
    
    while(flag)
    {
        getchar();
		scanf("%[^\n]",b);
        if(b[0] == '#' && b[1] == '\0')
        {
        	flag = flag;
		}
        else
        {
        	sum++;
        	if(strcmp(a,b) == 0)
      	 	{
      	 		cout << "Welcome in" << endl;
           		flag = 0;
      		}
     	  	else
        	{
        		cout << "Wrong password: " << b << endl;
            	if(sum == n)
            	{
            		cout << "Account locked" << endl;
                	flag = 0;
           	 	}
        	}
		}
    }
    return 0;
}

在这里插入图片描述
但是还是有问题,第二个测试点运行超时。思考了很久没清楚是什么问题,就百度了一下这个题目然后找到了别人的只是我写的flag = 0 写的是break(break可以直接退出,速度确实快于逻辑变量的修改,但是我上学的老师叫我们不要使用break,速度确实会快,但是会让代码的逻辑很糟糕,continue还有goto一样,好用是好用,但是会让代码很难理解,建议少用,甚至不用)

总结:1.学习了scanf("%[^\n]%*c",str)的使用
2.break能提速,但是建议少用!!!

第一次写博客,写的比较随意,希望大家多多支持啊,谢谢!!

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值