1092. To Buy or Not to Buy (20)[字符处理]

本文介绍了一道PAT-A级别的编程题目,该题目要求判断商店的珠子能否满足顾客需求。通过使用C++和map数据结构实现了一个简洁高效的解决方案,并成功通过了评测。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1. 原题: https://www.patest.cn/contests/pat-a-practise/1092

2. 思路:

题意:给出你需要的珠子, 商店里售卖的珠子,查看是否包含你需要的。
思路:数据处理题。
比较简单,可以用字符串进行比较处理。
为了简便,我用的map映射。
已AC。

3. 源码:

#include <iostream>
#include <map>
#include<cstring>
using namespace std;
const int s_max = 1000 + 5;//最大数

int main(void)
{
	//freopen("in.txt", "r", stdin);
	char offer[s_max], need[s_max];//分别为提供的和需要的珠子
	scanf("%s%s", offer, need);

	map<char, int> mp;//键值分别是珠子号,数目
	for (int i = 0; offer[i] != '\0'; i++)//进行映射
	{
		if (mp.count(offer[i]) == 0)
			mp[offer[i]] = 0;
		mp[offer[i]]++;
	}

	int flag = 0;
	int missingNum = 0;//缺少数目
	for (int i = 0; need[i] != '\0'; i++)
	{
		if (mp.count(need[i]) > 0)
		{
			mp[need[i]]--;
			if (mp[need[i]] == 0)//删除该键
				mp.erase(need[i]);
		}
		else
		{
			flag = 1;
			missingNum++;
		}
	}

	if (flag == 0)//表示满足要求
	{
		cout << "Yes " << strlen(offer) - strlen(need) << endl;
	}
	else
	{
		cout << "No " << missingNum << endl;
	}

	return 0;
}


