C基础函数的使用

Posted mChenys

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了C基础函数的使用相关的知识,希望对你有一定的参考价值。

目录

一、库函数的使用

1.1 随机数rand与srand

对应的头文件是stdlib.h,Rand是伪随机数产生器,每次调用rand产生的随机数是一样的,如果调用rand之前先调用srand就出现任意的随机数。

只要能保证每次调用srand函数的时候,参数的值是不同的,那么rand函数就一定会产生不同的随机数, 通常会传一个时间作为srand的参数. 这样rand的值就是随机不重复的。

由于生成的随机数的范围是不定的, 那么通常会采用取摸的方式来规定范围,例如 生产0-100之间的随机数,那么可以和101取余。

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

int main()


	int t = (int)time(NULL); //获取距1970的系统时间,单位s ,需要导入time.h头文件
	printf("t=%d\\n",t);

	srand(t);//先调用srand

	int i;
	for(i=0;i<10;i++)
	
		int r=rand(); //再调用这个生产随机数
		printf("r=%d,sr=%d\\n",r,r%11);
	

	return 0;


结果:

1.2 scanf函数

通过scanf("%s",a); 可以把用户输入的字符串写到char数组中, 由于a是数组名, 已经表示的是地址了,不用在&a多次一举。

scanf并不会直接读入用户最后输入完成的那个回车键,而是会在最后自动补一个0,这样才是完整的字符串. 用户按空格或回车键都表示输入完成.

#include<stdio.h>
int main()

	char a[100] = 1,2,3,4,5,6,7,8,9,10;
	//接收用户输入
	scanf("%s",a);

	int i;
	for(i=0;i<10;i++)
	
		printf("%d\\n",a[i]);
	
	return 0;

(1)当输入abc回车结果:

说明abc字符串的ASCII= 97 98 99 0 , 末尾的0就是’\\0’

(2)当输入ab c回车结果:

可以看到空格和c被忽略了, 因为scanf遇到空格和遇到回车是一样的效果,表示输入完成。

scanf缓冲区溢出的危险
scanf并不检查参数的char数组的下标,用户输入多少,scanf就往数组里面放入多少,一旦用户输入的过多,会导致内存错误。

1.3 gets函数

用来接收用户输入的字符串的, 参数是字符数组, 仅认回车符表示输入完成,同样和scanf一样存在安全问题(用户输入过多内容会报缓冲区溢出的问题).

#include<stdio.h>

int main()

    char a[10] =0;
    gets(a);
    for(int i=0;i<sizeof(a);i++)
        printf("%d\\n",a[i]);
    
    return 0;

结果如下:

1.4 fgets函数

fgets函数就是解决gets函数的安全缺陷问题的. 但是由于fgets是为读取文件而设计的,所以读取键盘输入时没有gets函数方便 , fgets函数会把用户的回车键也当做字符接收了。
它接收3个参数:
参数一:char数组
参数二: char数组的大小
参数三: 如果是通过键盘输入, 那么可以固定写为 stdin

#include<stdio.h>
int main()

	char a[10] =0;
     // 注意:参数2要填写正确的数组大小, 如果故意填写过大, 也会造成缓冲区溢出的问题
	fgets(a,sizeof(a),stdin);
	printf("%s",a);


结果如下:

虽然用户输入了超过10个字符的长度, 但是实际接收的是9个字符,因为第10元素用来放’\\0’了.

1.5 puts函数

用于打印字符串,与printf不同,puts会在输出结果最后自动加一个’\\n’,无论要输出的字符串末尾是否已有’\\n’了, 而且不支持各种转义字符,比如%d,%s都是不支持的,puts只能简单的直接输出一个字符串,而不能输出char,int,double等其他类型。

#include<stdio.h>
int main()

	char a[] ="hello";
	puts(a); //字符串才可以输出

	char b[] = 0,1,2,3;
	puts(b); //char数组输出不了效果

	return 0;


结果:

1.6 strlen函数

用于求字符串所占的字节长度,使用时需要导入头文件<string.h> , 得到的长度是不包含字符串末尾’\\0’所占的长度。
注意:英文和数字是占1BYTE的长度, 而中文在utf-8是占3BYTE的长度。

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

int main()

	char a[] ="hello世界";
	/*
	unsigned int len =0;
	while(a[len])
	
		len++;
	
	*/

	int len = strlen(a); //效果和上面的一样,都是11,5个英文占5Byte,2个中文占6Byte

	printf("%u\\n",len);


练习-给定一个字符串,求中文出现的次数
思路: 汉字的首个字节的ASCII值是负数, 只需要统计下有多少个首字母是负数的即可。

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

