字符数组,字符串,处理字符串的函数,周小结

沈杰同学大概是beyond的铁粉,已经连续两次早会上放他们的歌。不过不可否认,家驹同学的歌确实都还蛮励志的。沈杰同学每次开早会都颇有教授范儿,说话一板一眼,很有趣,私底下确是个活跃分子。每个集体中其实都需要这样一个人。

生兔子的题目简化版:
#include<stdio.h>
int i = 1,j = 1,k = 0,m = 2;
void main()
{   
    while(m < 30)
    {   
        k = i + j;
        i = j;
            j = k;
        m++;
    }
        printf("\n%d",k);
        getchar();
}

一题了解for循环:

#include<stdio.h>
int i = 1,sum = 0;
void main()
{   
    for(i = 0;i != 10;i++)
    {
        sum += i;
    }
    printf("%d\t%d",i,sum);     //10  45
    getchar();
}

一,字符数组

在 C 语言中,字符串实际上是使用 null 字符 ‘\0’ 终止的一维字符数组。
由于在数组的末尾存储了空字符,所以字符数组的大小比单词 “Hello” 的字符数多一个。(注意空格也算一个字符 )
char greeting[6] = {‘H’, ‘e’, ‘l’, ‘l’, ‘o’, ‘\0’};
依据数组初始化规则,可以把上面的语句写成以下语句:
char greeting[] = “Hello”;

    char s1[5] = {1,2,3,4,5};
    printf("%s",s1);
    getchar();
    这样就会有乱码,因为该字符数组没有结束符\0,或者说没有预留\0的内存空间。

定义时安全动作:初始化字符数组char s1[30]=”\0”;

字符串的截取:

截取“He”:

# include<stdio.h>
char ch1[6] = {'H','e','l','l','o'};
void main()
{
    char *p;
    p = ch1;
    *(p + 2) = 0;  
    //这一步是将结尾设置成空字符,ascii码0对应的是null,即“\0”,必须有这一步。否则会打印直到遇到空字符为止。
    printf("%s",p);  
    //这里是p,如果写*p则是打印字符'H',前面必须改成%c,就像这样:printf("%c",*p);
    getchar();
}

在C语言中,字符串是以\0结尾的字符数组。因此printf库函数在计算字符串长度的时候都是找到\0才结束,按%s输出字符数组的时候也是到\0结束,所以有时候如果没有给字符串加\0结束符,会看到乱码,就是这个原因。
‘\n’代表ASCII码为0的字符,从ASCII码表中可以查到ASCII码为0的字符不是一个可以显示的字符,而是一个“空操作符”,即它什么也不干。用它来作为字符串结束标志不会产生附加的操作或增加有效字符,只起一个供辨别的标志。

????

为什么打印字符数组的首地址,可以输出字符串

在c语言中,将字符串作为字符数组来处理。(c++中不是)

????:

int a[5] = {1,2,3,4,5};
int *p = {1,2,3,4,5} // 报错,不允许
char str[ ]=”I love China”;
char* str=”I love China”; //允许

C语言对字符串常量是按字符数组处理的,在内存中开辟了一个字符数组用来存放字符串常量,程序在定义字符串指针变量str时只是把字符串首地址(即存放字符串的字符数组的首地址)赋给str。

定义字符串有两种方法:

一、字符串指针 char *string=”abcde”;
二、一维字符数组。例如:char string[10];

字符数组的赋值

对字符数组只能对各个元素赋值,不能用以下方法对字符数组赋值
char str[14];
str=”I love China”; (但在字符数组初始化时可以,即char str[14]=”I love China”;)
而对字符指针变量,采用下面方法赋值:
char* a;
a=”I love China”;
或者是 char* a=”I love China”; 都可以

字符数组的整体赋值只能在字符数组初始化时使用,不能用于字符数组的赋值,字符数组的赋值只能对其元素一一赋值,下面的赋值方法是错误的
char str[ ];
str=”I am happy”;
因为如果定义了一个字符数组,那么它有确定的内存地址;而定义一个字符指针变量时,它并未指向某个确定的字符数据,并且可以多次赋值。

处理字符串输入输出的函数:

scanf () , printf(),puts(), gets()

#include<stdio.h>
char ch[100];
void main()
{   
    scanf("%s",ch);  //输入“hello”
    getchar();
    printf("\n%s",ch);   //输出“hello”
    getchar();
}

**下列函数需引用头的文件:<string.h>

复制 strcpy(s1, s2);

复制字符串 s2 到字符串 s1。
只对第一个字符长度的限制,对第二个字符串没有长度限制。
s1和s2所指内存区域不可以重叠且s1必须有足够的空间来容纳s的字符串。

拼接 strcat(s1, s2);

连接字符串 s2 到字符串 s1 的末尾,返回的是s1.

测量 strlen(s1);

返回字符串 s1 的长度。strlen所作的仅仅是一个计数器的工作,它从内存的某个位置(可以是字符串开头,中间某个位置,甚至是某个不确定的内存区域)开始扫描,直到碰到第一个字符串结束符’\0’为止,然后返回计数器值(长度不包含’\0’)

比较 strcmp(s1, s2);

当s1

字符串中寻字符首现地址 strchr(s1, ch);

返回一个指针,指向字符串 s1 中字符 ch 的第一次出现的位置。

字符串中寻字符串首现地址 strstr(s1, s2);

返回一个指针,指向字符串 s1 中字符串 s2 的第一次出现的位置。

题目:小写转大写

