网站建设初期 该如何推广,一般网站设计多大宽度,措美网站建设,河南建设银行官网招聘网站在学习完成了C语言的的指针这一大难点后#xff0c;我们将继续学习C语言里面的库函数#xff0c;其中字符函数也是比较重要的一类。 
零 . 字符函数#xff1a; 
下面列出了头文件 ctype.h 中定义的函数。 这些函数用于测试字符是否属于某种类型#xff0c;这些函数接受 in…在学习完成了C语言的的指针这一大难点后我们将继续学习C语言里面的库函数其中字符函数也是比较重要的一类。 
零 . 字符函数 
下面列出了头文件 ctype.h 中定义的函数。 这些函数用于测试字符是否属于某种类型这些函数接受 int 作为参数它的值必须是 EOF 或表示为一个无符号字符。 如果参数 c 满足描述的条件则这些函数返回非零true。如果参数 c 不满足描述的条件则这些函数返回  
这些函数所需要的头文件是ctype.h,在这里我们只需要练习一个函数就ok了其他的函数是非常类似的。借助下面的练习完成。 
1.1. 练习1将字符串中的小写字母改成大写字母其他不变 
方法一利用ASCII码来改变 
代码如下 
#define  _CRT_SECURE_NO_WARNINGS
#includestdio.h
#includectype.h
//练习1将字符串中的小写字母改成大写字母其他不变
int main()
{char str[]  hElLo WOrld;char c;int i  0;while (str[i]){char c  str[i];if (islower(c))c - 32;putchar(c);i;}return 0;
}我们来看这段代码1. 其中islower就是判断字母是小写如果是小写那么减去32小写字母ASCII 97–122减去32 → 大写字母ASCII 65–90如果是大写就不进去if内部。 2. putchar输出转换后的字符或原大写字符到标准输出。 3. 循环条件str[i] 检查当前字符是否为非零即非 \0遇到结束符时终止 4. char c 声明字符变量用于存储单个字符将 str[i] 的值字符复制到变量 c 中二者内存独立修改 c 不影响原字符串 
方法二利用字符转换函数 
代码如下 
//练习1将字符串中的小写字母改成大写字母其他不变
int main()
{char str[]  hElLo WOrld;char c;int i  0;while (str[i]){char c  str[i];c  toupper(c);putchar(c);i;}return 0;
}此时就不需要判断了如果加了判断也是ok的这样就能把字符进行大写化 toupper就是to upper往上-大写。 tolower就是to lower往下-小写。 
一. 重要的字符函数 
1. strlen函数 
1. 1.strlen 函数的使用 strlen是库函数本质是通过计算字符串里面的\0前面的字符的个数他是可以用来计算字符串但是不能用来计算字符数组的一般字符数组里面不含\0 同时返回值是一个无符号数需要打印的话使用%zd传入字符串的首地址就ok 
1.2 . strlen函数的模拟 
代码如下 
size_t my_strlen(char* c)
{int count  0;while (*c){count;c;}return count;
}int main()
{char* c  helso;int ret  my_strlen(c);printf(%zd, ret);
}还可以做一下稍微的改进 
size_t my_strlen(char* c)
{int count  0;while (*c){count;}return count;
}int main()
{char* c  helsole;size_t ret  my_strlen(c);printf(%zd, ret);
}先来看这个第二个代码的while循环 
*c 包含两步操作 *c**解引用指针 c获取当前字符的值。c指针后移指向下一个字符副作用发生在解引用之后。   
可以详细看这张图标来完成。我们还可以继续尝试递归的方式还有 
#includeassert.h
size_t my_strlen(const char* str)
{assert(str);if (*str  \0)return 0;elsereturn 1  my_strlen(str  1);
}int main()
{char a[]  heijos;size_t ret  my_strlen(a);printf(%zd, ret);
}2.strcpy函数 
2.1 strcpy的使用 
C 库函数 **char *strcpy(char dest, const char src) 把 src 所指向的字符串复制到 dest。 该函数返回一个指向最终的目标字符串 dest 的指针。  
cpy顾名思义就是靠拷贝函数将原字符串拷进目标字符串src–dest,需要注意的是 需要注意的是如果目标数组 dest 不够大而源字符串的长度又太长可能会造成缓冲溢出的情况同时原来的字符串也是以‘\0’结尾。\0也会被复制 
#includestring.h
int main()
{char* c  copy to d;char d[10]  { 0 };strcpy(d, c);printf(%s, d);
}网址给出的案例 
最后结果 
strcpy代码模拟 
我们尝试模拟代码如下 
char* my_strcpy(char* dest, const char* str)
{int tmp  dest;while (*str){*dest  *str;dest;str;}return dest;
}#includestring.h
int main()
{char* c  copy to d;char d[10]  { 0 };my_strcpy(d, c);printf(%s, d);
}这段代码就完成了复制我们还可以做一下改进 
char* my_strcpy(char* dest, const char* str)
{int tmp  dest;while (*dest  *str);return dest;
}#includestring.h
int main()
{char* c  copy to d;char d[10]  { 0 };my_strcpy(d, c);printf(%s, d);
}以下分步拆解首次循环逻辑假设 str 初始指向字符串 copy to d 的首字符 c 
步骤操作指针状态**dest 赋值结果**1. while (*str) 检查先取 *str 的值c非零 → 条件为真 → **再执行 str**str 指向 o未执行赋值2. 进入循环体执行 *dest  *strstr 仍指向 odest[0]  o3. dest目标指针后移dest 指向下一个位置- 
关键问题 
首字符 c 被完全跳过条件判断时检查了 *strc但 str 在进入循环体前已执行导致循环内 *str 实际指向的是第二个字符 o。**dest[0] 未被覆盖因初始化为 0char d[10]  {0}且未被赋值 → 首字节仍是 \0导致 printf 输出空字符串。 你的问题直指C语言中后置自增运算符*str的核心陷阱**它会在判断条件后立刻移动指针导致循环内操作错位。以下是详细分析 问题核心while (*str) 的执行顺序 
以下分步拆解第二段代码的首次循环逻辑假设 str 初始指向字符串 copy to d 的首字符 c 
步骤操作指针状态**dest 赋值结果**1. while (*str) 检查先取 *str 的值c非零 → 条件为真 → **再执行 str**str 指向 o未执行赋值2. 进入循环体执行 *dest  *strstr 仍指向 odest[0]  o3. dest目标指针后移dest 指向下一个位置- 
关键问题 
首字符 c 被完全跳过条件判断时检查了 *strc但 str 在进入循环体前已执行导致循环内 *str 实际指向的是第二个字符 o。**dest[0] 未被覆盖**因初始化为 0char d[10]  {0}且未被赋值 → 首字节仍是 \0导致 printf 输出空字符串。 
⚠️ 对比三种自增写法的差异 
以下对比你提供的三版代码中 while 条件的行为 
代码版本**while 条件**行为是否复制首字符第一段while (*str)检查当前字符非 \0不自增指针 → 循环内复制当前字符✅ 是第二段while (*str)检查后立刻自增 → 循环内复制的是下一个字符❌ 否跳过首字符第三段while (*dest  *str)先复制当前字符包括 \0再自增 → 完整复制✅ 是 核心区别后置自增i在表达式中“先返回值再自增”导致条件判断和循环内操作使用的指针位置不同步 3.strcat函数 
3.1 strcat函数的使用 
C 库函数 **char *strcat(char dest, const char src) 把 src 所指向的字符串追加到 dest 所指向的字符串的结尾  
该函数返回一个指向最终的目标字符串 dest 的指针。 两个字符串要求以\0结尾。 正确代码如下 
int main()
{char c[22]  i like;char* b   you;strcat(c, b);printf(%s, c);
}避免出现目标空间不够会出先错误。 
3.2 strcat的模拟实现 
通过观察我们做出以下代码 
char* my_strcat(char* dest, char* str)
{char *tmp  dest;while (*dest);dest--;while ((*dest  *str));return tmp;
}int main()
{char c[22]  i like;char* b   you;my_strcat(c, b);printf(%s, c);
}为什么有dest– 
在 C 语言的字符串操作中while (*dest) 这种循环是定位目标字符串末尾的常见写法但它的执行逻辑会导致 dest 指针最终指向 \0 之后的位置而非 \0 本身。以下是详细分析 **while (*dest) 的执行机制** 
假设目标字符串 dest 为 i like存储在数组 c[22] 中其内存布局如下\0 在索引 6 处 
索引01234567…字符ilike\0?… 
循环的执行步骤如下 
**检查条件 *dest** 若 *dest 非 \0条件为真进入循环体但此循环无显式循环体仅执行指针自增。 **执行自增 dest** 后置自增先返回 dest 的当前值再将 dest 指向下一位置。 **重复直到遇到 \0** 当 dest 指向 c[6]\0时 条件 *dest 为 0假但自增仍会执行 → dest 移动到 c[7]。 因此dest–是必须要有的。   
4.strcmp函数 
4.1strcmp的使用 
顾名思义就是比较两个字符串的大小  
我们先说以下cmp的比叫方式 字符串通过标准库函数 strcmp() 实现比较核心逻辑为 
逐字符ASCII值对比从首字符开始逐个比较字符的ASCII值终止条件 遇到不相同的字符 → 返回两字符ASCII差值正数/负数。遇到 \0 结束符 → 若长度不同短字符串较小否则相等返回0 ![[Pasted image 20250613170755.png]] 使用说明代码如下  
int main()
{char c[22]  i like;char* b   you;int ret  strcpmy(c, b);if (ret  0)printf(一样大);if (ret  0)printf(c  b);else {printf(c  b);}
}4.2.strcmp的模拟实现 
第一次尝试而写的错误代码没有考虑到\0,就是str的结束 
int my_strcmp(const char *str1,const char * str2 )
{while (*str1 - *str2  0){str1;str2;}return *str1 - *str2;
}int main()
{char c[22]  i like;char* b   you;int ret  my_strcmp(c, b);if (ret  0)printf(一样大);if (ret  0)printf(c  b);else {printf(c  b);}
}改进过后的代码就有 
int my_strcmp(const char *str1,const char * str2 )
{while (*str1 ! 0  *str1 - *str2  0){//只有未到达/0时才继续str1;str2;}return *str1 - *str2;//当到达0时一定比没到到达的小这样比较出来了
}int main()
{char c[22]  i like;char* b   you;int ret  my_strcmp(b,c);if (ret  0)printf(一样大);if (ret  0)printf(c  b);else {printf(c  b);}
}