基于开源大模型的教学实训智能体软件,帮助教师生成课前备课设计、课后检测问答,提升效率与效果,提供学生全时在线练习与指导,实现教学相长。 智能教学辅助系统 这是一个智能教学辅助系统的前端项目,基于 Vue3+TypeScript 开发,使用 Ant Design Vue 作为 UI 组件库。 功能模块 用户模块 登录/注册功能,支持学生和教师角色 毛玻璃效果的登录界面 教师模块 备课与设计:根据课程大纲自动设计教学内容 考核内容生成:自动生成多样化考核题目及参考答案 学情数据分析:自动化检测学生答案,提供数据分析 学生模块 在线学习助手:结合教学内容解答问题 实时练习评测助手:生成随练题目并纠错 管理模块 用户管理:管理员/教师/学生等用户基本管理 课件资源管理:按学科列表管理教师备课资源 大屏概览:使用统计、效率指数、学习效果等 技术栈 Vue3 TypeScript Pinia 状态管理 Ant Design Vue 组件库 Axios 请求库 ByteMD 编辑器 ECharts 图表库 Monaco 编辑器 双主题支持(专业科技风/暗黑风) 开发指南 # 安装依赖 npm install # 启动开发服务器 npm run dev # 构建生产版本 npm run build 简介 本项目旨在开发一个基于开源大模型的教学实训智能体软件,帮助教师生成课前备课设计、课后检测问答,提升效率与效果,提供学生全时在线练习与指导,实现教学相长。
<think>我们遇到了一个错误:`AttributeError:'AttributeValueList' objecthas noattribute 'lower'`。这个错误发生在尝试对一个属性值(可能是列表)调用`lower()`方法时。在BeautifulSoup中,某些属性(如`class`)返回的是由多个值组成的列表(AttributeValueList),而不是字符串。因此,我们需要确保在检查属性值之前,将其转换为字符串。解决方案:修改宽松匹配部分的代码,将属性值转换为字符串(如果它是列表,则合并为字符串)后再进行小写转换和检查。具体修改位置:在宽松匹配部分,我们有以下代码:if any('email' inattr.lower() forattr inelem.attrs.values()):这里,`elem.attrs.values()`返回的是属性值的列表,每个属性值可能是字符串,也可能是列表(如class属性)。我们需要修改为:将每个属性值转换为字符串(如果是列表,则用空格连接),然后转换为小写,再检查是否包含关键词。修改后的代码:ifany('email'in ''.join(attr).lower() ifisinstance(attr,list)else str(attr).lower() forattr inelem.attrs.values()):但是,注意:`elem.attrs.values()`返回的是每个属性的值,而每个属性的值可能是字符串或列表(如class属性是列表)。所以,我们需要对每个属性值进行处理。但是,上面的代码可能有点复杂,我们可以写一个辅助函数来规范化属性值。辅助函数:defnormalize_attr_value(value):if isinstance(value,list):return' '.join(value).lower()return str(value).lower()然后使用:if any('email' innormalize_attr_value(attr) forattr inelem.attrs.values()):但是,注意:`elem.attrs.values()`中的每个`attr`就是一个属性值(可能是字符串或列表),所以我们需要对每个属性值应用这个函数。然而,我们也可以直接遍历属性名和属性值,因为属性值可能是复杂类型。另一种更清晰的方式是遍历属性项(键值对):forattr_name, attr_value inelem.attrs.items():normalized_value= normalize_attr_value(attr_value)if 'email'in normalized_value:...但是,我们是在`any`函数中使用的,所以可以这样写:if any('email' innormalize_attr_value(attr_value)for attr_value inelem.attrs.values()):现在,我们修改宽松匹配部分的代码。具体修改如下:步骤:1.在宽松匹配部分之前,定义一个辅助函数`normalize_attr_value`。2.在宽松匹配部分,使用这个辅助函数来处理每个属性值。但是,注意:这个错误发生在宽松匹配部分,所以我们只需要修改宽松匹配部分的代码。修改后的宽松匹配代码段: ```python#在测试函数内部(宽松匹配之前)定义辅助函数defnormalize_attr_value(value):"""将属性值规范化为小写字符串,如果是列表则合并"""ifisinstance(value, list):return ''.join(value).lower()returnstr(value).lower() #然后在宽松匹配部分使用ifany('email'in normalize_attr_value(attr_value) forattr_valuein elem.attrs.values()):... ```但是,注意:这个辅助函数应该定义在测试函数内部,因为它是临时使用的。然而,为了避免重复,我们可以将辅助函数放在测试函数外部(作为模块级函数),但为了简单,我们将其放在测试函数内部。完整修改后的宽松匹配部分:```python#宽松匹配if missing_elements:with allure.step("宽松匹配"):#定义辅助函数def normalize_attr_value(value):if isinstance(value,list):return' '.join(value).lower()return str(value).lower()forelement_namein missing_elements[:]:#创建副本用于迭代ifelement_name== "邮箱输入框":#查找任何包含"email"文本的输入框email_inputs= soup.find_all('input', attrs={'type':lambda t: tin ['text','email']})forelem inemail_inputs:#检查元素的属性值中是否包含"email"if any('email' innormalize_attr_value(attr_value)for attr_value inelem.attrs.values()):missing_elements.remove(element_name)logger.info(f"宽松匹配找到{element_name}元素")breakelifelement_name== "确认密码输入框":#查找任何包含"confirm"文本的密码输入框confirm_inputs= soup.find_all('input', attrs={'type':'password'})forelem inconfirm_inputs:ifany('confirm'in normalize_attr_value(attr_value) forattr_valuein elem.attrs.values()):missing_elements.remove(element_name)logger.info(f"宽松匹配找到 {element_name}元素")breakelif element_name =="提交按钮":#查找任何包含注册文本的按钮register_buttons =soup.find_all(['button','input'])for btnin register_buttons:btn_text= btn.get_text().strip().lower()if any(text inbtn_textfor textin ['register','signup','create', '注册']):missing_elements.remove(element_name)logger.info(f"宽松匹配找到 {element_name}元素")break```这样修改后,应该可以避免`AttributeError`。但是,我们还需要注意,在严格匹配部分也可能存在类似问题?严格匹配部分我们使用了`soup.find_all`,然后通过`elem.get(attr_name,'')`获取属性值,这个返回的是字符串或列表吗?在严格匹配部分,我们获取属性值的方式是:attr_value =input_elem.get(attr_name,'').lower()这里,如果获取到的属性值是列表(如class),那么调用`.lower()`就会出错。所以严格匹配部分也需要修改。因此,我们需要在严格匹配部分也使用同样的规范化方法。修改严格匹配部分:在严格匹配部分,我们原来是这样检查的:attr_value =input_elem.get(attr_name,'').lower()ifany(val.lower()in attr_value forval invalues):现在,我们需要规范化属性值,并规范化比较值。修改为:attr_value =input_elem.get(attr_name,'')normalized_attr_value= normalize_attr_value(attr_value)ifany(val.lower()in normalized_attr_value forval invalues):但是,注意:`val`是我们在验证器中定义的字符串,我们将其转换为小写,然后检查是否在规范化后的属性值字符串中(也是小写)。所以,严格匹配部分也需要使用`normalize_attr_value`函数。因此,我们重构一下,将`normalize_attr_value`函数定义在测试函数的开头,然后在严格匹配和宽松匹配部分都使用它。最终修改后的完整测试函数(仅显示修改部分):```pythondeftest_get_register_page(self):"""测试获取账户注册页面"""# ...前面的代码不变...#定义辅助函数(在测试函数内部)def normalize_attr_value(value):if isinstance(value,list):return' '.join(value).lower()return str(value).lower()#增强的表单元素验证with allure.step("验证关键注册表单元素"):# ...定义element_validators不变 ...#检查每个元素for element_name,validator inelement_validators.items():found =Falsematch_details =[]#检查输入类元素if element_name in["邮箱输入框","密码输入框", "确认密码输入框"]:#查找所有输入元素inputs= soup.find_all('input')forinput_elem ininputs:#检查类型input_type =input_elem.get('type', '').lower()if 'types'in validatorand input_type notin validator['types']:continue#检查属性匹配for attr_name,values invalidator.get('attributes', {}).items():attr_value=input_elem.get(attr_name,'')normalized_attr_value =normalize_attr_value(attr_value)#检查每个值是否在属性值中ifany(val.lower()in normalized_attr_value forval invalues):found= Truematch_details.append(f"匹配属性:{attr_name}={attr_value}(规范化后:{normalized_attr_value})")logger.info(f"找到{element_name}元素: {input_elem}")breakiffound:break#检查按钮类元素elif element_name =="提交按钮":#...类似修改,注意按钮的文本匹配不需要改,因为文本是字符串...#在属性匹配部分使用normalize_attr_value#文本匹配部分不变buttons= soup.find_all(['button', 'input'])for btnin buttons:btn_type= btn.get('type','').lower()#检查类型if 'types'in validatorand btn_type notin validator['types']:continue#检查文本匹配if 'text'in validator:btn_text= btn.get_text().strip().lower()if any(text.lower() inbtn_textfor textin validator['text']):found= Truematch_details.append(f"匹配文本:{btn_text}")logger.info(f"找到{element_name}元素: {btn}")break#检查属性匹配ifnot found:for attr_name,values invalidator.get('attributes', {}).items():attr_value= btn.get(attr_name, '')normalized_attr_value= normalize_attr_value(attr_value)if any(val.lower() innormalized_attr_valuefor valin values):found =Truematch_details.append(f"匹配属性: {attr_name}={attr_value}(规范化后:{normalized_attr_value})")logger.info(f"找到{element_name}元素: {btn}")breakiffound:break# ...后面的代码不变...#宽松匹配部分(已经修改过,使用normalize_attr_value)#...如前所示... ```这样修改后,整个测试函数在获取和比较属性值时都会先进行规范化,避免出现属性值为列表而无法调用`.lower()`的问题。注意:在严格匹配部分,我们对按钮的文本匹配没有修改,因为`btn.get_text()`返回的是字符串,可以直接调用`.lower()`。最后,我们还要注意,在宽松匹配部分,对于提交按钮的文本匹配,我们使用的是`btn.get_text().strip().lower()`,这是安全的,因为`get_text()`返回字符串。因此,修改后的测试函数应该可以避免这个错误。由于代码较长,这里仅提供修改后的完整测试函数中变化的部分。如果需要,可以重新生成整个测试函数,但考虑到长度,我们只展示修改的关键部分。如果问题仍然存在,请检查是否还有其他地方直接调用了属性值的`.lower()`方法,并确保所有属性值都通过`normalize_attr_value`函数进行规范化。我们也可以考虑在获取属性值时统一使用`soup`提供的`get`方法,并注意处理多值属性。但是,使用`normalize_attr_value`函数是一个比较通用的解决方案。现在,我们提供修改后的完整测试函数(只显示修改后的部分,但为了清晰,我们给出整个函数,但省略了重复部分,只展示关键修改)。完整修改后的测试函数(带注释):</think>这个错误是由于在宽松匹配部分处理HTML属性时导致的。具体原因是`elem.attrs.values()`返回的某些属性值不是字符串类型(如`class`属性返回的是一个列表),而代码尝试直接在它们上调用`.lower()`方法。 ### 修复后的代码 以下是修复后的完整测试函数,主要修改了宽松匹配部分: ```python def test_get_register_page(self): """测试获取账户注册页面""" logger.info("开始测试 - 获取账户注册页面") # 初始化API api = AccountsAPI() # 执行API请求 with allure.step("发送GET请求获取注册页面"): res = api.get_register_page() logger.info(f"请求URL: {res.request.url}") # 保存HTML响应到文件用于调试 html_path = "register_page.html" with open(html_path, "w", encoding="utf-8") as f: f.write(res.text) allure.attach.file(html_path, "完整HTML响应", allure.attachment_type.HTML) # 记录请求信息到Allure allure.attach(res.request.url, "请求URL", allure.attachment_type.TEXT) allure.attach(res.text[:1000], "响应内容摘要", allure.attachment_type.TEXT) # 验证HTTP状态码 with allure.step("验证HTTP状态码"): assert res.status_code == 200, ( f"HTTP状态码异常,预期200,实际{res.status_code}" ) # 验证响应内容类型 with allure.step("验证响应内容类型"): content_type = res.headers.get("Content-Type", "") logger.info(f"响应Content-Type: {content_type}") assert "text/html" in content_type, ( f"响应内容类型异常,预期包含text/html,实际{content_type}" ) # 使用BeautifulSoup解析HTML with allure.step("解析HTML内容"): soup = BeautifulSoup(res.text, 'html.parser') logger.info("HTML解析完成") # 提取所有表单元素用于分析 form_elements = soup.find_all(['input', 'button', 'select', 'textarea']) allure.attach("\n".join(str(e) for e in form_elements), "所有表单元素", allure.attachment_type.HTML) # 增强的表单元素验证 with allure.step("验证关键注册表单元素"): # 定义关键元素及其验证规则 element_validators = { "邮箱输入框": { "types": ["email"], "attributes": { "name": ["email", "username", "user_email", "user[email]"], "id": ["email", "user_email"], "placeholder": ["Email", "E-mail", "邮箱", "メールアドレス"] }, "required": True }, "密码输入框": { "types": ["password"], "attributes": { "name": ["password", "pass", "user_password", "user[password]"], "id": ["password", "user_password"], "placeholder": ["Password", "Pass", "密码", "パスワード"] }, "required": True }, "确认密码输入框": { "types": ["password"], "attributes": { "name": ["confirm_password", "password_confirmation", "confirmPassword"], "id": ["confirm_password", "password_confirmation"], "placeholder": ["Confirm Password", "Re-enter Password", "确认密码", "パスワード確認"] }, "required": True }, "提交按钮": { "types": ["submit", "button"], "text": ["Register", "Sign Up", "Create Account", "Submit", "注册", "创建账户"], "attributes": { "id": ["submit", "register", "signup"], "class": ["btn-submit", "btn-register", "submit-button"] }, "required": True } } missing_elements = [] found_elements = [] element_details = {} # 检查每个元素 for element_name, validator in element_validators.items(): found = False match_details = [] # 检查输入类元素 if element_name in ["邮箱输入框", "密码输入框", "确认密码输入框"]: # 查找所有输入元素 inputs = soup.find_all('input') for input_elem in inputs: # 检查类型 input_type = input_elem.get('type', '').lower() if 'types' in validator and input_type not in validator['types']: continue # 检查属性匹配 for attr_name, values in validator.get('attributes', {}).items(): attr_value = input_elem.get(attr_name, '') # 处理多值属性(如class) if isinstance(attr_value, list): attr_value = ' '.join(attr_value) attr_value = attr_value.lower() if any(val.lower() in attr_value for val in values): found = True match_details.append(f"匹配属性: {attr_name}={attr_value}") logger.info(f"找到 {element_name} 元素: {input_elem}") break if found: break # 检查按钮类元素 elif element_name == "提交按钮": # 查找提交按钮或包含提交文本的按钮 buttons = soup.find_all(['button', 'input']) for btn in buttons: btn_type = btn.get('type', '').lower() # 检查类型 if 'types' in validator and btn_type not in validator['types']: continue # 检查文本匹配 if 'text' in validator: btn_text = btn.get_text().strip().lower() if any(text.lower() in btn_text for text in validator['text']): found = True match_details.append(f"匹配文本: {btn_text}") logger.info(f"找到 {element_name} 元素: {btn}") break # 检查属性匹配 if not found: for attr_name, values in validator.get('attributes', {}).items(): attr_value = btn.get(attr_name, '') # 处理多值属性 if isinstance(attr_value, list): attr_value = ' '.join(attr_value) attr_value = attr_value.lower() if any(val.lower() in attr_value for val in values): found = True match_details.append(f"匹配属性: {attr_name}={attr_value}") logger.info(f"找到 {element_name} 元素: {btn}") break if found: break if found: found_elements.append(element_name) element_details[element_name] = "\n".join(match_details) elif validator["required"]: missing_elements.append(element_name) logger.warning(f"未找到 {element_name} 元素") # 记录发现和缺失的元素 logger.info(f"找到的关键元素: {', '.join(found_elements)}") if missing_elements: logger.error(f"缺失的关键元素: {', '.join(missing_elements)}") allure.attach('\n'.join(missing_elements), "缺失元素", allure.attachment_type.TEXT) # 在报告中添加详细的元素匹配信息 with allure.step("元素匹配详情"): for element_name, details in element_details.items(): allure.attach(details, f"{element_name}匹配详情", allure.attachment_type.TEXT) # 如果仍然缺失元素,尝试更宽松的匹配 if missing_elements: with allure.step("宽松匹配"): # 定义辅助函数处理属性值 def get_normalized_attrs(element): """获取元素所有属性的规范化值""" normalized = {} for attr, value in element.attrs.items(): # 处理多值属性 if isinstance(value, list): normalized[attr] = ' '.join(value).lower() else: normalized[attr] = str(value).lower() return normalized for element_name in missing_elements[:]: # 创建副本用于迭代 if element_name == "邮箱输入框": # 查找任何包含"email"文本的输入框 email_inputs = soup.find_all('input', attrs={'type': lambda t: t in ['text', 'email']}) for elem in email_inputs: attrs = get_normalized_attrs(elem) if any('email' in val for val in attrs.values()): missing_elements.remove(element_name) logger.info(f"宽松匹配找到 {element_name} 元素") break elif element_name == "确认密码输入框": # 查找任何包含"confirm"文本的密码输入框 confirm_inputs = soup.find_all('input', attrs={'type': 'password'}) for elem in confirm_inputs: attrs = get_normalized_attrs(elem) if any('confirm' in val or 'retype' in val for val in attrs.values()): missing_elements.remove(element_name) logger.info(f"宽松匹配找到 {element_name} 元素") break elif element_name == "提交按钮": # 查找任何包含注册文本的按钮 register_buttons = soup.find_all(['button', 'input']) for btn in register_buttons: btn_text = btn.get_text().strip().lower() if any(text in btn_text for text in ['register', 'sign up', 'create', '注册']): missing_elements.remove(element_name) logger.info(f"宽松匹配找到 {element_name} 元素") break # 如果文本匹配失败,尝试属性匹配 if not missing_elements: continue attrs = get_normalized_attrs(btn) if any('submit' in val or 'register' in val for val in attrs.values()): missing_elements.remove(element_name) logger.info(f"宽松匹配找到 {element_name} 元素") break # 断言所有必需元素都存在 assert len(missing_elements) == 0, ( f"注册页面缺少{len(missing_elements)}个关键表单元素: {', '.join(missing_elements)}\n" "请查看附件中的完整HTML响应进行调试" ) logger.info("测试通过 - 成功获取注册页面") ``` ### 关键修复说明 1. **属性值类型处理**: ```python # 处理多值属性(如class) if isinstance(attr_value, list): attr_value = ' '.join(attr_value) attr_value = attr_value.lower() ``` - 检查属性值是否是列表类型(如`class`属性) - 如果是列表,将其连接为字符串 - 然后转换为小写进行匹配 2. **创建辅助函数处理属性**: ```python def get_normalized_attrs(element): """获取元素所有属性的规范化值""" normalized = {} for attr, value in element.attrs.items(): # 处理多值属性 if isinstance(value, list): normalized[attr] = ' '.join(value).lower() else: normalized[attr] = str(value).lower() return normalized ``` - 统一处理所有属性的规范化 - 确保所有属性值都是字符串类型 - 适用于宽松匹配部分 3. **宽松匹配优化**: ```python # 邮箱输入框的宽松匹配 for elem in email_inputs: attrs = get_normalized_attrs(elem) if any('email' in val for val in attrs.values()): missing_elements.remove(element_name) break ``` - 使用规范化后的属性进行匹配 - 检查任何属性值中是否包含关键词 - 匹配成功后立即跳出循环 4. **确认密码输入框的增强匹配**: ```python # 确认密码输入框的宽松匹配 if any('confirm' in val or 'retype' in val for val in attrs.values()): ``` - 添加更多可能的关键词(如"retype") - 提高匹配的灵活性 ### 错误分析 原始错误发生在以下代码行: ```python if any('email' in attr.lower() for attr in elem.attrs.values()) ``` 问题在于: 1. `elem.attrs.values()`返回的是HTML属性的值 2. 对于`class`属性,BeautifulSoup返回的是字符串列表(如`['btn', 'btn-primary']`) 3. 尝试在列表上调用`.lower()`方法导致`AttributeError` ### 调试建议 如果修复后仍然失败,可以添加以下调试代码: ```python # 在宽松匹配部分添加调试信息 if missing_elements: with allure.step("元素属性调试"): debug_info = [] for element_name in missing_elements: debug_info.append(f"缺失元素: {element_name}") if element_name == "邮箱输入框": elements = soup.find_all('input', attrs={'type': lambda t: t in ['text', 'email']}) elif element_name == "确认密码输入框": elements = soup.find_all('input', attrs={'type': 'password'}) elif element_name == "提交按钮": elements = soup.find_all(['button', 'input']) for i, elem in enumerate(elements[:5]): # 只检查前5个元素 debug_info.append(f"元素 #{i+1}: {elem.name}") for attr, value in elem.attrs.items(): debug_info.append(f" {attr}: {value} ({type(value)})") allure.attach("\n".join(debug_info), "元素属性调试信息", allure.attachment_type.TEXT) ``` 这段代码会显示缺失元素的属性及其类型,帮助进一步诊断问题。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值