news 2026/9/7 23:04:47

C语言字符串操作:不用第二指针实现删除指定字符与字符间插入空格

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
C语言字符串操作:不用第二指针实现删除指定字符与字符间插入空格

这个题目很有代表性,我第一眼看到就想起当年被指针和字符串数组折腾的日子。它表面上是两道操作题——删除特定字符、字符间插空格,但真正考察的是对“数组内存布局”和“下标即指针偏移”这两个概念的理解。很多人能写出功能正常的代码,但一旦被要求“不用第二指针”,立刻就卡住了。这篇文章就把这两道题彻底拆开,从原理到代码到坑点,一次讲透。

1. 项目概述与核心需求拆解

1.1 这个题目到底在考什么

先看题面:【指针删除字符串特定字符不用第二指针、不使用第二指针实现字符串间插空格】。注意这里的关键词是“不用第二指针”、“不使用第二指针”,这不是偷懒的写法,而是刻意制造的限制条件。

在C语言里,处理字符串删除和插入的常规做法确实是双指针。删除字符用快慢指针,慢指针指向最终结果写入位置,快指针遍历原串;插入空格则通常从尾部开始搬移,用两个指针分别指向原串尾部和新串尾部。但题目一旦要求去掉第二个指针,很多人就懵了——因为我刚才提到的所有经典解法,从思路上都依赖两个游标协同工作。

那这个问题真正想考察的是什么?答案是:指针和下标本质上是同一件事p[i]就是*(p + i),一个指针配上偏移量,完全可以替代第二个指针的职责。换句话说,题目限制的是“不要声明第二个char *变量”,但并没有禁止你使用一个整型变量当作偏移量。很多初学者在刷这类题时,把“指针”想得太神秘,总觉得一定要写出*p*(p+1)这种形式才算用指针。实际上下标就是语法糖,理解了这一层,限制也就被绕开了。

1.2 两个任务的目标与边界条件

任务A:删除字符串中的特定字符,例如把hello world中的所有l删除,得到heo word

任务B:在字符串每个字符之间插入一个空格,例如把abcd变成a b c d

这两个任务看起来一正一反,但共同点是都涉及连续内存区域中的数据搬移。删除是向前搬移覆盖,插入是向后搬移腾位。真正难的点在于:不允许使用第二个指针变量时,如何保证搬移过程中数据不丢失、顺序不乱、终点正确。

还要注意题面里括号内的细节——2025-1-2。这个日期倒不必过度解读,但这类题目往往出现在期末机试、考研C语言复习、刷题平台的经典题型里。也就是说,读者很可能是在备考或者刷题时遇到这个题的,那么解题思路的严谨性、边界条件的完整性,比花哨的技巧更重要。

2. 常规“双指针”方案回顾:为什么它是首选

2.1 删除字符串特定字符的快慢指针版本

在动手写“单指针版本”之前,先把大家最容易想到的常规解法梳理一遍。因为理解了常规解法做了什么,才能明白限制条件真正砍掉了什么。

删除字符的快慢指针代码如下:

#include <stdio.h> void delete_char(char *s, char target) { char *slow = s; char *fast = s; while (*fast != '\0') { if (*fast != target) { *slow = *fast; slow++; } fast++; } *slow = '\0'; }

这里fast负责“侦查”,逐个检查原字符串里的字符;slow负责“落地”,把不需要删除的字符依次写到字符串前面。两个指针一快一慢,同向移动,互相之间最多差一个距离,整个过程在原数组内完成,不需要额外申请空间。

这个方案的时间复杂度是 O(n),空间复杂度 O(1),非常干净,是C语言初学者应该熟练掌握的模板。我见过不少人在这一题上犯的错是:忘记在最后补*slow = '\0',导致字符串尾部残留旧数据。这在调试时往往看不出问题,但一旦用strlen()或者输出时,就会出现莫名其妙的乱码。

2.2 插入空格的从后向前版本

插入字符比删除字符要麻烦一些。因为删除是“往后读、往前写”,前面一定有空位;而插入是“往前读、往后写”,如果从前向后处理,后面的字符很快会被覆盖掉。所以常规解法是倒着来:先算出插入完后的总长度,然后把原字符串从尾部一个个搬到新位置,边搬边把空格填进去。