int main()

	char a[] = "abc我ef哈哈12呵呵";

	int len = strlen(a);

	int i;
	int count=0;//统计汉字个数

 	//方式一:
	for(i=0;i<len;i++)
	
		char c = a[i];
		if(c < 0)
		
			count++;
			i+=2;//下标+2,因为utf-8下汉字占3个字节,因此后面2个还是汉字的字节,可以跳过
		
	
	printf("count1=%d\\n",count); // 5
	
	//方式二:
	count=0;
	for(i=0;i<len;i++)
	
		char c = a[i];
		if(c<0)
		
			count++;
		
	
	count/=3;//由于汉字占3个字节,所以每3个字节位一个汉字

	printf("count2=%d\\n",count); // 5
	
	return 0;

	

1.7 strcat函数和strncat函数

字符串追加,接收2个字符串作为参数
例如传入char1 和char2,则char2会追加到char1的末尾. 使用这个函数需要注意第一个字符串需要有足够的空间存放第二个字符串,使用时也需要导入头文件<string.h>。
而strncat在strcat函数的基础上增加了一个参数,用来表示最多可以追加多少个char.

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

int main()

	char a[20] = "abc";
	char b[] = "hello world";

	strcat(a,b); //把字符串b追加到字符串a中
	printf("a1=%s\\n",a); // a1=abchello world


	strncat(a,b,5);//把字符串b追加到字符串a中,同时只追加5个字符

	printf("a2=%s\\n",a);// a2=abchello worldhello

	return 0;


1.8 strcmp和strncmp

strcmp:比较2个字符串是否相等,相等返回0,不等返回非0
strncmp:比较2个字符串的前几个字符是否相同,相等返回0,不等返回非0

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

int main()

	char a[] = "hello";
	char b[] = "hello";

	if(strcmp(a,b)==0)  //0表示相同,非0表示不同
	
		puts("相同");
	else
		puts("不相同");
	



	if(strncmp(a,b,3)==0)
	
		puts("相同");
	else
		puts("不相同");
	

	return 0;

1.9 strcpy和strncpy

strcpy:拷贝字符串,将字符串2拷贝到字符串1中, 会存在内存溢出的问题.
strncpy:拷贝有限个数的字符串, 通常这样使用strncpy(a,b,sizeof(a)-1);表示将字符串b拷贝到字符串a中, 最大可以拷贝的字节长度是a字符串的字节长度-1 , -1是因为保留字符串末尾的’\\0’标识。

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

int main()

	char a[]="hello";
	char b[100]="abcd1234";
	
//	strcpy(a,b);// 这样会有安全问题,超出了a字符串的字节长度
//	printf("a1=%s\\n",a);


	strncpy(a,b,sizeof(a)-1); //a字符串的长度其实是6个BYTE(包含了'\\0'标识)
	printf("a2=%s\\n",a); //a2=abcd1
	return 0;

1.10 sprintf函数

int sprintf(char *str,const char *format,...);
  • 参数:
    str: 字符串首地址
    format: 字符串格式,用法和printf()一样
    参数3: format对应的数据
  • 返回值:
    成功:实际格式化的字符个数
    失败:-1

用于向一个char的数组输出一个字符串。和printf的使用基本一致,区别是多了第一个参数,第一个参数是一个char数组,所有printf的转义符对于sprintf来说是一样的。

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

int main()

	char a[100];
	int i=100;
	//将结果输出到a数组中
	sprintf(a,"%s%d","hello",i);

	printf("%s\\n",a); // hello100
	return 0;

[使用技巧1] 可以利用sprintf拼接多个类型的数据

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

int main()

    char buf[1024] = 0;
    char *str1 = "hello";
    char *str2 = "world";
    int a = 100;
    sprintf(buf, "%s%s%d", str1, str2, a); // helloworld100
    printf("%s", buf);
    return 0;

[使用技巧2] 将数字转字符串

char buf[1024] = 0;
int a = 10;
sprintf(buf,"%d",a);

1.11 sscanf函数

int sscanf(const char *str,const char *fromat,...);
  • 参数:
    str:指定的字符串首地址
    format:字符串格式,用法和scanf()一样
    参数3:输出的目标,是一个可变参数
  • 返回值:
    成功:实际读取的字符个数
    失败:-1

类似与scanf,scanf是从键盘读取用户输入,而sscanf是从指定字符串读取输入数据。它多了第一个参数,char的数组,sscanf会从这个char数据中读取相关内容。

#include<stdio.h>

int main()

	char a[100] = "56+57";
	int i,j;
	sscanf(a,"%d+%d",&i,&j); //用法和scanf差不多,只是多传了一个char数组

	printf("%d+%d=%d\\n",i,j,i+j); // 56+57=113
	return 0;

