template 分类: templates ...

本文介绍了一种使用C++模板实现的通用读写函数,适用于多种数据类型。该方法利用模板特性,能够高效地从输入流中读取数据或将数据输出到流中,对于处理大量数值数据尤其有用。
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cmath>
#include <ctime>
#include <string>
#include <map>
#include <vector>
#include <stack>
#include <queue>
#include <utility>
#include <iostream>
#include <algorithm>

template<class Num>void read(Num &x)
{
    char c; int flag = 1;
    while((c = getchar()) < '0' || c > '9')
        if(c == '-') flag *= -1;
    x = c - '0';
    while((c = getchar()) >= '0' && c <= '9')
        x = (x<<3) + (x<<1) + (c-'0');
    x *= flag;
    return;
}
template<class Num>void write(Num x)
{
    if(x < 0) putchar('-'), x = -x;
    static char s[20];int sl = 0;
    while(x) s[sl++] = x%10 + '0',x /= 10;
    if(!sl) {putchar('0');return;}
    while(sl) putchar(s[--sl]);
}

版权声明:本文为博主原创文章,未经博主允许不得转载。

转载于:https://www.cnblogs.com/dashgua/p/4722954.html

from appium import webdriver from appium.options.android import UiAutomator2Options from selenium.webdriver.support.ui import WebDriverWait from selenium.webdriver.support import expected_conditions as EC from selenium.common.exceptions import TimeoutException, NoSuchElementException, ElementNotInteractableException import time # ==================== 目标应用配置 ==================== TARGET_PACKAGE = "com.brother.ptouch.iprintandlabel" TARGET_ACTIVITY = ".module.home.home.HomeActivity" # 主页 Activity MAX_RESTORE_ATTEMPTS = 2 MAX_HISTORY_REPEAT = 3 # ==================== 配置 Appium Options ==================== def create_driver(): options = UiAutomator2Options() options.set_capability("platformName", "Android") options.set_capability("deviceName", "emulator-5554") options.set_capability("automationName", "UiAutomator2") options.set_capability("noReset", True) options.set_capability("fullReset", False) options.set_capability("autoGrantPermissions", True) options.set_capability("newCommandTimeout", 600) options.set_capability("appPackage", TARGET_PACKAGE) options.set_capability("appActivity", TARGET_ACTIVITY) driver = webdriver.Remote('http://localhost:4723', options=options) return driver class AndroidAppExplorer: def __init__(self, driver): self.driver = driver self.wait = WebDriverWait(driver, 10) self.clicked_identifiers = set() self.recovery_history = [] self.restore_attempt_count = 0 def get_current_state(self): try: current_package = self.driver.current_package current_activity = self.driver.current_activity return current_package, current_activity except: return None, None def is_in_target_app(self): pkg, _ = self.get_current_state() return pkg == TARGET_PACKAGE def wait_for_page_load(self, timeout=10): """等待页面加载完成,可通过是否存在关键 UI 元素判断""" # print(f"⏳ 等待页面加载最多 {timeout}s...") try: # 等待任意一个可见的 ViewGroup 或 FrameLayout(代表页面结构已出现) WebDriverWait(self.driver, timeout).until( EC.presence_of_element_located(( 'xpath', '//android.view.ViewGroup[@displayed="true"] | ' '//android.widget.FrameLayout[@displayed="true"]' )) ) time.sleep(1) # 额外缓冲 # print("✅ 页面加载完成") except Exception as e: print(f"⚠️ 页面等待超时或出错: {e}") def ensure_in_target_app(self): current_pkg, current_act = self.get_current_state() if not self.is_in_target_app(): print(f"⚠️ 当前不在目标应用 ({current_pkg}/{current_act}),正在尝试恢复...") current_key = (current_pkg, current_act) recent_entries = self.recovery_history[-10:] if recent_entries.count(current_key) >= MAX_HISTORY_REPEAT: print(f"🛑 已多次回到 {current_key},疑似陷入循环,停止恢复。") return False self.recovery_history.append(current_key) # 方法1:back 返回 if self.restore_attempt_count < MAX_RESTORE_ATTEMPTS: try: self.driver.back() time.sleep(1.5) if self.is_in_target_app(): print("✅ 通过 back 成功返回目标 App") self.restore_attempt_count = 0 self.wait_for_page_load(10) # ✅ 关键:等待页面加载 return True except: pass # 方法2:activate_app if self.restore_attempt_count < MAX_RESTORE_ATTEMPTS: try: self.driver.activate_app(TARGET_PACKAGE) print("🔁 正在通过 activate_app 恢复...") time.sleep(2) self.wait_for_page_load(10) if self.is_in_target_app(): print("✅ 成功激活目标 App") self.restore_attempt_count = 0 return True except Exception as e: print(f"❌ activate_app 失败: {e}") # 方法3:冷重启 if self.restore_attempt_count >= MAX_RESTORE_ATTEMPTS: try: print("💀 执行冷重启...") self.driver.terminate_app(TARGET_PACKAGE) time.sleep(2) self.driver.activate_app(TARGET_PACKAGE) time.sleep(5) self.wait_for_page_load(10) if self.is_in_target_app(): print("✅ 冷重启成功") self.restore_attempt_count = 0 return True except Exception as e: print(f"❌ 冷重启失败: {e}") self.restore_attempt_count += 1 if self.restore_attempt_count > 5: print("🛑 恢复尝试过多,终止运行") return False return True else: self.recovery_history.append((current_pkg, current_act)) self.wait_for_page_load(1) # 每次正常进入也稍等一下 return True def get_element_identifier(self, element): try: attrs = [ element.get_attribute("resource-id") or "", element.get_attribute("text") or "", element.get_attribute("content-desc") or "", element.tag_name or "" ] return "/".join([a for a in attrs if a.strip()]) except: return "unknown_element" def find_clickable_elements(self): xpath = """ //*[ (@clickable='true' or @focusable='true') and @displayed='true' and @enabled='true' ] """ try: elements = self.driver.find_elements('xpath', xpath) # 过滤掉不可见的 return [e for e in elements if e.is_displayed()] except Exception as e: print(f"❌ 查找元素失败: {e}") return [] def classify_elements(self, elements): bottom_nav_container = "com.brother.ptouch.iprintandlabel:id/bottomNavigationView" nav_ids = [ "com.brother.ptouch.iprintandlabel:id/navigation_my_label", "com.brother.ptouch.iprintandlabel:id/navigation_setting", "com.brother.ptouch.iprintandlabel:id/navigation_buy" ] nav_elements = [] non_nav_elements = [] for elem in elements: try: res_id = elem.get_attribute("resource-id") or "" content_desc = elem.get_attribute("content-desc") or "" text = elem.get_attribute("text") or "" if (res_id == bottom_nav_container or res_id in nav_ids or content_desc in ["My Labels", "Settings", "Shop"]): nav_elements.append(elem) else: non_nav_elements.append(elem) except Exception as e: print(f"⚠️ 分类元素时异常: {e}") continue return nav_elements, non_nav_elements def handle_alert_popup(self): alert_xpath = "//*[contains(@text, 'OK') or contains(@text, '允许') or contains(@text, 'Allow')]" try: button = self.driver.find_element('xpath', alert_xpath) if button.is_displayed(): button.click() print("✅ 自动处理了弹窗") time.sleep(1) except: pass def handle_input_field(self, input_elem): hint = input_elem.get_attribute("hint") or "" text = input_elem.get_attribute("text") or "" print(f"\n🔍 发现输入框") if hint: print(f" 提示: '{hint}'") if text: print(f" 当前文本: '{text}'") print("请在设备上手动输入内容(3秒内完成)...") time.sleep(3) entered_value = (input_elem.get_attribute("text") or input_elem.get_attribute("value") or "") print(f"📝 用户在输入框中输入的内容为: '{entered_value}'") def click_element_safely(self, element): try: identifier = self.get_element_identifier(element) if identifier in self.clicked_identifiers: #not identifier or return False try: self.driver.execute_script("arguments[0].scrollIntoView(true);", element) except: pass time.sleep(0.5) element.click() print(f"🟢 点击成功: {identifier}") self.clicked_identifiers.add(identifier) time.sleep(1.5) return True except Exception as e: print(f"🔴 点击失败 {self.get_element_identifier(element)}: {str(e)}") return False def explore_page(self): print("\n🔄 开始探索当前页面...") while True: if not self.ensure_in_target_app(): print("❌ 无法恢复至目标应用,退出。") break self.handle_alert_popup() elements = self.find_clickable_elements() if not elements: print("📭 当前页面无可点击元素。") try: self.driver.back() print("🔙 返回上一页...") time.sleep(2) continue except: break nav_elements, non_nav_elements = self.classify_elements(elements) print(f"📌 导航栏元素数量: {len(nav_elements)}, 非导航栏元素数量: {len(non_nav_elements)}") # === 第一阶段:优先点击导航栏元素 === navigated = False for elem in nav_elements: try: tag_name = elem.tag_name or "" if "edit" in tag_name.lower() or "input" in tag_name.lower(): self.handle_input_field(elem) continue except: pass if self.click_element_safely(elem): navigated = True break if navigated: continue # === 第二阶段:点击非导航栏元素 === any_clicked = False for elem in non_nav_elements: try: tag_name = elem.tag_name or "" if any(keyword in (tag_name.lower()) for keyword in ["edit", "input", "text"]): self.handle_input_field(elem) continue except: pass if self.click_element_safely(elem): any_clicked = True break if not any_clicked: print("✅ 当前页面所有可点击元素已处理完毕。") try: self.driver.back() print("🔙 返回上一页继续探索...") time.sleep(2) except: print("🔚 无法返回,探索结束。") break time.sleep(1) def run(self): print("🚀 启动 Android 应用探索器...") try: self.explore_page() except KeyboardInterrupt: print("\n👋 用户中断执行。") except Exception as e: print(f"💥 执行过程中发生错误: {type(e).__name__}: {e}") finally: print("🔚 自动化结束。") # =============== 主程序入口 =============== if __name__ == "__main__": driver = create_driver() explorer = AndroidAppExplorer(driver) try: explorer.run() finally: driver.quit() 为什么在运行过程有看到输入框,却没有出发输入框处理? C:\own\app\python_code\.venv\Scripts\python.exe C:\own\app\python_code\work\IBL_click_all\click_all.py 🚀 启动 Android 应用探索器... 🔄 开始探索当前页面... 📌 导航栏元素数量: 0, 非导航栏元素数量: 7 🟢 点击成功: null/Navigate up/Navigate up 📌 导航栏元素数量: 3, 非导航栏元素数量: 6 🟢 点击成功: com.brother.ptouch.iprintandlabel:id/navigation_my_label/My Labels/My Labels 📌 导航栏元素数量: 3, 非导航栏元素数量: 3 🟢 点击成功: com.brother.ptouch.iprintandlabel:id/navigation_setting/Settings/Settings 📌 导航栏元素数量: 3, 非导航栏元素数量: 6 🟢 点击成功: com.brother.ptouch.iprintandlabel:id/navigation_buy/Shop/Shop ⚠️ 当前不在目标应用 (com.android.chrome/org.chromium.chrome.browser.firstrun.FirstRunActivity),正在尝试恢复... ✅ 通过 back 成功返回目标 App 📌 导航栏元素数量: 3, 非导航栏元素数量: 6 🟢 点击成功: null/null 📌 导航栏元素数量: 3, 非导航栏元素数量: 6 🟢 点击成功: com.brother.ptouch.iprintandlabel:id/setting_printer/null 📌 导航栏元素数量: 0, 非导航栏元素数量: 5 🟢 点击成功: com.brother.ptouch.iprintandlabel:id/wifi_printer_recycler_view/null 📌 导航栏元素数量: 0, 非导航栏元素数量: 5 ✅ 当前页面所有可点击元素已处理完毕。 🔙 返回上一页继续探索... 📌 导航栏元素数量: 3, 非导航栏元素数量: 6 🟢 点击成功: com.brother.ptouch.iprintandlabel:id/setting_unit/null ✅ 自动处理了弹窗 📌 导航栏元素数量: 3, 非导航栏元素数量: 6 🟢 点击成功: com.brother.ptouch.iprintandlabel:id/setting_support/Support/null ⚠️ 当前不在目标应用 (com.android.chrome/org.chromium.chrome.browser.firstrun.FirstRunActivity),正在尝试恢复... ✅ 通过 back 成功返回目标 App 📌 导航栏元素数量: 3, 非导航栏元素数量: 6 🟢 点击成功: com.brother.ptouch.iprintandlabel:id/setting_information/Information/null 📌 导航栏元素数量: 3, 非导航栏元素数量: 13 🟢 点击成功: com.brother.ptouch.iprintandlabel:id/info_list/null 📌 导航栏元素数量: 3, 非导航栏元素数量: 17 🟢 点击成功: com.brother.ptouch.iprintandlabel:id/send_info_check/Send Information/null 📌 导航栏元素数量: 3, 非导航栏元素数量: 17 🟢 点击成功: com.brother.ptouch.iprintandlabel:id/privacy_policy_text_view/Privacy Policy/null 📌 导航栏元素数量: 3, 非导航栏元素数量: 21 🟢 点击成功: com.brother.ptouch.iprintandlabel:id/privacy_policy_text2/When you use the SOFTWARE, information from the Brother Machine and the devices connected to the Brother Machine (“Device”), including but not limited to, product model, serial number, locale ID (regional information), OS type of your installation, firmware, use of each function of the SOFTWARE, may be recorded in our server. Additionally, printing information such as printing date, quantity, the types and sizes of paper, and the types of files, etc. (collectively, “Device Data”) may be recorded in our server. Device Data (except for the serial number) cannot be used in itself or in combination with any other information we may have to identify you as a person. We reserve the right to use such Device Data solely for the improvement of the SOFTWARE or any other products/services of Brother, our marketing/research activities without identifying you as a person, product planning or any other related activities for our customer’s benefits (collectively “Purposes”). We will not use your Device Data other than for the Purposes without your prior consent. We may disclose your Device Data to third parties in an anonymous format solely for achieving the Purposes, and always by obliging such third parties to control such data as confidential. Device Data includes the serial number of your Brother Machine. The serial number can be associated with the data which you might register to our sales company’s product registration website. However, we will not use the serial number to identify you or other than for the Purposes. Serial number may be stored in Server located in countries without an adequate level of protection for personal data compared to that in your country, but we will control the serial number in strict accordance with “Brother’s Statement on Device Data Worldwide” which is available at Brother’s Website <https://web.global.brother/aa/privacy.html> . /null 📌 导航栏元素数量: 3, 非导航栏元素数量: 21 🟢 点击成功: com.brother.ptouch.iprintandlabel:id/navigation_layout/Create/Create 📌 导航栏元素数量: 3, 非导航栏元素数量: 6 🟢 点击成功: com.brother.ptouch.iprintandlabel:id/tabLayout/null 📌 导航栏元素数量: 3, 非导航栏元素数量: 6 🟢 点击成功: null/Templates/Templates 📌 导航栏元素数量: 3, 非导航栏元素数量: 6 🟢 点击成功: com.brother.ptouch.iprintandlabel:id/download_template_button/DOWNLOAD TEMPLATES/null 📌 导航栏元素数量: 3, 非导航栏元素数量: 5 🟢 点击成功: com.brother.ptouch.iprintandlabel:id/actionButtonNewLabel/NEW LABEL/null 📌 导航栏元素数量: 0, 非导航栏元素数量: 7 🟢 点击成功: com.brother.ptouch.iprintandlabel:id/edit_save/Save/null 📌 导航栏元素数量: 0, 非导航栏元素数量: 4 🟢 点击成功: com.brother.ptouch.iprintandlabel:id/edit_save_label_edit/null 📌 导航栏元素数量: 0, 非导航栏元素数量: 4 🟢 点击成功: com.brother.ptouch.iprintandlabel:id/buttonPanel/null 📌 导航栏元素数量: 0, 非导航栏元素数量: 7 🟢 点击成功: com.brother.ptouch.iprintandlabel:id/edit_print/Print/null 📌 导航栏元素数量: 0, 非导航栏元素数量: 9 🟢 点击成功: com.brother.ptouch.iprintandlabel:id/printer_option_printer/PRINT/null 📌 导航栏元素数量: 0, 非导航栏元素数量: 4 🟢 点击成功: com.brother.ptouch.iprintandlabel:id/option_select_print_lay/null 📌 导航栏元素数量: 0, 非导航栏元素数量: 5 ✅ 当前页面所有可点击元素已处理完毕。 🔙 返回上一页继续探索... 📌 导航栏元素数量: 0, 非导航栏元素数量: 9 🟢 点击成功: com.brother.ptouch.iprintandlabel:id/option_print_lay/null 📌 导航栏元素数量: 0, 非导航栏元素数量: 5 ✅ 当前页面所有可点击元素已处理完毕。 🔙 返回上一页继续探索... 📌 导航栏元素数量: 0, 非导航栏元素数量: 9 🟢 点击成功: com.brother.ptouch.iprintandlabel:id/option_resolution_options/null 📌 导航栏元素数量: 0, 非导航栏元素数量: 3 🟢 点击成功: android:id/text1/Normal/null 📌 导航栏元素数量: 0, 非导航栏元素数量: 9 🟢 点击成功: com.brother.ptouch.iprintandlabel:id/option_down/null 📌 导航栏元素数量: 0, 非导航栏元素数量: 9 🟢 点击成功: com.brother.ptouch.iprintandlabel:id/option_up/null 📌 导航栏元素数量: 0, 非导航栏元素数量: 9 🟢 点击成功: com.brother.ptouch.iprintandlabel:id/option_cut_expand/null 📌 导航栏元素数量: 0, 非导航栏元素数量: 17 🟢 点击成功: com.brother.ptouch.iprintandlabel:id/auto_cut_switch_lay/null 📌 导航栏元素数量: 0, 非导航栏元素数量: 17 🟢 点击成功: com.brother.ptouch.iprintandlabel:id/auto_cut_swh/null 📌 导航栏元素数量: 0, 非导航栏元素数量: 17 🟢 点击成功: com.brother.ptouch.iprintandlabel:id/half_cut_switch_lay/null 📌 导航栏元素数量: 0, 非导航栏元素数量: 17 🟢 点击成功: com.brother.ptouch.iprintandlabel:id/half_cut_swh/null 📌 导航栏元素数量: 0, 非导航栏元素数量: 17 🟢 点击成功: com.brother.ptouch.iprintandlabel:id/chain_print_switch_lay/null 📌 导航栏元素数量: 0, 非导航栏元素数量: 17 🟢 点击成功: com.brother.ptouch.iprintandlabel:id/chain_print_swh/null 📌 导航栏元素数量: 0, 非导航栏元素数量: 17 🟢 点击成功: com.brother.ptouch.iprintandlabel:id/special_tape_switch_lay/null 📌 导航栏元素数量: 0, 非导航栏元素数量: 14 🟢 点击成功: com.brother.ptouch.iprintandlabel:id/special_tape_swh/null 📌 导航栏元素数量: 0, 非导航栏元素数量: 17 ✅ 当前页面所有可点击元素已处理完毕。 🔙 返回上一页继续探索... 📌 导航栏元素数量: 0, 非导航栏元素数量: 7 🟢 点击成功: com.brother.ptouch.iprintandlabel:id/add_btn/null 📌 导航栏元素数量: 0, 非导航栏元素数量: 10 🟢 点击成功: com.brother.ptouch.iprintandlabel:id/touch_outside/null 📌 导航栏元素数量: 0, 非导航栏元素数量: 10 🟢 点击成功: com.brother.ptouch.iprintandlabel:id/edit_bottom_sheet_lv/null ⚠️ 当前不在目标应用 (com.google.android.permissioncontroller/com.android.permissioncontroller.permission.ui.GrantPermissionsActivity),正在尝试恢复... ✅ 通过 back 成功返回目标 App 📌 导航栏元素数量: 0, 非导航栏元素数量: 7 🟢 点击成功: com.brother.ptouch.iprintandlabel:id/text_paper/1.4"/null ✅ 自动处理了弹窗 📌 导航栏元素数量: 0, 非导航栏元素数量: 7 🟢 点击成功: com.brother.ptouch.iprintandlabel:id/text_scale/100%/null 📌 导航栏元素数量: 0, 非导航栏元素数量: 7 ✅ 当前页面所有可点击元素已处理完毕。 🔙 返回上一页继续探索... 📌 导航栏元素数量: 3, 非导航栏元素数量: 6 ✅ 当前页面所有可点击元素已处理完毕。 🔙 返回上一页继续探索... 📌 导航栏元素数量: 3, 非导航栏元素数量: 6 ✅ 当前页面所有可点击元素已处理完毕。 🔙 返回上一页继续探索... 📌 导航栏元素数量: 3, 非导航栏元素数量: 6 ✅ 当前页面所有可点击元素已处理完毕。 🔙 返回上一页继续探索... 📌 导航栏元素数量: 3, 非导航栏元素数量: 6 ✅ 当前页面所有可点击元素已处理完毕。 🔙 返回上一页继续探索... ⚠️ 当前不在目标应用 (com.google.android.apps.nexuslauncher/.NexusLauncherActivity),正在尝试恢复... 🔁 正在通过 activate_app 恢复... ✅ 成功激活目标 App 📌 导航栏元素数量: 3, 非导航栏元素数量: 6 ✅ 当前页面所有可点击元素已处理完毕。 🔙 返回上一页继续探索... ⚠️ 当前不在目标应用 (com.google.android.apps.nexuslauncher/.NexusLauncherActivity),正在尝试恢复... 🔁 正在通过 activate_app 恢复... ✅ 成功激活目标 App 📌 导航栏元素数量: 3, 非导航栏元素数量: 6 ✅ 当前页面所有可点击元素已处理完毕。 🔙 返回上一页继续探索... ⚠️ 当前不在目标应用 (com.google.android.apps.nexuslauncher/.NexusLauncherActivity),正在尝试恢复... 🔁 正在通过 activate_app 恢复... ✅ 成功激活目标 App 📌 导航栏元素数量: 3, 非导航栏元素数量: 6 ✅ 当前页面所有可点击元素已处理完毕。 🔙 返回上一页继续探索... ⚠️ 当前不在目标应用 (com.google.android.apps.nexuslauncher/.NexusLauncherActivity),正在尝试恢复... 🛑 已多次回到 ('com.google.android.apps.nexuslauncher', '.NexusLauncherActivity'),疑似陷入循环,停止恢复。 ❌ 无法恢复至目标应用,退出。 🔚 自动化结束。 Process finished with exit code 0
10-17
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符  | 博主筛选后可见
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值