字符串函数_1

字符串的表示方法及输出

首先要说的是C语言中没有字符串string这样的数据类型,所以我们要表示字符串,可以使用字符数组,不过,输出字符串时,必须用%s来输出,下面举个例子

1

# include <stdio.h>

int main(void) {
	char a[9] = {'g', 'o', 'o', 'd', '!', '\0'};//表示字符数组,可以事先指定数组长度,也可以像下面的代码一样,不指定数组长度 
	char b[] = {'C', 'o', 'n', 's', 'o', 'l', 'e', '\0'};
	
	printf("%s\n%s\n", a, b); 
	
	return 0;
} 

输出结果为:


需要说明的是,用字符数组表示字符串,在字符数组的末尾必须加上\0,如果不加,那字符数组就是仅仅表示多个字符,而不是表示字符串,像上面的那个程序,如果把两个数组里的’\0’去掉,则输出结果会变成这样:


当然,出现的乱码可能会在进行新的执行时有所改变


在对以字符数组表示的字符串赋初值的时候,还可以使用双引号,示例如下

2

# include <stdio.h>

int main(void) {
	char a[9] = "good!";
	char b[] = "Console";
	printf("%s\n%s\n", a, b); 
	
	return 0;
} 

输出结果为:


需要指出的是,此时数组内仍包括这’\0’这个字符,即a数组中有6个元素被赋予初值,b数组内有8个元素,等下面说了一些字符串操作的函数后,会再举例说明的


表示字符串变量,还可以用指针形式表示示例如下

3

# include <stdio.h>

int main(void) 
{
	char * a = "good!";
	char * b = "Console";
	printf("%s\n%s\n", a, b); 
	
	return 0;
} 

输出结果为:


在这个程序中,ab都是指针,56行表示其初始化为一个字符串常量,但是如果需要修改字符串,则需要字符数组

当然,需要注意的是,字符串可以表示为char *形式,但char *不一定是字符串,char *的本意是指向字符的指针,它可能指向字符数组,但只有它指向的字符数组末尾有\0时,它指向的才可以称为字符串

还有,在使用字符指针表示字符串时,需要注意几点,比如说字符串赋值,像下面的代码:

char * s = "good!";

char * t;

t = s; 

这样并没有产生新的字符串,而是让指针t也指向了指针s所指向的字符串,对s的任何操作就是对t的操作,反之亦然

字符串的输入

当使用scanf输入字符串时,scanf会在遇到空格、回车和Tab时,一个输入就会停止,下面举几个例子

4.1

# include <stdio.h>

int main(void)
{
	char a[10];
	printf("请输入一个字符串:\n"); 
	scanf("%s", a);
	printf("输出该字符串为:%s\n", a); 
	
	return 0;
}

示例输出结果为:


输入字符串与输出相同,也是使用%s,这里a不需要使用&,原因在数组那块儿说过了 

另举一个错误的输入结果:


这个是字符串中间加空格的错误,加Tab和回车的例子这里就不说了


scanf在输入字符串时,如果在其%s写成这样——%9s,则表示scanf最多识别输入的9个字符,%s之间最大是数组元素个数减一,多余的字符不会识别,直接舍弃

另外需要注意的是下面的代码是不正确的

char * s;

scanf(“%s”, s);

因为s这个字符指针没有赋初值,所以它指向的位置不确定,有时这样的代码可以正确,但在另一些时候是会出错的,最好不要这么写

char a[10] = “”,这是个空字符串,其内部只有一个元素\0,即a[0] = ‘\0’,如果这样,char a[] = “”,那该数组的长度就会是1

字符串数组

我们用字符数组表示字符串,那又需要什么表示字符串数组呢?可以这样,char ** aa是一个指针,它指向另一个指针,而这个所谓的“另一个指针”指向一个字符或字符串;也可以这样char a[][],使用二维数组表示,当然,使用二维数组时,第二个维必须有确定的大小,如果没有,则会出错,举个例子

4.2

# include <stdio.h>

int main(void)
{
	char a[][9] = {"good", "morning"};
	
	return 0;
} 

第五行表示一个数组a,其元素都是char [9],即a[0]可表示为一个长度为9的字符数组,a[1]a[2]等等皆是如此

表示字符串数组,还可以这样,char * a[],其中,a[0]等元素是char *类型,即数组元素分别是a[0]a[1]等等,每个元素其实是一个指向字符或字符串的指针,它和上面的char a[][]是不一样的

还有在使用编译器新建一个工程,选择控制台应用程序,下一步后再选择新建一个简单的程序,就会出现这样的代码:main(int argc, char *argv[]),在mian函数中有两个参数,一个是整数参数argc,一个是字符串数组参数argv,这个整数表示字符串数组的长度,下面用一个简单的程序查看一下这个字符串数组的内容

4.3

#include <stdio.h>

int main(int argc, char *argv[])
{
	int i;
	for (i=0; i<argc; i++)
	{
		printf("%d:%s\n", i, argv[i]);
	}
	
	return 0;
}

C-Free5.0下的输出结果为:

其中C:\Users\CC\Desktop\sss\mingw5\sss.exe是可执行文件所在的路径

