C语言字符串基本操作
在 C 语言中,字符串是由数字、字母、下划线组成的一维字符数组,并且使用 null 字符 '\0' 作为终止符号。字符串在存储上类似字符数组,所以它每一位的单个元素都是可以提取的,如s=“abcdefg”,则s[0]=“a”,s[1]="b"。
字符实际上是以对应的ASCII数值的形式在内存中存储的。 对一个字符强制转换成int类型,得到的就是该字符的ASCII码。
字符与字符相减,其实就是它们对应的ASCII码相减,得到的是它们的ASCII码之间相差的距离。
C中函数返回字符串的4种方法
函数返回字符串的两个条件 1. 返回一个字符串地址(首地址), 2. 保证这块地址的内存空间不会随着函数退出而销毁
1.将字符串指针作为函数参数传入,并返回该指针
2.使用malloc申请的堆空间,返回申请的堆地址,注意释放
3.返回一个static定义的静态局部变量
4.使用全局变量
1. 将字符串指针作为函数参数传入,并返回该指针
这种方法一般在函数内复制一份该字符串指针的首地址,通过它操作首地址指向的元素,及其后边的元素,这样操作 就相当于直接操作原始字符串内容。例如strcpy函数:
char* strcpy(char* des,const char* source)
{
char* r=des;
assert((des != NULL) && (source != NULL));
while((*r++ = *source++)!='\0');
return des;
}
2. 使用malloc函数动态分配内存,函数可以返回该内存地址
malloc申请的内存位于堆上,不会被系统自动释放掉,可以从函数中返回,但是切记要在主调函数中使用free主动释放该空间。
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
char * return_Pchar_malloc()
{
char * str2;
str2 = (char *)malloc(10);
strcpy(str2,"Hello!");
return str2;
}
int main()
{
char * str1;
str1 = return_Pchar_malloc();
printf("%s\n",str1);
//记住一定要用free释放,否则会造成内存泄露
free(str1);
return 0;
}
3. 返回一个静态局部变量
使用static修饰的静态变量存放位置是在全局数据区,在主程序运行的整个生命周期中都存在,不会随着函数的退出而销毁。
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
char * return_Pchar_static()
{
static char str2[10];
strcpy(str2,"Hello!");
return str2;
}
int main()
{
char * str1;
str1 = return_Pchar_static();
printf("%s\n",str1);
return 0;
}
4. 使用全局变量
全局变量是老大,没啥说的。
那么可否在函数中返回一个常量字符串指针?如下:
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
char* return_pstr(){
char* str = "HELLO";
return str;
}
int main(){
char * str = return_pstr();
printf("%s\n",str);
}
答案是可以的,但也是危险的!
字符常量位于静态数据区里的文字常量区,生命周期是整个函数,但是字符常量是只读的,任何尝试修改字符常量的操作都会导致运行错误。
1. 数字转换成字符串、 字符串转换成数字
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
//数字转换成字符串
void itoa(int num,char* str){
int i=0,length=0,temp=0;
while(num>0){
str[i]=num%10+'0'; //数字+'0'转换成字符
i++;
num=num/10;
}
str[i]='\0';
length = strlen(str);
//字符逆序,注意终止条件是长度的一半
for(int j=0;j<length/2;j++){
temp = str[j];
str[j] = str[length-j-1];
str[length-j-1] = temp;
}
}
//字符串转换成数字
int char_to_num(char* str){
int i=0, temp = 0;
while(str[i]){
temp = temp*10+(str[i]-'0');
i++;
}
return temp;
}
int main(){
int num = 12343245;
int c_n;
char str[10];
itoa(num,str);
c_n = char_to_num(str);
printf("%s\n",str);
printf("%d\n",c_n);
return 0;
}
2. 实现 strcpy 字符串复制
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
//实现两个字符串复制
char* strcpy_(char* strS, char* strT){
char* temp = strT;
if(strS==NULL||strT==NULL){return NULL;}
while((*temp++=*strS++)!='\0');
return strT; //返回的是字符串首地址
}
int main(){
char strS[6]="12345";
char strT[6];
char* ss;
ss = strcpy_(strS,strT);
printf("%s\n\n",ss);
printf("%s\n",strT);
return 0;
}
3. 字符串循环右移n位
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
//字符串循环移动n位
char* strCir(char* str, int n){
int length = strlen(str);
char* temp=(char*)malloc(length+1);
n =n%length;
for(int i=0;i<length;i++){
int move = i+n;
if(move>=length){
move=move%length;
}
temp[move]=str[i];
}
temp[length]='\0';
return temp; //返回的是字符串首地址
}
int main(){
char str[]="ABCDEFG12345";
char* str_right = strCir(str,8);
printf("%s\n\n",str);
printf("%s\n",str_right);
free(str_right); //记得释放malloc内存
return 0;
}
4. 字符串逆序,以单词为单位逆序
如给定字符串“This is a sentence”,转换成"sentence a is This"。
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
//反转区间字符串
void reverse_Str(char* left, char* right){
while(left<right){
char temp = *left;
*left = *right;
*right = temp;
left++;
right--;
}
}
//字符串以单词为单位逆序
char * str_reverst(char * str, char key){
if(str==NULL){return str;}
char* start=str, *end=str, *kstr=str;
while((*++end)!='\0');
end--;
reverse_Str(start,end); //整个字符串逆序
while(*start!='\0'){
if(*start==key){
reverse_Str(kstr,start-1); //对中间单词逆序
kstr=start+1;
}
start++;
}
reverse_Str(kstr,start-1); //对最后一个单词逆序
return str;
}
int main(){
char str[45]="ABC DE FG B HIGK";
char* str_reverse = str_reverst(str,' ');
printf("%s\n",str_reverse);
return 0;
}
5. 求母串中子串出现的次数
如"abcrtabc"中字串"abc"出现的次数是2。
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
//子串出现次数
int count(char* str, char *str_son){
if(*str=='\0'||*str_son=='\0'){return 0;}
char* s0, *s1;
int amount = 0;
while(*str!='\0'){
s0 = str; s1 = str_son;
while((*s0==*s1)&&(*s0!='\0')&&(*s1!='\0')){
s0++; s1++;
}
if(*s1=='\0'){
amount+=1;
}
str++;
}
return amount;
}
int main(){
char str[]="abcrtabc";
printf("%d\n",count(str,"abc"));
return 0;
}
6. 查找第一个匹配字串的起始位置
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
//首个匹配字串的起始位置
int position(char* str,int n, char *str_son,int n_son){
if(*str=='\0'||*str_son=='\0'){return -1;}
if(n<=0||n_son<=0||n_son>n){return -1;}
int i=0;
for(;i<n-n_son;i++){
if(*str!=(*str_son)){
str++;
}
else{
for(int j=0;j<n_son;j++){
if(str[j]!=str_son[j]){
break;
}
}
return i;
}
}
return -1;
}
int main(){
char str[]="abcdefghigklmn";
printf("%d\n",position(str,strlen(str),"klm",strlen("klm")));
return 0;
}
7. 求两个字符串的最大公共子串
给定字符串A和B,输出A和B中的最大公共子串。比如A="aocdfe" B="pmcdfa" 则输出"cdf"
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
//两个字符串的最大公共字串(重要)
char* max_sub_str(char* str1,int str1_l, char* str2, int str2_l){
char* max_sub = (char*)malloc(100*sizeof(char));
char* max_sub_help = (char*)malloc(100*sizeof(char));
int p_str1,p_str2,p_str_help;
for(int i=0;i<str1_l;i++){ //最好先判断哪个str长
for(int j=0;j<str2_l;j++){
p_str1 = i;
p_str2 = j;
while(str1[p_str1]==str2[p_str2]){
max_sub_help[p_str_help]=str2[p_str2];
p_str1++;
p_str2++;
p_str_help++;
}
if(strlen(max_sub_help)>strlen(max_sub)){
strcpy(max_sub,max_sub_help);
}
p_str_help=0;
}
}
free(max_sub_help);
return max_sub;
}
int main(){
char str[]="abcdefg";
char* sub_str = max_sub_str(str,7,"efghi",5);
printf("%s\n",sub_str);
free(sub_str);
return 0;
}