常用的格式化符号

其中%*表示忽略的意思,例如%*d表示忽略数字, %*s表示忽略字符串
1.%*s忽略字符串的时候需要有分割符号,例如空格或者\\t, 否则会将整个字符串都忽略了
2.%[a-z]是从字符串开头位置开始匹配,如果开都是数字,那么直接匹配失败,通常结合%*d使用,也就是%*d%[a-z],这样可以忽略开头的数字
3.%[aBc]也是从字符串开头位置开始匹配,如果第一个都不符合,那么直接匹配失败.
4.%[^a]也是从字符串开头位置开始匹配,直到出现了a字符为止,a字符之后的不会参与匹配.
5.%[^a-z]也是从字符串开头位置开始匹配,直到出现了a-z中的任意字符位为止.
上面说说的a-z字符是任意字符,可以是数字,例如0-9;

练习-求获取"abcde#12uiop@plju"字符串中的"12uiop"子串.

int main()

    char *str = "abcde#12uiop@plju";
    char buf[1024] = 0;
    //先忽略#号前的字符,然后#照写,然后匹配非@的字符
    sscanf(str, "%*[^#]#%[^@]", buf); 
    printf("buf=%s\\n", buf);
    return 0;

练习-求给定一个字符串表达式,求其结果并追加到原字符串末尾
例如"56*57="的字符串。

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

int main()

	char a[100] = "56*57=";
	int i,j; // 存储2个操作数
	char c; // 存储操作符号
 
     // 从字符串中取数据
	sscanf(a,"%d%c%d",&i,&c,&j);
	
	int res =0;
	if(c=='+')
	
		res = i+j;
	else if(c=='-')
	
		res = i-j;
	else if(c=='*')
	
		res = i*j;
	else if(c=='/')
	
		res = i/j;
	

	printf("%d%c%d=%d\\n",i,c,j,res);
	return 0;

1.12 strchr和strstr函数

这2个函数都是用于在特定字符串中查找子串, 区别是strchr只能按字符查找, 而strstr可以按字符串查找, 注意如果找到特定的字符或者字符串,那么它会返回这个字符或者字符串作为起点到被查找字符串的末尾的字符串。 相当于java中的substring的功能, 截取子串。

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

int main()

	char a[] = "hello world";

	char *s; //定义一个char类型的指针变量
	s = strchr(a,'l');
	if(s !=NULL)
	
		printf("s1=%s\\n",s); // s1=llo world
	

	s = strstr(a,"wo");
	if(s !=NULL)
	
		printf("s2=%s\\n",s); // s2=world
	

	return 0;

1.13 strtok函数

字符在第一次调用时strtok必须给予参数s字符串,往后的调用则将参数s设置成NULL,每次调用成功则返回指向被分割出片段的指针, 类似于java中的String的split方法

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

int main1()

	char a[]="abc_123_hello_world";
	char *s;//定义一个char的指针变量,指针的概念将会在后续介绍
    s = strtok(a,"_");
	printf("%s\\n",s); // abc

	
    s = strtok(NULL,"_"); //后面的调用必须传NULL
	printf("%s\\n",s); // 213

    s = strtok(NULL,"_");
	printf("%s\\n",s); // hello


	return 0;



//上面的截取方式有点麻烦,通常会采用下面这种方式
int main()

	char a[] = "abc_213_hello_world";
	char *s;
	s = strtok(a,"_");
	while(s) //如果s为NULL,就是0 , 0就是false,退出循环
	
		printf("%s\\n",s);// 依此输出:abc、213、hello、world
		s = strtok(NULL,"_");
	
	return 0;


1.14 atoi和atof,atoll函数

可以将字符串转成int,long ,long long类型

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

int main()

	char a[] = "36";
	char b[] = "37";
	//字符串转int
	int sum = atoi(a)+atoi(b);
	printf("sum=%d\\n",sum); //sum=73

	//字符串转float或double
	char c[] = "3.5";
	double f = atof(c);
	printf("f=%f\\n",f);// f=3.500000
	return 0;

int类型转字符串类型

c语言中没有提供int转string的,那如何要实现将int添加到字符串的功能?
只能使用sprintf+strcat来完成

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

int main()

	char str1[100] = "abc";
	char str2[10]

以上是关于C基础函数的使用的主要内容,如果未能解决你的问题,请参考以下文章

C 中在单链表末尾添加节点的函数不起作用

函数体调用C ++末尾的奇怪循环

go语音基础之append函数的使用

文件操作+函数基础day09

c++基础(lambda)

嵌入式软件面试高频基础——C语言