gcc下运行的结果为:

如果在./test后边加空格后添加其他字符,则会出现这样的情况:

argv接收的是命令后面的字符串,前边的012等是argc所获取的值


单个字符的输入及输出函数,输入单个字符需要用的getchar()函数,输出需要用到putchar()函数,

int getchar(void);

从标准输入都一个字符

返回类型是int是为了返回EOF(-1)

结束程序:

Windows下——Ctrl+Z

Linux下——Ctrl+D


int putchar(int c);

向标准输出写一个字符

返回值为写了几个字符的个数,EOF(-1)表示写失败

举例如下

5

# include <stdio.h>

int main(int argc, char const *argv[])
{
	int ch;
	
	while ((ch = getchar()) != EOF)
	{
		putchar(ch);
	}
	printf("鸟哥的LINUX私房菜\n");
	
	return 0;
} 

输入什么字符或字符串就会原样输出,当然,是一个个输入,最终一个个输出,windows环境下只有Ctrl+Z才能正常结束程序(说正常结束,是因为按Ctrl+C也可以直接结束程序,但这种结束不是正常的,像下面的printf语句不会被执行,而正常结束是会执行的,Ctrl+C适用于windowsLinux系统)

字符串操作函数

C语言在标准库中提供了一些对字符串进行操作的函数,这些函数的原型都在string.h头文件中,即在使用这些函数时,需要加# include <string.h>

strlen函数

size_t strlen(const char * s);

功能是获取字符串的长度

