C语言学习-字符学习

1.字符类型

char是一种整数,也是一种特殊的类型——字符。用单引号表示的字符字面量:‘a’,'1’也是一个字符,printf和scanf里面用%c来输入输出字符。

2.字符读取

1.scanf()函数

用法

scanf("%d",&p);

%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”; 则为字符串变量可以修改!
  • 调用时:
    printf(“%s”,str);//调用时直接用%s占位符即可。
  • 字符串在内存中的存储方式:
    字符串在存储时,除了有效字符以外,还会自动在后面补一个’\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;
    }

}
  • 0
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值