C语言基础练习:13个核心字符串与数据处理函数封装实战
本文详细整理了C语言中常见的字符串处理与数据转换函数封装案例,包括闰年判断、字符串查找替换、类型互转及GPS数据解析等13个经典实例,帮助读者掌握指针操作与底层算法逻辑。
封装函数:判断闰年与平年
该函数通过返回值区分传入年份的属性。逻辑上,若年份能被4整除且不能被100整除,或者能被400整除,则为闰年。本例约定返回0表示闰年,返回1表示平年。
#include <stdio.h>
// 函数声明
int GetYearSate(int year);
int main()
{
int year;
printf("请输入年份:");
scanf("%d",&year);
// 根据返回值判断结果
if(GetYearSate(year))
{
printf("平年.\n");
}
else
{
printf("闰年.\n");
}
return 0;
}
/*
函数功能: 判断平年闰年
返回值: 0表示闰年 1表示平年
*/
int GetYearSate(int year)
{
if((year%4==0 && year%100!=0)||(year%400==0))
{
return 0;
}
return 1;
}
封装函数:字符串查找(参考strstr)
自定义 `my_strstr` 函数用于在源字符串中查找目标子串的首地址。操作时需引入 <string.h> 以使用 strlen,并建议通过 man strstr 查阅标准库手册了解接口规范。
#include <stdio.h>
#include <string.h> // 需包含此头文件
char *my_strstr(char *src_str,char *find_str);
int main()
{
char src_str[100];
char find_str[100];
printf("请输入源字符串:");
scanf("%s",src_str);
printf("请输入查找的字符串:");
scanf("%s",find_str);
// 对比系统函数与自定义函数的输出
printf("系统strstr结果:%s\n",strstr(src_str,find_str));
printf("自定义my_strstr结果:%s\n",my_strstr(src_str,find_str));
return 0;
}
// 函数功能: 字符串查找
// 返回值: 找到返回首地址,未找到返回NULL
char *my_strstr(char *src_str,char *find_str)
{
int src_len;
int find_len;
int i,j;
src_len=strlen(src_str);
find_len=strlen(find_str);
for(i=0;i<src_len;i++)
{
for(j=0;j<find_len;j++)
{
if(src_str[i+j]!=find_str[j])break;
}
// 若内层循环完整执行,说明匹配成功
if(j==find_len)
{
return src_str+i;
}
}
return NULL;
}
封装函数:字符串比较(参考strcmp)
手动实现字符串比对逻辑,逐个字符比较ASCII值。当两字符串完全一致时返回0,否则返回1。注意原代码逻辑仅判断相等性,实际应用中可返回差值。
#include <stdio.h>
#include <string.h>
int my_strcmp(char *s1,char *s2);
int main()
{
char str1[100];
char str2[100];
printf("请输入字符串1:");
scanf("%s",str1);
printf("请输入字符串2:");
scanf("%s",str2);
printf("系统strcmp结果:%d\n",strcmp(str1,str2));
printf("自定义my_strcmp结果:%d\n",my_strcmp(str1,str2));
return 0;
}
/*
函数功能: 比较两个字符串是否相等
返回值: 0表示相等 1表示不相等
*/
int my_strcmp(char *s1,char *s2)
{
while(*s1!='\0' && *s2!='\0')
{
if(*s1!=*s2)break;
s1++;
s2++;
}
if(*s1=='\0'&&*s2=='\0')return 0;
return 1;
}
封装函数:字符串拼接(参考strcat)
通过移动指针至源字符串末尾,然后将目标字符串内容逐字节拷贝。需注意缓冲区溢出风险,实际应用应确保目标数组空间充足。
#include <stdio.h>
#include <string.h>
char *my_strcat(char *s1,char *s2);
int main()
{
char str1[100];
char str2[100];
printf("请输入字符串1:");
scanf("%s",str1);
printf("请输入字符串2:");
scanf("%s",str2);
printf("拼接的结果:%s\n",my_strcat(str1,str2));
return 0;
}
char *my_strcat(char *s1,char *s2)
{
char *p=s1; // 记录源字符串的首地址以便返回
while(*s1 != '\0'){s1++;} // 指针偏移到结尾
while(*s2!='\0')
{
*s1=*s2;
s2++;
s1++;
}
*s1='\0'; // 添加结束符
return p;
}
封装函数:字符串转整数(参考atoi)
遍历字符串,识别数字字符后通过乘10累加的方式构建整数。遇到非数字字符即停止转换。未处理符号位与溢出异常,适用于基础教学场景。
#include <stdio.h>
#include <string.h>
int my_atoi(char *str);
int main()
{
char buff[100];
printf("请输入一个整数字符串:");
scanf("%s",buff);
printf("系统atoi转换结果:%d\n",atoi(buff));
printf("自定义my_atoi转换结果:%d\n",my_atoi(buff));
return 0;
}
/*
函数功能: 字符串转整数 (支持正整数)
返回值: 转换后的整数,失败返回0
*/
int my_atoi(char *str)
{
int data=0;
while(*str!='\0')
{
if(*str>='0' && *str<='9')
{
data*=10;
data+=*str-'0';
}
else
{
break;
}
str++;
}
return data;
}
封装函数:字符串转浮点数(参考atof)
分离小数点前后的部分分别处理。整数部分常规累乘,小数部分提取后配合 my_pow 计算幂次进行合成。注意精度限制。
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
double my_pow(double x,int y);
double my_atof(char *str,int cnt);
int main()
{
char buff[100];
printf("请输入一个浮点数字符串:");
scanf("%s",buff);
// cnt为指定保留的小数位数
printf("自定义my_atof转换结果:%lf\n",my_atof(buff,3));
return 0;
}
double my_atof(char *str,int cnt)
{
int data_int=0;
int data_frac=0;
double result=0.0;
int cnt_f=0;
// 1. 处理整数部分
while(*str!='\0' && *str!='.')
{
if(*str>='0' && *str<='9')
{
result*=10;
result+=*str-'0';
}
else break;
str++;
}
if(*str == '.') str++; // 跳过 "."
// 2. 处理小数部分
while(*str!='\0' && cnt_f!=cnt)
{
if(*str>='0' && *str<='9')
{
data_frac*=10;
data_frac+=*str-'0';
cnt_f++;
}
else break;
str++;
}
// 3. 合成结果
int actual_cnt = (cnt > cnt_f) ? cnt_f : cnt;
result += data_frac * my_pow(0.1, actual_cnt);
return result;
}
double my_pow(double x,int y)
{
double tmp=1.0;
int i;
for(i=0;i<y;i++)
{
tmp=tmp*x;
}
return tmp;
}
封装函数:整数转字符串
通过取余分离每一位数字存入临时数组,随后逆序拷贝至目标字符串。此方法简单有效,未处理负号情况。
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
void int_to_str(char *str,int data);
int main()
{
int data;
char buff[100];
printf("请输入一个整数:");
scanf("%d",&data);
int_to_str(buff,data);
printf("转换结果: %s\n",buff);
return 0;
}
void int_to_str(char *str,int data)
{
char temp_buf[100];
int i=0;
int j=0;
if(data == 0) {
str[0] = '0';
str[1] = '\0';
return;
}
while(data)
{
temp_buf[i]=data%10+'0';
data=data/10;
i++;
}
// 逆序放入目标字符串
for(j=0;j<i;j++)
{
str[j]=temp_buf[i-1-j];
}
str[j]='\0';
}
封装函数:浮点数转字符串
将浮点数拆分为整数和小数两部分独立转换,中间插入小数点连接。涉及辅助幂函数计算小数权重。
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
int my_pow_int(int x,int y);
void double_to_str(char *str,double data_f,int cnt);
int main()
{
double data;
char buff[100];
printf("请输入一个浮点数:");
scanf("%lf",&data);
double_to_str(buff,data,5);
printf("转换结果: %s\n",buff);
return 0;
}
void double_to_str(char *str,double data_f,int cnt)
{
char temp_buf[50];
int i=0, n=0, j=0;
int data_i_part = (int)data_f;
double temp_f = data_f - data_i_part;
int data_frac_part = (int)(temp_f * my_pow_int(10,cnt));
// 1. 转换整数部分
while(data_i_part)
{
temp_buf[i]=data_i_part%10+'0';
data_i_part=data_i_part/10;
i++;
}
for(j=0;j<i;j++)
{
str[j]=temp_buf[i-1-j];
}
str[j]='.';
// 2. 转换小数部分
while(data_frac_part)
{
temp_buf[n]=data_frac_part%10+'0';
data_frac_part=data_frac_part/10;
n++;
}
for(j=0;j<n;j++)
{
str[j+i+1]=temp_buf[n-1-j];
}
str[j+i+1]='\0';
}
int my_pow_int(int x,int y)
{
int tmp=1;
for(int i=0;i<y;i++) tmp*=x;
return tmp;
}
封装函数:判断回文字符串
利用双指针思想,从两端向中间靠拢比较字符。若任意位置字符不匹配则立即跳出,若遍历完成无差异则为回文。
#include <stdio.h>
#include <string.h>
int func_is_palindrome(char *p);
int main()
{
char buff[100];
printf("输入字符串:");
scanf("%s",buff);
if(func_is_palindrome(buff))printf("是回文.\n");
else printf("不是回文.\n");
return 0;
}
int func_is_palindrome(char *p)
{
int len = strlen(p);
for(int i=0; i<len/2; i++)
{
if(p[i]!=p[len-1-i]) return 0;
}
return 1;
}
封装函数:字符串替换
较复杂的逻辑:先定位子串,再根据源串与替换串长度差值,决定向前压缩还是向后扩展内存,最后填充新内容。注意数组边界检查在实际生产中必不可少。
#include <stdio.h>
#include <string.h>
void str_replace(char *str1, char *str2, char *str3);
int main()
{
char str1[100] = "123A789";
char str2[100] = "A";
char str3[100] = "XX";
str_replace(str1, str2, str3);
printf("替换结果: %s\n", str1);
return 0;
}
void str_replace(char *str1, char *str2, char *str3)
{
int len1 = strlen(str1);
int len2 = strlen(str2);
int len3 = strlen(str3);
for(int i=0; i<len1; i++)
{
// 查找匹配
bool match = true;
for(int j=0; j<len2; j++)
{
if(str1[i+j] != str2[j]) { match=false; break; }
}
if(!match || i+len2 > len1) continue;
// 处理长度差异导致的移位
if(len2 > len3)
{
int diff = len2 - len3;
for(int k=i+len2; k<len1; k++)
str1[k-diff] = str1[k];
str1[len1-diff]='\0';
len1 -= diff;
}
else if(len2 < len3)
{
int diff = len3 - len2;
for(int k=len1; k>=i+len2; k--)
str1[k+diff] = str1[k];
str1[len1+diff]='\0';
len1 += diff;
}
// 写入新内容
for(int j=0; j<len3; j++)
str1[i+j] = str3[j];
// 修正当前索引继续搜索
i += len3 - 1;
}
}
封装函数:清除二维数组的指定行
演示如何通过指向数组的指针访问二维矩阵,并将指定行的所有元素重置为特定值。
#include <stdio.h>
void clear_row(int (*p)[5], int val, int row_idx);
int main()
{
int buff[][5]=
{{1,2,3,4,5},
{11,12,13,14,15},
{21,22,23,24,25}};
printf("源数据:\n");
for(int i=0; i<3; i++)
for(int j=0; j<5; j++)
printf("%d ", buff[i][j]);
printf("\n");
clear_row(buff, 888, 1); // 清除第2行(索引1)
printf("清除之后:\n");
for(int i=0; i<3; i++)
for(int j=0; j<5; j++)
printf("%d ", buff[i][j]);
printf("\n");
return 0;
}
void clear_row(int (*p)[5], int val, int row_idx)
{
for(int i=0; i<5; i++)
p[row_idx][i] = val;
}
封装函数:字符串大小写互换
通过 ASCII 码偏移量(大写与小写相差32)实现转换。传入标志位 `flag` 区分方向:0为大转小,1为小转大。
#include <stdio.h>
#include <string.h>
void swap_case(char *str, int flag);
int main()
{
char buff[100];
printf("输入字符串:");
scanf("%s",buff);
swap_case(buff, 0); // 大写转小写
printf("Result1: %s\n", buff);
swap_case(buff, 1); // 小写转大写
printf("Result2: %s\n", buff);
return 0;
}
void swap_case(char *str, int flag)
{
while(*str!='\0')
{
if(flag)
{
if(*str>='a' && *str<='z')
*str = *str - 32; // 小 -> 大
}
else
{
if(*str>='A' && *str<='Z')
*str = *str + 32; // 大 -> 小
}
str++;
}
}
封装函数:GPS NMEA数据解析
针对 GPS 模块输出的 NMEA 协议字符串,通过查找特定指令头(如 $GNGGA),按逗号计数定位字段位置,提取经纬度或时间数据。
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
int GPS_GetData(const char *gps_src, const char *find_head, char *buff, int field_idx);
int main()
{
const char gps_buff[] = "$GNGGA,114955.000,2842.4158,N,11549.5439,E,1,05,3.8,54.8,M,0.0,M,,*4F";
char buff[100];
// 提取纬度 (通常在$GNGGA的第2域,具体依协议而定)
GPS_GetData(gps_buff, "$GNGGA", buff, 2);
printf("纬度字段: %s\n", buff);
return 0;
}
/*
函数功能: 提取NMEA字符串中指定域的字段
参数: gps_src源串, find_head指令头, buff接收缓冲, field_idx目标逗号序号
返回值: 提取到的字符数
*/
int GPS_GetData(const char *gps_src, const char *find_head, char *buff, int field_idx)
{
const char *p = strstr(gps_src, find_head);
if(p == NULL) return 0;
p += strlen(find_head);
int commas = 0;
while(*p != '\0' && commas < field_idx)
{
if(*p == ',') commas++;
if(commas == field_idx) break;
p++;
}
if(commas < field_idx) return 0;
p++; // 跳过当前逗号
int count = 0;
while(*p != '\0' && *p != ',')
{
buff[count++] = *p;
p++;
}
buff[count] = '\0';
return count;
}
封装函数:十进制转十六进制字符串
利用除基取余法,将余数映射到 0-F 字符表,最后逆序输出。
#include <stdio.h>
int main()
{
int number = 255;
char hex_chars[] = {'0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F'};
char result[100];
int i=0;
do {
result[i++] = hex_chars[number % 16];
number /= 16;
} while(number > 0);
printf("0x");
for(int j=i-1; j>=0; j--)
printf("%c", result[j]);
printf("\n");
return 0;
}
以上就是C语言字符串处理与基础算法封装的详细内容,更多关于C语言指针与内存管理技巧的资料请关注本站其它相关文章!本站声明
本文内容仅供参考,不代表本站观点。转载或引用请注明出处。如发现内容问题,请通过联系我们页面反馈。