返回的是字符串的长度(不包括结尾的\0

下面举个例子

6

# include <stdio.h>
# include <string.h>

int main(int argc, char const *argv[])
{
	char a[] = "good!";
	
	printf("strlen=%lu\n", strlen(a));
	printf("sizeof=%lu\n", sizeof(a));
	
	return 0;
} 
输出结果为:

C-Free5.0中,对strlen函数

跳至声明,则是这样

_CRTIMP size_t __cdecl __MINGW_NOTHROW strlen (const char*)  __MINGW_ATTRIB_PURE;


我们可以推测出strlen的函数体

其函数体为

size_t strlen(const char * s)
{
	int cnt = 0;
	while (s[cnt] != '\0')
	{
		cnt++;
	}
	return cnt;
}

最终下面这个程序

# include <stdio.h>
# include <string.h>
//设一个函数mylen();
size_t mylen(const char * s)
{
	int cnt = 0;
	while (s[cnt] != '\0')
	{
		cnt++;
	}
	return cnt;
} 

int main(int argc, char const *argv[])
{
	char a[] = "good!";
	
//	printf("strlen=%lu\n", strlen(a));
	printf("strlen=%lu\n", mylen(a));
	printf("sizeof=%lu\n", sizeof(a));
	
	return 0;
} 

得到的结果与使用strlen函数功能相同

strcmp函数

int strcmp(const char * s1, const char * s2);

功能是比较两个字符串

返回值为:

0:当s1 == s2

1:当s1>s2

2:当s1<s2

这个字符串的大小怎么说,举个例子说明一下

7

# include <stdio.h>
# include <string.h>

int main(int argc, char const *argv[])
{
	char a[] = "asd";
	char b[] = "asd";
	char c[] = "bsd";
	char d[] = "Asd";
	char e[] = "asd ";
	
	printf("%d\n", strcmp(a, b));
	printf("%d\n", strcmp(a, c));
	printf("%d\n", strcmp(a, d));
	printf("%d\n", strcmp(a, e));
	
	return 0;
} 

第一次C-Free5.0下输出结果为:

(然而,后来我有进行了几次运行,发现结果竟然和gcc下的结果一样了,不知什么情况,下面的那段文字,是我对一开始两个不同结果的解释,至于为什么C-Free下第一次结果不同,而第二天再次运行时,又出现这样的结果,实在是不清楚,以后若是知道,定会在此说明

gcc下输出的结果为:

两个编译器输出的结果不同,下面一一分析一下:

通过这个例子,我们可以发现,所谓的比较字符串大小,实际上是比较其所有字符的ASCII表的值的大小之和,所不同的是,C-Free只要有大小,只会返回其大小的逻辑值(01-1),而gcc返回的是字符串ASCII表值得总和的差

因为字符串ab相等,所以两个结果返回的都是0;而字符串cASCII值得和比aASCII的值大1,所以gcc返回的是aASCII值减去bASCII值得差,即-1,而C-Free是因为a小于b,所以返回的是-1,这是上面两个结果

这两个值相同的原因;下面,字符串da的不同在于其中一个字符是大写的A,因为小写a和大写AASCII值分别是9765,其差值是32,所以gcc得到的结果是32C-Free得到的结果是1;同理,字符串ea多一个空格,而空格的ASCII值恰好是32,所以gcc得到的是-32C-Free得到的是-1,


下面各处这个函数的函数体

int strcmp(const char * s1, const char * s2)
{
	while (*s1 == *s2 && *s1 != '\0')
	{
		s1++;
		s2++;
	}
	return *s1-*s2;
}

strcpy函数

char * strcpy(char * restrict dst, char * restrict src);

功能是把src的字符串拷贝到dst (即src是源操作数,dst是目的操作数)

restrict表明srcdst不重叠

(注:所谓不重叠,是指二者所占的内存单元之间的间隙必须大于src的字符串长度,即假设src5个字节的内存单元,而dst原来指向的是src所占的5个单元的前面的一个单元,而其到src的首个单元之间的间距小于src所占的单元个数,则dst在复制src的内容时,会占用一部分src原本的内存单元,这个是不被允许的,这个其实是C99的标准)

返回的是dst


经常会这样用

char * dst = (char *)malloc(strlen(src)+1);//1是为了包含数组最后的\0

strcpy(dst, src); 


下面举个例子

8

# include <stdio.h>
# include <string.h>

char * mycpy(char * dst, const char * src)
{
	char * ret = dst;
	while (*dst++ =*src++)
	;
	*dst = '\0';
	return ret;
}

int main(int argc, char const *argv[])
{
	char a[] = "asd";
	char a1[] = "";
	char b[] = "aaa";
	char b1[] = "";
		
	strcpy(a1, a);
	mycpy(b1, b);
	printf("a1=%s\n", a1);
	printf("b1=%s\n", b1);
	
	return 0;
} 

输出结果为:


由以上代码可知,strcpy的函数体即mycpy函数函数体

注:这些函数的函数体不止一种形式,这里仅列出一种


strcat函数

char * strcat(char * restrict s1, const char * restrict s2);

功能是把s2拷贝到s1的后面接成一个长的字符串

返回的是s1

这个函数要求s1必须有足够大的空间

 

所谓的接成新的字符串,假设有两个字符串a[10] = “good”,b =[10] “morning”,要知道数组的末尾是一个0(或者说\0),当对这两个字符串进行strcat函数操作时,b字符串中的m会到达a字符串中的\0位置,然后后面的字符串依次跟过来


无论是strcpy还是strcat,都有一个不安全的地方,就是空间可能不够

下面举个例子

9

# include <stdio.h>
# include <string.h>

char * mycat(char * s1, const char * s2)
{
 	int i, j;
 	i = strlen(s1);
 	j = 0;
 	while(s1[i++] = s2[j++])
	;
 	return s1;
}
 
int main(void)
{
 	char s1[20] = "good ";
 	char s2[] = "morning";
 	char a[20] = "How ";
 	char b[] = "are you";
 	mycat(s1,s2);
 	strcat(a, b);
 	printf("%s\n", s1);
 	printf("%s\n", a);
  
 	return 0;
}

输出结果为:

由上可知,strcat的函数体为:

char * strycat(char * s1, const char * s2)
{
 	int i, j;
 	i = strlen(s1);
 	j = 0;
 	while(s1[i++] = s2[j++])
	;
 	return s1;
}

当然,有安全的函数,情况是这样的

char * strncpy(char * restrict dst, const char * restrict src, size_t n);

char * strncat(char * restrict s1, const char * restrict s2, size_t n);

这个n表示最多拷过去(连接)n个字符,如果有多余,或将多余的字符忽视

int strncmp(const char * s1, const char * s2, size_t n);

对于strcmp来说,n的存在是为了判断是比较几个字符,假如我们想看一下某个字符串的前几位是不是和另一个字符串相同,就可以用

n来控制字符个数


字符串搜索函数

char * strchr(const char * s, int c);//从左往右找

char * strrchr(const char * s, int c);//从右往左找

返回NULL表示没有找到


举个例子

10

# include <stdio.h>
# include <string.h>

int main(int argc, char const *argv[])
{
	char a[] = "good";
	char * p = strchr(a, 'o');
	
	printf("%s\n", p);
	
	return 0;
} 

输出结果为:

需要注意的是,在good这个单词中,o有两个,我们这个程序查到的是第一个,那么,如何查到第二个o呢?只需在上个程序的第八行添加这样的语句:p = strchr(p+1, 'o'); 即可

如果想把查到的后面的字符串复制到另一个字符串里边,可以这样做

11

# include <stdio.h>
# include <string.h>
# include <stdlib.h>

int main(int argc, char const *argv[])
{
	char a[] = "good";
	char * p = strchr(a, 'o');
	
	char * t = (char *)malloc(strlen(p)+1);
	strcpy(t, p);
	printf("%s\n", t);
	free(t);
//	p = strchr(p+1, 'o');
//	printf("%s\n", p);
	
	return 0;
} 

输出结果同例10

这个是输出了所查到的字符后面的字符串,那如何输出所查到字符的前边的字符串呢?可以这样

12

# include <stdio.h>
# include <string.h>
# include <stdlib.h>

int main(int argc, char const *argv[])
{ 
	char a[] = "good";
	char * p = strchr(a, 'o');
	char c = *p;
	*p = '\0'; 
	char * t = (char *)malloc(strlen(a)+1);
	strcpy(t, a);
	printf("%s\n", t);
	free(t);
	
	return 0;
} 

输出结果为:


【所有代码均在windows系统下C-Free5.0下运行通过】

(如有错误,敬请指正)

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值