#include<stdio.h>
void main()
{
    int i = 0;
    char s1[30]="\0"; 
    char *p = s1;
    printf("请用小写字母输入一个字符串:\n"); 
    scanf("%s",s1); 
    getchar();
    printf("大写转换:\n");
    while(!(*p == '\0'))         //注意这里的写法
    {
        printf("%c",*p - 32);   
        p++;        
    }
    getchar();
}

C语言 gets()和scanf()函数的区别:

scanf 不能接受空格、制表符Tab、回车等;只要遇到他们即认为输入结束。并且会自动在字符串后面添加’\0’,但是回车,空格和tab键仍会留在输入的缓冲区中

gets 能够接受空格、制表符Tab等; 所以允许间隔输入,只有遇到回车才认为输入结束。会接受回车键之前输入的所有字符,并用’\n’替代 ‘\0’.回车键不会留在输入缓冲区中。和它配合使用的puts函数,在输出字符串的时候自动换行。

gets()用到读取字符串
scanf()可以读取所有类型的变量

指针

1,指针指向的是地址,地址指向的是值。
2,指针变量就是将另一个变量的地址作为值保存在自己的地址上。比如*p = &a,这时我们称p是指向a的指针。
3,指针有改变它所指向的变量的值的功能。你的值在你的地址里,而你的地址在我的地址里,可以理解为指针获取了操控其所指向的变量的权限。通俗一点,你在你的房间里,而你的房间在我的家里,我是你的主人,当然有访问你,干涉你的权限。
4,指针作为形参时,传入的是变量的地址,在被调函数中可以通过该地址取得变量的原始值并重新赋值,此时原函数中的变量也会随之修改。这是指针功能的具体体现。
5,int *p = &a,可以分解为两步,int *p; p = &a
定义时的“*”只是代表后面的变量是一个指针变量他是一个标志,
完成定义以后‘*’ +指针变量才是取值。
6,指针变量定义以后需要初始化,即给其赋值一个确定的地址,否则就是野指针,参与指针运算以后可能会出现不可预见的错误,有系统崩溃的风险。

指向指针的指针,指针与数组

**重点内容**1,指针的指针,其实就是二级指针。参考指针的概念,很容易理解。就是一个新的指针变量,它的地址里保存着另一个指针变量的地址。还是那个通俗的比喻:a住宅&a里,&a住宅&b里,&b住在&c里。所以c可以直接操作b,b又可以直接操作a,所以c可以间接操作a.例如:

    int a = 10,b = 11,*p1,**p2 ;    //注意这里的变量名分别是p1,p1
    p1 = &a; p2 = &p1;             //p1整形变量a的指针,p2是指针变量p1的指针
    *p1 = 20;                     //指针变量P1通过a的地址获取a的值并重新赋值为20
    *p2 = &b;                    //通过二级指针p2改变一级指针p1的指向,从指向a变为指向b
    *p1 = 30;(或者**p2 = 30)     //转向后的指针p1通过b的地址获取b的值并重新赋值为30
    printf("%d\t%d",a,b);      //此时打印的结果a = 20,b = 30

2,指针与数组这一节又分:指针与一维数组&指针与二维数组,这里涉及到指针运算
指针的运算主要包括:+,-,++,–。其实就是所指地址的移动。
两个公式:一维数组:*(p+i) = a[i] (下标逐个移动)
二维数组:(p+i)+j) = a[i][j] (i为行移动,j为列移动)

3,所有指针默认指向的都是目标变量首字节的地址,这句话可以判断能否精确取值的问题。比如:
int a[2][3] = [{1,2,3},{4,5,6}]
a指向整个数组,并默认指向第一行,*a无法取到1。
a[0]指向数组第一行,并默认指向第一行第一个元素,所以*a[0]可以取到1。
&a[0][0]无需默认,它精确的指向第一行第一个元素,所以*(&a[0][0])可以取到1.

4,指向数组的指针叫数组指针。
一维数组指针:
int *p = a; (或&a[0]都可以)
数组指针也可以有下标,比如p[5],代表当前所指的下标往后移5个。

二维数组指针:
int(*p)[4]; (表示其指向的是一个列数为4的二维数组指针)
此定义模式下的p才有行移动的功能。其它模式下如int *p = a[0]/&a[0]/&a[0][0]都只能逐个移动

数组传参的特殊性,数组指针,函数指针。

1,数组作为实参传入数组时,为了节约,形参并不重新分配内存。此时如果函数内用指针操作的其实是数组原始地址上的值,所以能够实现形参实参的双向互动。
2,数组指针,周二部分已讲。
3,函数指针,函数指针指向函数以后,通过指针就可以调用函数,主要是格式:
定义 int (*p)(int a,int b) 相当于去掉函数体,替换函数名,第一个小括号不可省略。
赋值 int = add add是函数名,跟数组一样,函数的函数名指向整个函数的地址
调用 p(a,b)

字符数组,字符串,处理字符串的函数

由于博客今日内容部分已详细描述,周小结部分就不做细致描述,罗列几个重点:
1,字符数组和字符串在内存中的存储格式是一样的,可以认为字符串就是字符数组。
2,字符数组的长度比字符个数要多一个,因为要预留一个位置给空字符\0,因为它是字符串结尾的标志,也是必不可少的部分。
3,printf(“%s”,p),是可以得到完成字符串的。
4,字符串可以这样定义,char *ch1 = “hello china”,但是 int *p = {1,2,3,4}不可以。
5,要打印单个字符需要这样printf(“%c”,*p)
6,处理字符串的函数,应用的头文件是string,h

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值