博途1500PLC字符串包含判断:FOR+MID滑动窗口实现详解

用博途1500PLC判断源字符串中是否含有子字符串,这个需求听起来简单,我第一次在现场做的时候也以为一条指令就完事了。那是条包装线的扫码工位,读码器通过Profinet把条码送进PLC,我需要在ABC240315001XYZ这样的字符串里判断有没有2403这个月份编号,有的话走甲通道,没有走乙通道。当时的直觉是用FIND函数处理,后来做标准化模板时才发现,很多人真正想搞清楚的是FOR+MID怎么做,因为在字符长度不定、大小写不固定、还要找多个位置的场景里,用基础指令组合往往是更通用的底层方案。这篇文章就把FOR+MID函数的实现原理、完整代码、边界坑一次讲完,适合刚开始玩1500PLC的朋友,也适合准备把字符串处理逻辑封装进标准库的工程师参考。

1. 为什么放着现成的FIND不用,偏要写FOR+MID循环

1.1 现场需求复盘:一个扫码判断的典型场景

先还原一下我在现场遇到的真实需求。读码器读取的条码不是固定格式,项目前期供应商给的样例是ABC240315001XYZ,后来实际生产时条码前面多了一位工厂代码,变成XABC240315001XYZ。这就意味着,生产日期字段2403不在固定位置,你要是用LEFT取前几位,取出来的东西就完全不对;用RIGHT从尾部取,也会因为流水号位数变化而错位。这种情况下,唯一的办法就是"在整串字符串里搜索",判断源字符串里有没有特定的连续字符片段。

很多类似场景都有这个特征:目标子串一定存在或一定不存在,但你不知道它从第几个字符开始。除了扫码,常见的还有HMI输入校验——操作员录入一长串工艺参数,必须先判断字符串中是否包含RUN才允许启动;再有就是报文解析,从通信数据里找出某个关键字再截取后续内容。这类问题的共同点是,包含判断只是第一步,后面往往还有更多处理。如果第一步就用一个封装好的指令带过去,后续扩展时反而被绑住。

1.2 FIND函数能做90%的事,为何还是要学FOR+MID

必须承认,TIA Portal里确实提供了现成指令FIND,用起来基本是一行搞定:

#pos := FIND(IN := #sourceStr, L := #targetStr); IF #pos > 0 THEN // 找到了 END_IF;

功能上,FIND已经能完成"判断是否包含"这件事。那我为什么还建议你把FOR+MID这套自己写一遍?关键在于,工程上的需求往往会从"是否包含"升级。

FIND只能返回第一个匹配位置。如果条码里同一个字段出现多次,或者你需要知道所有出现的位置,FIND就无解。再比如,你希望从源字符串第5个字符之后开始搜索,跳过固定前缀,FIND也没有提供起点参数。还有大小写不敏感的场景,FIND直接比较依然敏感,你还是得自己处理字符串变换。

FOR+MID的价值不是替代FIND,而是让你手里有一份完全可控的查找逻辑。一旦需求变成"找第二个""忽略大小写""从第N位找",你改的是自己的循环,而不是去查库函数支持哪些参数。我在封装标准库的时候,倾向把这类基础能力用底层逻辑自己实现,因为不同版本、不同固件对FIND等字符串指令的行为细节有差异,自己写一套反而更可控。

1.3 这个需求适合哪些人参考

如果你是刚开始接触1500PLC、正在学SCL语言,这篇文章帮你把STRING类型、LEN、MID、FOR循环串起来,是一个很好的综合练习。如果你在做设备标准化程序,要把"字符串包含判断"封装成一个通用功能块,这套代码改改接口就能直接用。如果你在准备设备厂家或设计院的笔试面试,用FOR+MID实现子串查找几乎是字符串环节的必考题,理解滑动窗口的思路比背代码有用得多。至于只想要快速结果、不打算深究原理的项目,那你直接用FIND就够了,完全不丢人。

2. 动手之前:博途STRING在PLC里的真实存储结构

2.1 公式化记忆STRING的布局

在1500PLC里,STRING变量不是普通的数组,它自带管理信息。一个声明为STRING[254]的变量,在数据块里实际占用256个字节:前面部分字节用来记录最大长度和当前有效长度,从后面开始才是字符数据本身。你可以记住一个粗算公式:STRING占用字节数 ≈ 声明的最大字符数 + 2。

