文章目录
- 1.字符类型
- 2.字符读取
-
- 1.scanf()函数
- 2.getchar和putchar函数用法
- 3.字符串
-
- 1.自符串的定义:
- 2.strlen();和sizeof();的区别
-
- 3.注意出现野指针造成非法内存访问,出现段错误。
- 4.malloc 动态开辟内存空间
- 5.字符串的操作函数:(调用函数时需要包含文件#include<string.h>)
- 6.自己实现的字符串操作函数
1.字符类型
char是一种整数,也是一种特殊的类型——字符。用单引号表示的字符字面量:‘a’,'1’也是一个字符,printf和scanf里面用%c来输入输出字符。
2.字符读取
1.scanf()函数
用法
%d说明我们现在要读入一个整数了,scanf这个函数会读入下一个整数,读到的结果赋值给指定变量,要注意指定变量前面的&
如果要读入输入的数据,就必须严格按照""中的格式输入,如:
int main()
{
int a,b;
scanf("%d,%d",&a,&b);
printf("%d %d\n",a,b );
return 0;
}
若不严格按照格式输入,则会导致接收错误
-
scanf语句的原理
scanf并不会直接从我们的键盘输入中读取数据,我们从键盘输入的数据先存储在输入缓冲区中,当按下回车键后,即输入缓冲区遇到回车符时,程序才会在输入缓冲区中读取数据,scanf读取到空格、tab或者回车符的时候停止读取。
scanf语句读取完数字后,会把后面的空格也读取掉。如果后面有变量来接收,读取后就会把空格赋值给对应的变量,如果没有变量来接收,那么仅仅是读取,不会进行赋值操作。值得注意的是,scanf只有在读取完数字后会继续把后面的空格读取掉
如下例:
int main()
{
char word[8];
scanf("%s",word);
printf("%s\n",word);
return 0;
}
这说明读取完字符o后,并没有将后面的空格读取出来,遇到空格就直接停止读取了。
2.getchar和putchar函数用法
(1)getchar函数
函数格式: int getchar()
所在头文件: <stdio.h>
函数功能: 从输入缓冲区中读取单个字符
函数返回值: 成功时为获得的字符,失败时为 EOF 。
(2)putchar函数
函数格式: int putchar(int ch)
所在头文件: <stdio.h>
函数功能: 输出字符到标准输出上,等价于 putc(ch, stdout)
函数参数: ch,表示要写入的字符,可以是字符常量,转义字符,可以是介于0~ 127之间的一个十进制整型数(包含0和127,超过127就不是ASCII码了),当参数为一个介于0~127(包括0及127)之间的十进制整型数时,它会被视为一个ASCII代码,输出该ASCII代码对应的字符,也可以是一个字符变量。
参数为是一个字符,但参数却是int型,这表示1字节的字符存在4字节大小的内存中。
或者换个理解方式,字符对应的ASCII码值用int型参数来接收。
函数返回值:
成功时,返回参数的ASCII码值。
失败时,返回 EOF 并设置 stdout 上的错误指示器。
3.getchar和putchar函数工作原理:
getchar()用于从键盘输入中读取单个字符,当我们连续输入多个字符时,第一个getchar()读取第一个字符,后续的getchar()依次读取后续的字符,当getchar()读取到EOF或者读取到回车时停止执行。
while ((ch = getchar()) != EOF) {
putchar(ch);
}
#include<stdio.h>
int main()
{
char ch = ' ';
while ((ch = getchar()) != EOF) {
putchar(ch);
}
return 0;
}
我们输入abc按下回车后,
输入缓冲区中的内容:abc\n
由于遇到\n,因此getchar开始从输入缓冲区中读取字符,先读取a,满足输出while循环条件,可以输出,先存储到输出缓冲区中,然后读取b,满足输出while循环条件,可以输出,先存储到输出缓冲区中,然后读取c,满足输出while循环条件,可以输出,先存储到输出缓冲区中,最后读取\n,满足输出while循环条件,可以输出,先存储到输出缓冲区中。
此时输出缓冲区中的内容:abc\n
由于输出缓冲区遇到了\n,所以进行一次系统调用,将输出缓冲区的内容直接输出到标准输出上。
3.字符串
1.自符串的定义:
char* str=” Zhang ”;
相当于
char str []=”Zhang”;
这里直接使用指针因为数组的名称相当于首元素的地址。
-
注意:
上述方法定义
char* str=” Zhang ”;
是字符串的常量,内容不可以修改。
若定义为:
则为字符串变量,可以修改!char str []=”Zhang”;
- 调用时:
//调用时直接用%s占位符即可。printf(“%s”,str);
-
字符串在内存中的存储方式:
字符串在存储时,除了有效字符以外,还会自动在后面补一个’\0’的结束标志。
2.strlen();和sizeof();的区别
计算字符串有效字符的个数用函数 strlen();而不是sizeof();
- sizeof();是C语言得关键字,而strlen();是函数
strlen();在计算字符大小时遇到’\0’就停止了计数。
sizeof 计算字符数组大小时计算全部数组大小,即:
char data [128] = “hello”;
sizeof(data) = 128;
strlen(data) = 5;
3.注意出现野指针造成非法内存访问,出现段错误。
形如:
char*pstr;
scanf(“%s”,pstr);
puts(pstr);
便会造成非法内存访问。定义出来的pstr 成为了一个野指针,指针变量里面所存放的东西未知且系统没有给空间。
解决方法:
方法1:(直接用字符数组并在内存放128个’\0’)
`char pstr[128]=’\0’;`//申请空间并做了初始化,把每个元素都初始化为’\0’
scanf(“%s”,pstr);
puts(pstr);
方法2:(用malloc函数开辟空间)
char*pstr=(char*)malloc(128);
4.malloc 动态开辟内存空间
与malloc 相关的函数
(Linux下)
void *malloc(size_t size);
void free(void *ptr);
void *calloc(size_t nmemb, size_t size);
void *realloc(void *ptr, size_t size);
void *malloc(size_t size);
分配所需的内存空间。并返回一个指向它的指针
void free(void *ptr);
释放,防止内存泄露 当内存不再使用的时候,应使用free()函数将内存块释放掉。
void *calloc(size_t nmemb, size_t size);
calloc(10 , sizeof(int)) calloc在返回在堆区申请的那块动态内存的起始地址之前,会将每个字节都初始化为0
void *realloc(void *ptr, size_t size);
尝试重新调整之前malloc或calloc所分配的指针所指向内存块的大小
5.字符串的操作函数:(调用函数时需要包含文件#include<string.h>)
(1)
puts(str);
//输出字符串函数。(此函数可以自动加换行\n)
#include<stdio.h>
#include<string.h>
int main()
{
char * str = "hello";
puts(str);
return 0;
}
(2)
gets(str);
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
int main()
{
char *str;
str = (char *)malloc(32);
gets(str);
printf("str:%s\n",str);
return 0;
}
(3)
void *memset(void *s, int c, unsigned long n);
第一个参数
void* mem_loc
:已开辟内存空间的首地址,通常为数组名或指针,由于其为
void*
,故函数能为任何类型的数据进行初始化。
第二个参数
int c
:初始化使用的内容,取器低字节部分。
第三个参数
size_t n
:需要初始化的字节数。
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
int main()
{
char char_arr[5];
int int_arr[10];
int* int_malloc_ptr = (int*)malloc(sizeof(int) * 15);
memset(char_arr, 0, sizeof(char_arr)); // 数组名可以使用sizeof(arrName), 1 * 5 = 5
memset(int_arr, 0, sizeof(int_arr)); // 4 * 10 = 40
memset(int_malloc_ptr, 0, sizeof(int) * 15); // 4 * 15 = 60
printf("%s\n",char_arr);
return 0;
}
(4)
strcpy(str1,str2);
字符串拷贝
把str2的内容拷贝到str1中
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
int main()
{
char *str1 = "Hello World";
char *str2;
strcpy(str2,str1);
printf("str2:%s\n",str2);
return 0;
}
(5)
strncpy(str1,str2,int n);
把str2的内容拷贝到str1中,拷贝n个字符
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
int main()
{
char *str1 = "Hello World";
char *str2;
strncpy(str2,str1,6);
printf("str2:%s\n",str2);
return 0;
}
(6)
strcat(str1,str2);
//拼接函数 把str1和str2接到一起。
注意
由于要改变字符串需要将字符串定义为数组形式
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
int main()
{
char str1[] = "Hello ";
char str2[] = "World";
strcat(str1,str2);
printf("str1:%s\n",str1);
return 0;
}
(7)
strlwr(str);
将一段字符转为小写
注意定义str时只能用数组定义
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
int main()
{
char str1[] = "HELLO";
strlwr(str1);
printf("str1:%s\n",str1);
return 0;
}
(8)
strupr(str);
将一段字符转为大写。
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
int main()
{
char str1[] = "hello";
strupr(str1);
printf("str1:%s\n",str1);
return 0;
}
(9)
strtok(str1,”,”);
字符切割 将str1以,为结束标志切割
注意只能分割出来第一个字符串若想继续分割则要继续调用strok()调用而且要把目标字符串改成NULL strok(NULL,”,”);
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
int main()
{
char str1[]="hello,world";
char*p=NULL;
p=strtok(str1,",");
puts(p);//注意只能分割出来第一个字符串若想继续分割则要继续调用strok()调用而且要把目标字符串改成NULL strok(NULL,”,”);
return 0;
}
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
int main()
{
char str[]="hello,world";
char*p=NULL;
p=strtok(str,",");
puts(p);
p=strtok(NULL,",");
puts(p);
return 0;
}
(10)
strchr();
检索字符在一个字符串中出现的位置
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
int main()
{
char*str="hello world";
char c='w';
char*p=NULL;
//str 要被检索的字符串,c在str中要搜索的字符,返回值 返回字符串中第一次出现该字符的指针。若字符串中不包含该字符则返回NULL。
p=strchr(str,c);
puts(p);
system("pause");
return 0;
}
可见得到了第一次出现的’w’指针,并返回"world"字符串
(11)
strstr();
检索子串在一个字符串中出现的位置,并返回子串指针。
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
int main()
{
char*str="hello world!";
char*p=NULL;
char*substr="wor";
p=strstr(str,substr);
if(p==NULL)
{
printf("没有找到\n");
}
else{
puts(p);
}
return 0;
}
(12)
int ret =strcmp(char *s1,char*s2);
- 功能:比较两个字符串
(1). 如果两个字符串相等,则返回0;
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
int main()
{
char* str1 = "helloworld";
char* str2 = "helloworld";
int ret;
ret = strcmp(str1,str2);
printf("%d\n",ret);
return 0;
}
(2). 若str1大于str2,返回一个正数,这个正数不一定是1;
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
int main()
{
char* str1 = "helloworld";
char* str2 = "hellow!";
int ret;
ret = strcmp(str1,str2);
printf("%d\n",ret);
return 0;
}
(3). 若str1小于str2,返回一个负数,这个数不一定是-1
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
int main()
{
char* str1 = "helloworld!";
char* str2 = "hello!";
int ret;
ret = strcmp(str2,str1);
printf("%d\n",ret);
return 0;
}
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
int main()
{
char* str1 = "hello world";
char* str2 = "helloworld";
int ret;
ret = strcmp(str1,str2);
printf("%d\n",ret);
return 0;
}
- 注意:若字符串中存在空格,则以空格前的字符串进行比较:
(13)断言函数:
#include <assert.h>
assert的作用是现计算表达式expression,如果其值为假(0)则会打印错误消息终止运行:
6.自己实现的字符串操作函数
(1)strcpy
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
char* myStrcpy(char *des_str,char *src_str)
{
assert(des_str != NULL&&src_str != NULL);
char *temp = des_str;
while(*src_str != '\0'){
*des_str++ = *src_str++;
}
*des_str = '\0';
return temp;
}
int main()
{
char * str = "hello world!";
char str1[128] = {'\0'};
myStrcpy(str1,str);
printf("%s\n",str1);
system("pause");
return 0;
}
(2)strcat
char *myStrcat(char *des_str,char *src_str)
{
assert(des_str!=NULL&&src_str!=NULL);
char *temp = des_str;
while(*des_str != '\0'){
des_str++;
}
while((*des_str++ = *src_str++)!='\0');
*des_str = '\0';
return temp;
}
int main()
{
char *str = "world!";
char str1[32] = "hello ";
char *p2;
p2 = myStrcat(str1,str);
printf("%s\n",p2);
system("pause");
return 0;
}
(3)strcmp
int myStrcmp(char *str1,char *str2)
{
int str1Len;
int str2Len;
while(*str1!='\0'){
str1++;
str1Len++;
}
while(*str2!='\0'){
str2++;
str2Len++;
}
if(str1Len < str2Len){
return -1;
}else if (str1Len == str2Len)
{
return 0;
}else if(str1Len > str2Len){
return 1;
}
}