#include <stdio.h> #include <string.h> void insert_space(char *s) { int len = strlen(s); int new_len = len + (len - 1); // 每个字符间插一个空格,末尾不加 s[new_len] = '\0'; for (int i = len - 1; i >= 0; i--) { s[--new_len] = s[i]; if (i > 0) { s[--new_len] = ' '; } } }

逻辑很简单:用new_len当“新串的写指针”,用i当“原串的读指针”,从后往前同步推进。注意这里new_len是整型下标,不是指针。这其实就是那种“口头上说不用指针,实际上下标用得很欢”的写法,但恰恰是这种情况下最稳妥的解法。

如果你非要用char *指针,也能写,只是指针来回移动容易把自己绕晕:

void insert_space_ptr(char *s) { int len = strlen(s); int new_len = len * 2 - 1; s[new_len] = '\0'; char *p = s + len - 1; // 指向原串最后一个字符 char *q = s + new_len - 1; // 指向新串最后一个写作位置 while (p >= s) { *q-- = *p--; if (p >= s) { *q-- = ' '; } } }

不停自减的指针看着头疼?这就是为什么很多阅卷老师反而建议用下标,清晰、直观、不容易错。

2.3 限制“不用第二指针”的本质

现在再回头看题目:它要你“不用第二指针”。在双指针方案里,slowfast是两个char *;在插入方案里,pq也是两个char *。限制条件就是要求你把其中一个指针变量去掉,改用其他方式来追踪位置。

最直接的做法是用整型int作为下标。下标本质就是“指针的偏移量”,你把char *p = s + i;p省略掉,直接用s[i],语法上完全等价。所以你可以说“我没有用第二个指针”,但实现上依然遵循快慢指针那样的位置分离逻辑。

如果连下标也不允许用(真的是极端情况),那就只能通过“每次搬移时把整个字符串整体移动”这种 O(n^2) 的方法来实现。虽然能过功能测试,但效率太差了,实际工程里不会这么写。在本篇文章里,我按“不用第二指针变量,但允许用整型下标/计数器”这个理解来展开,这也是刷题平台和考试中最常见的允许范围。

3. 严格限制下的删除字符实现:计数覆盖法

3.1 思路分析:一个下标压缩全串

我们先用最简单的方式实现“不用第二指针的删除”。既然不能声明第二个char *,那就只用一个指针去遍历原串,另用一个整型计数器记录“已经写入的字符个数”。写入位置直接用s[count]表达,读的位置用p表达。

从前向后扫描,碰到非目标字符,就把它放到s[count]上,然后count++;碰到目标字符,直接跳过,不写入。扫描结束后,在s[count]处放一个'\0'截断。

#include <stdio.h> void delete_char_single_ptr(char *s, char target) { int count = 0; // 等效于慢指针的偏移量 char *p = s; // 唯一的指针,负责遍历 while (*p) { if (*p != target) { s[count] = *p; count++; } p++; } s[count] = '\0'; }

仔细看这个实现:执行过程中,p是向后前进的“读指针”,count是落在了安全区内的“写位置”。所有的写操作都发生在s[count],它永远不会超过p当前指向的位置,因此不会覆盖掉还没来得及读的数据。这正是快慢指针的“先读后写”原则,在这里用“一个指针 + 一个整型”复刻出来了。

3.2 严格去掉计数器:纯指针往复搬移

上面这个版本,严格来说还是用了一个整型变量当“第二游标”。假如题目特别死板,连int count都不让声明,那还有一个办法:每删除一个字符,就把后面的所有字符整体向前搬一格。整个过程只用一个指针,但代价是时间复杂度从 O(n) 退化为 O(n^2)。

#include <stdio.h> void delete_char_pure_ptr(char *s, char target) { char *p = s; while (*p) { if (*p == target) { char *q = p; // 等等,这里又声明了一个指针! while (*q) { *q = *(q + 1); q++; } } else { p++; } } }

这个版本里我用了一个q来搬移剩余字符串,还是违反了“不用第二指针”的严格限制。所以这种方式其实没法做到真正“只用单指针 + 无整型变量”的删除操作,除非你递归处理,或者允许声明函数参数变量。看到这里你就该明白,题目的重点并不是逼你在 O(n^2) 里硬抠,而是考察你能否想到用“整型偏移量”来代替“指针变量”。

所以我的建议是:不要被“不用第二指针”这句话束缚得太死。只要你不显式声明第二个char *类型指针,而用int下标实现同样的逻辑,在绝大多数场景下就是符合题目要求的。

3.3 测试用例与运行结果

写代码很容易,但验证边界条件才是真正区分水平的地方。我建议至少测五组情况:字符在开头、字符在结尾、连续重复字符、没有任何目标字符、空字符串。

#include <stdio.h> #include <string.h> void delete_char_single_ptr(char *s, char target) { int count = 0; char *p = s; while (*p) { if (*p != target) { s[count] = *p; count++; } p++; } s[count] = '\0'; } void test(char *s, char target) { printf("原始串: \"%s\", 删除 '%c'\n", s, target); delete_char_single_ptr(s, target); printf("删除后: \"%s\"\n\n", s); } int main() { char s1[] = "hello world"; test(s1, 'l'); char s2[] = "aabc"; test(s2, 'a'); char s3[] = "axxx"; test(s3, 'x'); char s4[] = "nochange"; test(s4, 'z'); char s5[] = ""; test(s5, 'a'); return 0; }

输出结果:

原始串: "hello world", 删除 'l' 删除后: "heo word" 原始串: "aabc", 删除 'a' 删除后: "bc" 原始串: "axxx", 删除 'x' 删除后: "a" 原始串: "nochange", 删除 'z' 删除后: "nochange" 原始串: "", 删除 'a' 删除后: ""

删除连续重复字符时,慢位置写入的节奏要跟得上前进的节奏,只要判断条件写的是“不等于目标才写入”,连续出现目标字符时自然会连续跳过,不会出问题。空字符串单独测试很重要,因为很多解法在空串上会越界访问,比如还没确认*p是否为'\0'就去执行p++之类的操作。

3.4 一个容易忽略的坑:字符串字面量不可修改

我在调试时踩过一个特别典型的坑:直接用char *s = "hello";声明字符串,传给删除函数,结果程序运行直接 crash。原因很简单,指向字符串字面量的指针指向的是只读数据段,不能修改其内容。删除函数需要向s里写数据,就必须保证s指向可写的内存。

解决办法是改用char s[] = "hello";初始化数组,这样字符串会存放在栈区,可以修改。这个坑在笔试环节不一定会出现,但在实际调试代码时可太常见了,我自己就栽过不止一次。

4. 严格限制下的字符间插空格实现:预计算长度回填法

4.1 为什么必须从后往前处理

字符间插入空格,本质是在长度为n的字符串中间插入n-1个空格,得到总长度为2n-1的新字符串。这里有个重要前提:题目通常允许你预先知道字符串有足够的空间存放插入后的结果,否则就需要动态分配内存,比如malloc

从前向后插入会造成数据覆盖,这一点在 2.2 节已经解释过。一个直观的例子:abc要变a b c。如果你先在前两个字符之间插入空格,得到a bc,接下来去第三个位置插入空格时,原本的c已经被推到更后面了,你得先知道它挪去了哪里。这个过程中所有字符的位置都在不断变化,从前面写容易漏数据。

从后往前处理是一劳永逸的办法:先确定最终字符串的结尾位置,把结尾的'\0'放到正确位置,再逐步从后往前把原字符复制过去,复制一个字符后,紧接着在它前面补一个空格。这样每个原字符都是先被复制到新位置,然后它的正前方才被空格占位,绝不会覆盖还没有处理过的字符。

4.2 只用一个指针变量实现

这里我们约束自己:只能声明一个char *类型的指针,同时可以用整型变量辅助计算长度。这个限制其实很宽松,整型变量不算“第二指针”。

#include <stdio.h> #include <string.h> void insert_space_single_ptr(char *s) { int len = strlen(s); if (len <= 1) { return; // 只有一个字符或空串,无需处理 } int new_len = len + (len - 1); s[new_len] = '\0'; // 新串末尾 char *p = s + len - 1; // 唯一指针,从原串最后一个字符开始 for (int i = len - 1; i >= 0; i--) { s[--new_len] = p[i]; if (i > 0) { s[--new_len] = ' '; } } }

等等,这里p声明了但好像也没派上用场,因为全程用的是p[i],这跟s[i]没区别。我把它改得更纯正一点——用指针从后往前移动,彻底不用下标访问原串:

void insert_space_single_ptr_v2(char *s) { int len = strlen(s); if (len <= 1) return; int new_len = len * 2 - 1; s[new_len] = '\0'; char *p = s + len - 1; // 唯一指针,指向原串末尾字符 while (p >= s) { s[new_len--] = *p; // 写原字符 if (p > s) { s[new_len--] = ' '; // 不是第一个字符时,前面补空格 } p--; } }

这个版本里,指针p从后往前扫过原串,每扫到一个字符,先把它写入新位置,然后判断它是否还有前一个字符,如果有,就在它前面写一个空格。循环结束后,正好写出len个原字符和len - 1个空格,组成a b c d这样以原字符开头、空格间隔、原字符收尾的字符串。

4.3 完整可运行示例

#include <stdio.h> #include <string.h> void insert_space_single_ptr_v2(char *s) { int len = strlen(s); if (len <= 1) return; int new_len = len * 2 - 1; s[new_len] = '\0'; char *p = s + len - 1; while (p >= s) { s[new_len--] = *p; if (p > s) { s[new_len--] = ' '; } p--; } } int main() { char buf[128]; // 测试1 strcpy(buf, "abcd"); insert_space_single_ptr_v2(buf); printf("[%s]\n", buf); // [a b c d] // 测试2 strcpy(buf, "hello"); insert_space_single_ptr_v2(buf); printf("[%s]\n", buf); // [h e l l o] // 测试3 strcpy(buf, "a"); insert_space_single_ptr_v2(buf); printf("[%s]\n", buf); // [a] // 测试4 strcpy(buf, ""); insert_space_single_ptr_v2(buf); printf("[%s]\n", buf); // [] return 0; }

输出都很正常。那个if (p > s)的判断很关键,它保证了字符串的开头不会多出一个空格。如果写成if (p >= s),那么第一个原字符前面也会被插一个空格,整体就变成" a b c d"了,多半不是题目想要的结果。这算是最容易踩的边界条件之一。

4.4 内存空间问题:为什么需要预留缓冲区

注意我在main里用的是char buf[128],而不是char *buf = "abcd"。不仅仅是只读数据段的问题,还有缓冲区容量的考量。假设原本字符串长度是 4,插入空格后长度变成 7,如果你的数组只声明了 5 个字节,写'\0'和后续字符时就会越界,后果可能是在堆栈里覆盖其他变量的内存,产生非常难排查的随机性 bug。

所以这类题目如果出现在实际工作里,第一步应该是确认存储空间是否足够。稳妥的做法是:先统计需要的空间,再用动态内存分配或者调用方提供足够大的缓冲区。我建议的函数声明是void insert_space(char *s, int cap),在函数内部先判断cap是否足够,不够就直接返回错误码。虽然刷题时不会这么要求,但工程思维才是长期受用的东西。

5. 两种操作的统一视角:本质是内存搬移

5.1 把删除和插空格抽象成一个模型

很多初学者把删除字符和插入字符当成两类完全不同的算法来记,其实它们共享同一个底层逻辑:在一段连续内存里,把若干字节从一个区间搬到另一个区间,同时保证顺序不变

删除字符类:把后半部分的字符向前搬移,覆盖掉不要的字符。这里搬移的方向是向低地址方向,搬移范围是从目标字符后面的第一个字符开始,直到'\0'

插入字符类:把原有数据向后搬移,腾出中间位置来放新字符。这里搬移方向是向高地址方向,搬移范围是从新字符串的尾部开始,一直到开头。

两种操作都遵循一个原则:如果搬移方向与数据移动方向相同(从前向后搬移),从前往后循环;如果相反(从后向前搬移),从后往前循环。这个原则说起来很简单,却是无数人写错的关键。删除时慢指针永远写在快指针左侧,所以可以放心从前往后;插入时空格占据的是更大的地址,如果从前往后写,后面的字符还没搬走就被覆盖了,必须从尾向前倒序处理。

5.2 指针、下标、偏移量是一回事

在处理这类问题时,我建议你在心里时刻默念一句话:s[i]就是*(s + i)。也就是说,数组下标访问本质是通过指针算术实现的。s本身可以被看成指向数组首元素的指针,i是从首元素偏移了多少个char的距离。

这样,题目里说的“不用第二指针”,最正面的解法其实就是“把第二指针隐藏在下标里”。你可以这样写给自己的阅卷人看:在注释里写着“本实现只声明了一个char *指针,用于遍历;写入位置通过整型偏移量控制”,然后代码里只用s[count]s[new_len]进行读写。这样既符合限制要求,又保留了双指针方案的效率优势。

5.3 时间复杂度与空间复杂度的权衡

实现方式时间复杂度空间复杂度优点缺点
双指针删除O(n)O(1)快、简洁需要两个指针变量
单指针+下标删除O(n)O(1)符合限制、不易踩坑思维上要接受下标等价指针
反复搬移删除O(n^2)O(1)最严格符合单指针慢,重复搬移浪费大
从后往前插空格O(n)O(1)快、不覆盖需要预先知道空间足够

从上表能直观看出,最优策略就是用“一个指针 + 整型偏移量”来取代“双指针”。对面试和考试来说足够了,对工程来说也是清晰的实现方式。

6. 常见问题与排查技巧实录

6.1 删除字符后出现乱码或长度不对

这是最常见的问题。原因基本就一个:字符串末尾没有正确放置'\0'。删除操作把有效字符往前移动后,原来末尾的'\0'也被搬走了,新逻辑上末尾的位置需要手动补一个终止符。如果不补,strlen()会继续往后读,直到内存中碰巧遇到一个零字节,结果不可预测。

排查方法:在删除函数结束后立即打印字符串的十六进制字节内容,比如for (int i = 0; i < 20; i++) printf("%02x ", s[i] & 0xff);,一眼就能看出字符是不是连续、'\0'是不是在正确位置。

6.2 插空格后字符串头尾多出空格

我在 4.3 节强调过那个if (p > s)判断。很多人从后往前搬移时,习惯性写成“每次都先插空格再写字符”,结果导致字符串开头多了空格。比如abc变成a b c而不是a b c。记住一个规则:原字符串的第0个字符前面永远不需要空格,第len - 1个字符后面也不加空格(除非题目明确要求两边都加)。

如果题目要求的是“每个字符之间”而不是“每个字符前面”,那就遵循上面的规则;如果题目换成了“每个字符后面都加一个空格”,那就是2n的长度,需要在每个原字符后写空格,包括最后一个。别小看这微小的差别,很多实际业务里的格式化字符串需求就经常在这里栽跟头。

6.3 字符串字面量导致崩溃

前面提过,char *s = "test";指向只读内存。如果函数里执行s[0] = 'x',在部分平台会直接触发段错误,在另一些平台可能“碰巧”没崩但行为未定义。解决办法是使用数组初始化:char s[] = "test";

如果在C++里,情况类似,建议用std::string,需要原地改就直接操作std::string::iterator或者用erase/insert方法。不过既然题目特别强调了指针,那大概率是C语言的场景,不往C++方向过度展开了。

6.4 中文字符串不能按单字节处理

严格来说,如果一个字符串是 UTF-8 编码的中文内容,比如"你好世界",每个汉字占 3 个字节,你按下标操作时挨个字节处理会拆散汉字,导致输出乱码。这类题目通常会限定“英文字母/数字/可见ASCII字符”,但如果需求变化成“删除某个中文字符”,就没法用上面这些单字节逻辑直接实现了。

在实际项目中遇到这种情况,我的建议是:要么把字符串统一转成宽字符类型(wchar_t)再操作,要么用字符串处理库(如 ICU)来做字符边界识别,千万不要自己硬刚字节流。这不是技术难度的问题,而是字符编码天然复杂,不值得重新造轮子。

6.5 缓冲区越界导致程序诡异闪退

插空格的常见越界场景:原串长度是 10,插入空格后需要19字节,加上'\0'共20字节,但调用方给的缓冲区只有16字节。后果可能不会立即显现,但等你再往后面写点别的变量,程序就会在某个完全不相干的地方崩溃,调试起来极其痛苦。

排查技巧:在函数开头计算需求容量,并与调用方传入的容量参数比对。没有容量参数的话,可以约定调用方必须保证缓冲区足够大,比如用一个宏定义#define MAX_LEN 1024来约束。写生产代码时强烈建议加长度参数,即便指针题目不要求,你也要有这个意识。

7. 从题目延伸开去:这类技巧的真实应用场景

删除字符串特定字符、字符间插入分隔符,看起来是教科书里的练习题,实际上在真实开发里处处可见。

比如做日志脱敏时要删除身份证号里的某些位,做格式化输出时要在 MAC 地址的每个字节间插入冒号,或者把一串数字用千分位逗号分隔,再或者从 CSV 行里过滤掉某些转义字符。这些需求背后全部是“删除特定字符”和“按规则插入字符”的组合操作。能在一开始就把内存模型想清楚,后面写起业务代码来会顺手很多。

再比如嵌入式设备上的 C 编程,经常需要解析串口数据帧。帧里可能包含校验位、无用填充位,你要把它们从缓冲区里剔除,同时还要保证帧头帧尾位置正确。这和“删除特定字符”是同一类问题。

又比如格式化生成协议报文,需要把原始数据以空格分隔的形式打印到日志里,这就是“字符间插空格”。不少人在这个需求里手写循环,结果漏了边界情况,或者在倒序搬移时搞反了方向,最后调试大半天。这都是可以提前避开的坑。

理解了这些实际场景,你会发现,题目本身的“指针”和“字符串”只是载体,真正要训练的是对连续内存的调度能力。这个能力无论在 C、C++,还是其他底层语言中,都是核心中的核心。

我在实际写代码过程中最深的体会是:这类题目不要急着一次写对,先画一张内存示意图,标出读位置、写位置、安全区,然后再动手写代码。凡是能画出图的人,基本都能一次通过。凡是上来就硬写的,大概率在边界条件上栽跟头。

最后再分享一个小技巧:如果笔试或面试时真遇到类似的限制条件,大胆去和出题人确认边界。比如“不用第二指针”是否允许使用整型下标,缓冲区是否保证有足够空间。这类问题不是丢分,反而会让对方觉得你考虑问题周全,具备工程思维。扎实的基本功加上清晰的沟通,这才是解决这一类问题的通关钥匙。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/7 23:04:39

基于IEEE33节点的经济-碳协调最优调度与灵敏度分析Matlab实现

做了大半年综合能源系统的调度项目后&#xff0c;我最大的感受是&#xff1a;这类问题真正难的地方不在建模本身&#xff0c;而在于怎么把“经济性”和“低碳性”这两个目标放在同一个框架里协调&#xff0c;还要保证算出来的结果在工程上站得住。正好最近在IEEE33节点系统上完…

作者头像 李华
网站建设 2026/9/7 23:03:38

十年后端经验总结:核心技能比框架更重要

框架会过时&#xff0c;问题不会消失。我花了十年写后端&#xff0c;从Struts到Spring Boot&#xff0c;从PHP的混乱到Go的克制&#xff0c;从自建机房到云原生&#xff0c;如果只能留下一条教训&#xff0c;那就是&#xff1a;技术栈是你的外衣&#xff0c;核心技能才是你的肌…

作者头像 李华
网站建设 2026/9/7 23:03:37

FPGA实战:16QAM调制解调系统设计全流程复盘

做FPGA通信项目这些年&#xff0c;我的一个深刻体会是&#xff1a;调制解调系统是最适合用来打通“数学原理”和“硬件实现”之间那条鸿沟的练手题材。16QAM作为经典的高阶调制方式&#xff0c;既有星座映射、脉冲成形、同步恢复这些完整信号处理链路&#xff0c;又不会像256QA…

作者头像 李华
网站建设 2026/9/7 23:02:10

《影之刃零》愿望单破百万,它能否成为下一个《黑神话》?

1. 从“愿望单”说起&#xff1a;《影之刃零》凭什么破百万如果你常逛Steam&#xff0c;一定知道愿望单这个东西。它不是点了就完事的收藏按钮&#xff0c;Steam对愿望单的算法权重非常高——玩家把一个游戏加进愿望单&#xff0c;意味着“我记住了这个游戏&#xff0c;发售时请…

作者头像 李华
网站建设 2026/9/7 22:59:47

Everything 1.4.1精简版:NTFS文件搜索利器解析

1. Everything 1.4.1.1032 精简单文件版解析 作为Windows平台最知名的文件搜索工具&#xff0c;Everything以其闪电般的检索速度赢得了全球用户的青睐。今天要讨论的这个1.4.1.1032精简单文件版&#xff0c;是经过深度优化的特殊版本&#xff0c;去除了原版中非必要的组件和功能…

作者头像 李华
网站建设 2026/9/7 22:58:01

CKKS同态加密数学原理详解:从RLWE到模数链的完整推导

第一次在项目里真正把 CKKS 用起来的时候&#xff0c;我对着源代码里Encoder和Evaluator的接口发了很久的呆。之前我接触的是 BFV/BGV 这类整数同态方案&#xff0c;思路非常直接&#xff1a;把明文变成一个大整数&#xff0c;加密&#xff0c;做运算&#xff0c;再解密。可 CK…

作者头像 李华