为什么要强调这个?因为很多现场问题是这么来的:你声明了STRING[10],觉得10个字符够用,但通信发送方一次性传过来13个字符,PLC在赋值阶段就把超出的部分直接截断了,你后面怎么查找都找不到本来存在的子串。这不是逻辑错,是存储容量不够。我习惯把所有可能需要接收外部数据的字符串变量直接声明成STRING[254],至少覆盖绝大多数工业字符串长度,避免这类隐性截断。

不过要说明一点,不同固件版本的STRING管理字节细节略有差异,但核心规律一致:不要手动去读写那前几个字节,统一用LEN(取长度)、MID(截取)这类指令操作,编译器会根据当前版本自动处理。

2.2 MID和LEN的计数规则与容易踩的索引坑

关于索引,高级语言程序员最容易在PLC里栽跟头:STRING的字符索引从1开始,不是0。MID(IN := #sourceStr, L := 3, P := 1)表示从第1个字符开始截3个字符,也就是取前三个字符;P := 0在PLC里属于非法位置,程序运行会报错或返回空串。

LEN函数返回的是字符串当前实际包含的字符个数,比如LEN('ABC240315001XYZ')返回15。这个"当前长度"和你声明的最大长度是两回事,一个字符都没有时LEN返回0。截取操作里,P + L - 1不能超过源字符串当前长度。举个例子:源字符串15个字符,你想从第14位开始截5个字符,14 + 5 - 1 = 18,超出15,这时候MID的实际行为可能会返回空串或截断后的残串,不同版本略有差异,但绝不能依赖这个特性。

我在调试字符串程序时,第一步永远是先看LEN结果对不对。长度不对,后面的截取和比较全是白费。你先在监控表里单独看#srcLen的值,确认它和实际字符数一致,再往下排查。

2.3 和高级语言字符串的差异

如果你熟悉C或者Python,会发现PLC字符串有几个别扭的地方。第一是索引从1开始,前面刚说过。第二是字符串变量声明时必须指定最大长度,相当于C语言里char数组加上长度上限,而Python那种动态字符串在PLC里不存在。第三是赋值截断静默发生,字符串太长不报错,只截断,这最容易埋雷。

拿Python做类比:'hello'[0:2]取he,而博途里MID('hello', 2, 1)取he,前者是左闭右开,起步0;后者是左闭右闭再加偏移。理解这个差异之后,写SCL的字符串处理就不容易串味道了。

3. 核心算法思路:滑动窗口法拆解子字符串查找

3.1 用传送带比喻理解滑动窗口

"判断源字符串是否含有子字符串"这个问题的核心,可以翻译成另一个问题:能不能在源字符串中找到一段连续字符,和目标子串一模一样?

我习惯拿传送带打比方。把源字符串想象成传送带上依次排列的盒子,每个盒子放一个字符;目标子串则是一个固定长度的检测框,一次性罩住N个盒子。最开始把检测框对准传送带最左端,检查框里的N个字符是否完全等于目标;如果不等,把检测框向右平移一格,再检查;一直推到检测框右边界超出传送带末端为止。

这个检测框每平移一次,就是FOR循环里的一次迭代。每迭代一次,用MID函数把检测框对应的那N个字符"截"出来,和目标子串做一次比较。整个过程没有用到任何魔法指令,就是机械地逐格比对,但绝对可靠。

3.2 比较次数到底怎么算:一个必须写进注释的公式

既然框是固定长度,它不可能无限向右移动。设源字符串长度是srcLen,目标子串长度是subLen,那有效比较次数就是:

比较次数 = srcLen - subLen + 1

这个公式建议直接写进代码注释,不然三个月后自己回来看都容易愣一下。为什么是+1?举个例子:源字符串HELLOWORLD长度10,目标子串WORLD长度5。检测框长度5,最左端在第1个字符,最右端能到的位置是第10-5+1=6个字符。位置6时,框住的是第6到第10个字符,也就是WORLD,正好匹配。如果推到位置7,框住第7到第11个字符,而第11个字符根本不存在。所以起点位置只能是1到6,共6次比较。

如果目标子串比源字符串还长,srcLen - subLen + 1变成负数,循环根本不该执行,结果直接判为不包含。这个边界条件的处理,我在第5章详说。

3.3 从算法到SCL伪代码

在写完整代码之前,先看一层伪代码,逻辑就清楚了:

// 初始化:还没找到 Found := FALSE; // 取两个字符串的实际长度 srcLen := LEN(Source); subLen := LEN(Target); // 只有目标非空,且目标长度小于等于源长度,才有必要循环 IF (subLen > 0) AND (subLen <= srcLen) THEN FOR i := 1 TO (srcLen - subLen + 1) DO // 从源字符串第i位开始取subLen个字符 temp := MID(Source, subLen, i); // 如果截出来的临时串和目标串相等 IF temp = Target THEN Found := TRUE; EXIT; // 找到第一个就可以退出循环 END_IF; END_FOR; END_IF;

到这里,核心思路已经落地了一半。伪代码里的变量具体用什么类型、在哪里声明、调用方式是什么,下一步把它变成能在博途里跑的完整程序。

4. 完整实现:FC块搭建、代码逐段解读与在线调试

4.1 建FC块与变量表

这个功能没有保持数据的需求,我建议用FC函数而不是FB功能块,调用时不需要背景数据块,干净。在博途里新建一个FC,命名为FC_StrContains,接口变量如下:

变量名数据类型方向说明
SourceStrSTRING[254]Input源字符串
TargetStrSTRING[254]Input目标子字符串
ContainsBOOLOutputTrue表示包含
srcLenINTTemp源字符串实际长度
subLenINTTemp目标子串实际长度
iINTTemp循环变量
tmpStrSTRING[254]Temp临时截取串

接口里SourceStr和TargetStr都声明成STRING[254],避免长度不够截断的问题。临时变量tmpStr也尽量给到254,因为MID截回来的字符串长度可能超过你预想,声明短了会直接截断。

4.2 完整SCL代码

// 功能:判断源字符串 SourceStr 是否包含子字符串 TargetStr // 原理:滑动窗口 + MID截取 + FOR循环逐位比较 // 返回:Contains = True 表示包含 Contains := FALSE; // 取当前实际长度,不要用声明的最大长度 srcLen := LEN(IN := SourceStr); subLen := LEN(IN := TargetStr); // 条件过滤: // 1. subLen > 0 排除空子串,工程上不把空串视为有效匹配 // 2. subLen <= srcLen 保证待比较窗口不超出源串范围 IF (subLen > 0) AND (subLen <= srcLen) THEN // 关键公式:窗口起点只能从 1 到 srcLen - subLen + 1 FOR i := 1 TO (srcLen - subLen + 1) DO // 从源字符串第 i 个字符开始截取 subLen 个字符 tmpStr := MID(IN := SourceStr, L := subLen, P := i); // 截出来的临时片段与目标子串逐字符比较 IF tmpStr = TargetStr THEN Contains := TRUE; EXIT; // 已经找到了,不需要继续循环 END_IF; END_FOR; END_IF;

4.3 代码逐段解读:为什么这样写

先看第一个判断条件:为什么要求subLen > 0?理论上讲,空字符串是任何字符串的"子串",但在工程逻辑里没有意义。如果TargetStr传了个空串,我们期望结果是不包含,而不是True,否则后续分支会跑出莫名其妙的结果。

再看循环终值srcLen - subLen + 1。终值在进入循环时只计算一次,如果循环体内修改了srcLen或subLen,不会影响循环次数。这里我们在循环体里没改任何长度变量,所以安全。

为什么用MID而不是LEFT、RIGHT?因为LEFT只能从最左边取,RIGHT只能从最右边取,只有MID支持任意起始位置。滑动的核心就是起始位置在变化,所以MID是唯一合适的取串工具。

比较tmpStr = TargetStr在SCL里是允许的,两个STRING类型直接比较内容。但有一个潜在细节:如果两个字符串变量声明的最大长度不同,比较结果是否受影响?我在TIA Portal V16、V17环境里实测,内容相同且有效长度相同的情况下,比较返回True。如果你遇到诡异的不相等,先检查两个字符串的有效长度是否一致,比如某个变量末尾多了空格。

EXIT语句是个好习惯。源字符串几百个字符时,如果第一个位置就匹配成功,后面几百次MID就没必要执行了。这个在通信报文解析这种大字符串场景里,性能能差出好几倍。

4.4 调用与在线监视

在OB1里调用FC,实参从数据块取:

"FC_StrContains"( SourceStr := "HMI_Data".ScanCode, TargetStr := '2403', Contains => "HMI_Data".HasTarget );

这里ScanCode是HMI或通信收到的条码字符串,目标串可以直接写字面量。在线调试时,我强烈建议使用监控表强制赋值,而不是干等现场信号:把SourceStr强制为ABC240315001XYZ,TargetStr强制为2403,然后运行看看Contains是否为True。为了验证循环过程,可以在SCL编辑器的tmpStr := MID(...)这行设置断点,在线单步执行,观察每一步的i值和tmpStr当前值。你会很直观地看到,当i等于4时,tmpStr变成了2403,然后Contains被置位,随后EXIT跳出循环。

这里有一个小坑:TIA Portal的SCL断点功能要求CPU在线且程序已下载,不是所有版本的Step 7都默认开启断点调试。如果断点不可用,就退而求其次,在IF tmpStr = TargetStr前后加两个赋值语句,把当前的i值存到一个监控变量里,硬数循环过程也行。

5. 六个最容易出问题的边界场景与处理办法

5.1 空字符串和目标子串为空

第一种情况:源字符串为空,目标子串非空。srcLen = 0,subLen > 0,条件subLen <= srcLen不成立,结果直接为False,合理。

第二种情况:源字符串非空,目标子串为空。subLen = 0,被subLen > 0挡在循环外,结果为False。有人会问,空串是不是应该算作包含?从字符串理论角度说是,但从设备运行安全角度,我坚决不建议把空串当成有效匹配。现场的条码字段不可能为空,一旦为空,更应该认为是数据异常,走异常分支,而不是走"包含匹配成功"的分支。

第三种情况:两者都为空。结果False,同上。

5.2 子串长度大于源字符串

这时srcLen - subLen + 1可能是0或负数。负数的FOR循环在SCL里的行为是什么?按我的经验,TIA Portal的FOR循环如果终值小于起始值,循环体一次都不执行,结果Contains保持False。逻辑上没问题,但我不建议依赖这个行为,因为不同版本编译器在这块的处理并不完全一致。最稳妥的就是代码里先判断subLen <= srcLen,条件不满足就直接跳过循环。这也是上面代码里嵌套一层IF的原因。

5.3 匹配位置在开头和结尾

开头匹配:i = 1时,MID从第1个字符开始截取subLen个字符,正好和目标一样。这是最理想的情况,循环第一次就命中,EXIT直接跳出。

结尾匹配:i = srcLen - subLen + 1时,MID从最后一个有效起点开始截取,取到的正好是源字符串最后几个字符。这个位置是循环的最后一次迭代,所以不会漏掉。要特别注意,绝对不能把循环终值写死成srcLen,否则最后一次截取会越界,MID在越界时的行为不可靠。老老实实用srcLen - subLen + 1。

5.4 大小写敏感问题

SCL的字符串比较是大小写敏感的。ABC和abc比较结果是不等于。现场条码经常出现大小写混用的情况,供应商这个月发来的条码是大写,下个月换了个批次就变成小写了。

最省心的处理方式,我建议在上位机或HMI侧先把字符串统一转成大写或小写,再传给PLC比较。1500PLC里做大小写转换比较麻烦,虽然可以逐字符读出来改ASCII码,但涉及到在STRING内部修改指定字符,代码量不小,而且用传统方式给STRING变量内部字符赋值挺别扭,不如在上位机处理干净。

如果你必须在PLC里做大小写不敏感比较,有一个变通思路:分别对源字符串和目标子串逐字符转换为大写后再比较。转换的逻辑是遍历每个字符,判断ASCII码是否在小写字母范围内,是则减32。这个思路本身不难,但要注意遍历时使用LEN获取实际字符数,且只针对ASCII字符有效。

5.5 中文与多字节字符的处理

STRING类型本质上是按字节存储字符串的,中文汉字在GBK编码下占用2个字节。问题来了:LEN和MID在处理中文时,按什么单位计算?

按照我在1500PLC上的实际经验,LEN对包含中文的STRING返回的结果可能和字符数对不上,MID在截取时也可能出现半个汉字、乱码的情况。原因在于这些字符串指令对STRING类型是按字节位置工作的,一个汉字占2个字节,当你从某个偏移量截取时,很可能正好落在汉字的中间字节上。

所以明确建议:如果现场可能输入中文,不要用这套STRING方案做包含判断,改用WSTRING宽字符串类型。WSTRING每个字符占2字节,对中文的支持更完善,LEN和MID按字符计算也更符合直觉。但WSTRING在通信和HMI上需要额外注意格式匹配,这里不展开。简单记住一句话:只处理ASCII码和数字,用STRING很省心;要处理中文,绕开STRING。

5.6 STRING长度超限与截断

这是我最想强调的隐性坑。你把一个字符串赋给STRING变量时,如果字符串实际长度超过声明最大长度,PLC不会报错,而是静默截断。比如声明STRING[10],赋值为ABCDEFGHIJKLMN,实际存进去的只有ABCDEFGHIJ,后面四个字符直接丢了。

这个坑在通信场景特别常见。Profinet或Modbus传输过来的字符串长度,往往由对方设备决定,你无法保证永远在10个字符以内。一旦截断,长度对不上、内容对不上,你在PLC里排查半天找不到原因,最后发现是声明长度不够。

我的习惯是:所有接口字符串统一声明为STRING[254],存储变量如果确实担心DB空间占用,再按实际需求收紧。但接口参数、临时变量一律宽松。一行代码省几个字节,不值得拿一次现场故障来换。

6. 进阶玩法:返回所有匹配位置与性能优化思路

6.1 从"是否包含"升级为"返回所有位置"

FIND做不到的功能,FOR+MID天生就会。如果你需要知道目标子串在源字符串中出现的所有位置,只需把上一版的"找到即退出"改成"找到就记录然后继续循环"。

// 假设已经声明了输出数组 matches : Array[0..99] OF INT // matchesCounter 记录找到次数 matchesCounter := 0; FOR i := 1 TO (srcLen - subLen + 1) DO tmpStr := MID(IN := SourceStr, L := subLen, P := i); IF tmpStr = TargetStr THEN matches[matchesCounter] := i; // 记录匹配起始位置 matchesCounter := matchesCounter + 1; // 注意:不执行 EXIT,继续往后找 END_IF; END_FOR;

这段代码里数组下标从0开始计数,存的是匹配位置1、匹配位置2……如果matchesCounter为0,就表示一个位置都没找到。这种能力和FIND函数相比是维度上的优势,比如报文里相同关键字出现多次,你想每次出现都触发一次处理逻辑,就得用这种方案。

需要注意数组大小限制。源字符串最长254个子串,但匹配次数最多也不会超过128次(至少子串长度为1,254个字符最多254个匹配位置,数组可以声明到254)。声明数组时留足余量,避免运行时越界。

6.2 简单有效的性能优化技巧

如果源字符串很长,比如几百个字符,每次都执行一次MID截取整个子串再比较,多少有些浪费。一种常见的提速思路是:首字符过滤。

在截取整个子串之前,先判断源字符串当前位置的字符是否等于目标子串的第一个字符。如果不相等,说明这段不可能匹配,直接跳过MID,节省一次截取操作。

FOR i := 1 TO (srcLen - subLen + 1) DO // 快速过滤:当前字符不等于目标首字符,直接跳过 IF SourceStr[i] = TargetStr[1] THEN tmpStr := MID(IN := SourceStr, L := subLen, P := i); IF tmpStr = TargetStr THEN Contains := TRUE; EXIT; END_IF; END_IF; END_FOR;

S7-1500的SCL环境里,SourceStr[i]这种索引方式可以访问STRING变量中第i个字符,返回Char类型。首字符过滤对于随机分布的字符串能省掉大量MID调用。不过如果目标子串很短、源字符串也不长,这点性能提升不大,代码可读性略有下降。我的建议是:源字符串超过100个字符再考虑这个优化,小字符串保持简单逻辑优先。

6.3 从"第N位之后"开始查找的扩展

另一个常见需求是从源字符串不从头找,而是从第N位之后开始找。这在解析固定报头报文时特别常见:前面8位是帧头,你要找的关键字在帧头之后才可能出现。

在FC接口里加一个Input参数SearchStart : INT,然后FOR循环从SearchStart开始:

FOR i := SearchStart TO (srcLen - subLen + 1) DO // 循环体不变 END_FOR;

但调用前必须做两个判断:SearchStart不能小于1,否则相当于从头找;SearchStart不能大于srcLen - subLen + 1,否则循环一次都不执行,等于白找。实际项目里,这两个边界很容易被忽略,传进来的SearchStart是HMI上操作员填的数字,随便填个100,源字符串总共才20个字符,那结果必然是False,操作员会以为程序坏了。

我在封装标准库时,会统一在FC内部再做一次起点校正:

IF SearchStart < 1 THEN SearchStart := 1; END_IF;

这样不管你外部传入什么值,FC都能给你一个合理的结果。


最后再分享一点个人的实操体会。这套FOR+MID逻辑我写过很多遍,踩过的坑总结下来就三条:其一,长度永远用LEN现取,不要凭印象写死;其二,临时字符串变量的长度一定要够大,宁可少吃几个字节也不截断;其三,循环里找到匹配后务必EXIT,否则源字符串一长,CPU时间白烧。把这三点记住,你基本就不会在这个问题上翻车。往后你要是遇到"找所有出现位置""从第N位开始找""统计某个字段出现次数"这些需求,都可以从这一篇的思路直接扩展,不需要再到处找库函数说明。

相关新闻

大模型Token计费全解析:从分词原理到成本优化实战

大模型Token计费全解析:从分词原理到成本优化实战

记得我刚接触大模型开发那会儿&#xff0c;最让我头疼的还真不是提示词怎么写&#xff0c;而是后台账单上的那一串token数字。明明感觉没聊几句&#xff0c;钱就悄悄没了&#xff0c;看计费详情时又一头雾水。后来自己跑接口做应用&#xff0c;才彻底搞明白Token到底是什么&…

2026/10/20 2:37:36 阅读更多 →
剪纸主题网页制作指南:HTML+CSS+JavaScript实现传统美学与交互设计

剪纸主题网页制作指南:HTML+CSS+JavaScript实现传统美学与交互设计

前两天有个同学跑过来问我&#xff0c;说期末作业想做“Web剪纸”主题的网页&#xff0c;不知道怎么把剪纸这种传统手艺和网页制作结合起来。我当时一听就觉得这个选题选得挺聪明的——剪纸是最有辨识度的中国民间视觉符号之一&#xff0c;红色、镂空、对称&#xff0c;任何一个…

2026/10/20 2:37:36 阅读更多 →
Ubuntu循环登录自救指南:从tty命令行到图形会话修复全流程

Ubuntu循环登录自救指南:从tty命令行到图形会话修复全流程

1. 循环登录的典型症状与背后机制1.1 症状什么样&#xff0c;怎么判断是不是它作为常年折腾桌面Linux的人&#xff0c;Ubuntu循环登录这五个字几乎每年都要见上几次。它不是某个品牌的独家问题&#xff0c;也不是Ubuntu 22.04才有的新毛病。我经手的案例里&#xff0c;从18.04到…

2026/10/20 2:37:36 阅读更多 →

最新新闻

调教Stable Diffusion注意力机制,让出图更清晰

调教Stable Diffusion注意力机制,让出图更清晰

1. 先别急着加高清修复&#xff0c;问题多半出在注意力分配上先说个不少人踩过的坑&#xff1a;用Stable Diffusion出图&#xff0c;总感觉边缘发虚、细节糊成一团&#xff0c;第一反应往往是把分辨率从512拉高到1024&#xff0c;或者直接开Hires. fix&#xff0c;结果要么显存…

2026/10/20 3:27:05 阅读更多 →
加密狗复制风险与工控软件授权管理:从停产事故看正确应对方式

加密狗复制风险与工控软件授权管理:从停产事故看正确应对方式

上个月我去一家做汽车零部件加工的朋友那边聊设备改造&#xff0c;正好撞上他们车间的一件急事&#xff1a;产线上一套工艺管理软件的加密狗突然失效&#xff0c;操作员报错、工艺配方调不出来&#xff0c;整个班组停了半个多小时。朋友的第一反应不是联系软件供应商&#xff0…

2026/10/20 3:27:05 阅读更多 →
Unity Scroll View Content配置全解:滚动失效排查与动态列表实战

Unity Scroll View Content配置全解:滚动失效排查与动态列表实战

聊起Unity里的Scroll View&#xff0c;十个新手有九个都栽在Content设置上。上周交流群里又有人发截图问&#xff1a;东西全拖进Scroll View了&#xff0c;为什么滚不动、显示不全、滚动条乱蹦&#xff1f;问题基本都出在Content这个子节点上。这篇专门讲Scroll View下Content的…

2026/10/20 3:27:05 阅读更多 →
AI Agent核心能力拆解与工程落地实战指南

AI Agent核心能力拆解与工程落地实战指南

各位做技术、做产品的朋友&#xff0c;最近是不是隔三差五就被"AI Agent"这个词刷屏&#xff1f;团队研讨它在讲&#xff0c;朋友圈技术博主在聊&#xff0c;产品评审会也在问"为什么不做成Agent"。但如果真让你一句话讲清楚它到底是什么&#xff0c;很多人…

2026/10/20 3:27:05 阅读更多 →
OpenAI兼容格式接入中文大模型:从密钥配置到流式输出实战

OpenAI兼容格式接入中文大模型:从密钥配置到流式输出实战

我先说个结论&#xff1a;如果你现在手里攒着一堆“用某个平台接大模型”的活儿&#xff0c;最省心的路线&#xff0c;往往不是直接用厂商自己那套SDK&#xff0c;而是找一个已经帮你把接口层做成了OpenAI兼容格式的数据中间件。这篇内容就围绕一个具体方案展开——用某数据云平…

2026/10/20 3:27:05 阅读更多 →
DeepSeek降AI指令5步流程:从AI味到自然学术写作

DeepSeek降AI指令5步流程:从AI味到自然学术写作

最近太多人在问“DeepSeek降AI指令怎么写”&#xff0c;尤其是论文写了一半&#xff0c;拿AI润色完&#xff0c;自己一读都觉得“太工整了”&#xff0c;然后被各种AI痕迹检测提示搞得心里发毛。先说结论&#xff1a;所谓“降AI”&#xff0c;并不是玄学&#xff0c;本质是让大…

2026/10/20 3:26:04 阅读更多 →

日新闻

CLRC663芯片Pin-to-Pin替代实战:从评估到量产全记录

CLRC663芯片Pin-to-Pin替代实战:从评估到量产全记录

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/20 1:01:30 阅读更多 →
ESP32舵机控制指南:原理、多路驱动与避坑实战

ESP32舵机控制指南:原理、多路驱动与避坑实战

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/20 1:01:30 阅读更多 →
位移法实现一阶低通滤波:单片机ADC采样降噪实战

位移法实现一阶低通滤波:单片机ADC采样降噪实战

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/20 1:01:30 阅读更多 →

周新闻

基于GMM的语音识别系统原理与MATLAB实现详解

基于GMM的语音识别系统原理与MATLAB实现详解

说到基于高斯混合模型&#xff08;GMM&#xff09;的语音识别系统&#xff0c;很多人第一反应就是一堆数学公式&#xff0c;觉得门槛很高。但如果你真的在MATLAB里把它落地跑通&#xff0c;会发现核心其实就是三件事&#xff1a;把声音变成特征向量&#xff0c;用GMM给每个类别…

2026/10/19 10:02:04 阅读更多 →
数字图像处理入门:反白、灰度化、调色板修改与导出txt实践

数字图像处理入门:反白、灰度化、调色板修改与导出txt实践

数字图像处理这四个字听起来挺唬人&#xff0c;但落到具体操作上&#xff0c;无非就是让计算机按你的想法“摆弄”像素。我在一个模拟项目X里用了一套特别经典的基础处理流程&#xff1a;对图像做反白、改调色板、彩色转灰度&#xff0c;最后把像素数据导出成txt文件。单看每一…

2026/10/19 17:32:41 阅读更多 →
机器人大脑技术盘点:具身智能的感知、决策与数据闭环

机器人大脑技术盘点:具身智能的感知、决策与数据闭环

如果你的信息流最近也天天刷到“机器人大脑”这个词&#xff0c;你会发现一个很有意思的现象&#xff1a;每个人说的“大脑”根本不是同一个东西。有人指的是大语言模型&#xff0c;有人指的是运动控制系统&#xff0c;还有人指的是能理解物理世界的端到端模型。在2026年这个时…

2026/10/20 2:50:50 阅读更多 →

月新闻

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/19 2:54:50 阅读更多 →
Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/19 9:10:22 阅读更多 →
黑夜航拍船只数据集训练YOLOV5模型全流程解析

黑夜航拍船只数据集训练YOLOV5模型全流程解析

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/18 12:16:16 阅读更多 →