栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > C/C++/C#

L1D5 C语言数组和字符串

C/C++/C# 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

L1D5 C语言数组和字符串

数组和字符串 一、一维数组的定义、引用及初始化 1.1 数组的定义

数组是具有一定顺序关系的若干个变量的集合,组成数组的各个变量称为数组的元素 数组中各元素的数据类型要求相同,用数组名和下标确定。数组可以是一维的,也可以是多维的。

1.2 一维数组的定义

一维数组是指只有一个下标的数组。它在计算机的内存中是连续存储的
说明形式为:<存储类型> <数据类型 > <数组名>[<表达式>]

例如:int a[6]; 数组名a表示内存首地址,sizeof(a)是数组占用的总内存空间,
C语言数组编译时,不会对数组做越界检查,自己要注意。
a[6]表示a有6个元素,分别为a[0] a[1] a[2] a[3] a[4] a[5]
1.3 一维数组的引用

C语言中规定数组必须逐个元素引用,而不能整体引用,比如下面这样是错误的,数组的引用实际上是数组元素的引用,数组元素需要用数组名[下标]表示:

int a[10];
printf("%dn",a);

如下演示是正确的,计算斐波那契数列前10项并逆序输出结果:

#include 
int main(int argc, char const *argv[])
{
    int i = 0 , a[10] = {0};
    a[0] = a[1] = 1;
    for(i = 2 ; i < 10 ; i++)
    {
        a[i] = a[i-2] + a[i-1];
    }
    printf("fibonacci numbers...n");
    for(i = 9 ; i > 0 ; i--)
        printf("a[%d] is %dn",i , a[i]);
    return 0;
}

1.4 一维数组的初始化

我们定义的任何形式的变量尽量都初始化,防止后续遇到问题无法快速定位,因为一个变量如果没有初始化及赋值就直接拿来使用的话,这个值是随机的,因为局部变量来说我们是去栈上开辟了空间,但是栈上原来可能是有数据的,不初始化的话就会直接把栈上的数据拿过来。如下演示所示(没对a[10]初始化):

#include 
int main(int argc, char const *argv[])
{
    int a[10];
    for (int i = 0; i < 10; i++)
    {
        printf("a[%d] is %dn", i , a[i]);
    }
    return 0;
}

数组初始化有七种情况:
1、局部变量不初始化:对于局部变量数组,若定义时未初始化,则数组元素值为随机值。
2、static数组不初始化:对于static修饰的数组,在内存上是存在全局与静态区,这里会进行清0处理(清bss段),因此元素都为0
3、全局数组不初始化:对于全局数组,在内存上是存在全局与静态区,这里会进行清0处理(清bss段),因此元素都为0
4、全部初始化:所有元素给一个初值

int a[5] = {1 , 2 , 3 , 4 , 5};

5、部分初始化:数组如果部分元素赋值,其他元素自动赋值0

int a[5] = {1 , 2};    //此时a[0] = 1 a[1] = 2  a[3] = 0 a[4] = 0   

6、数组全部初始化为0(特殊写法)

int a[5] = {0};
二、一维数组的内存分配

在内存中,数组中的元素占用连续空间,并且根据单个元素所占存储空间来进行内存分配。

#include 

int main(int argc, char const *argv[])
{
    int i = 0;
    char a[6] = {0};
    int b[6] = {0};
    for ( i = 0; i < 6; i++)
    {
        printf("a[%d] address is : %pn", i, &a[i]);
    }
    for ( i = 0; i < 6; i++)
    {
        printf("b[%d] address is : %pn", i, &b[i]);
    }
    return 0;
}


从上面可以看出,char型数组元素地址连续,且相差一个字节。int型数组元素地址连续且相差4字节。

三、二维数组的定义、初始化 3.1 二维数组的定义

二维数组是指有两个下标的数组。但是它在计算机的内存中是连续存储的,二维数组在内存上实际是一维的。
说明形式为:<存储类型> <数据类型 > <数组名>[<表达式1>][<表达式2>] 表达式1可省略 2不可省略

int a[2][3]   //2代表行  3代表列
// a[0][0]  a[0][1]   a[0][2]
// a[1][0]  a[1][1]   a[1][2]
3.2 二维数组的初始化

二维数组初始化与一维数组类似,主要是如下几种:
1、降维初始化

int a[2][3]  = {{ 1 , 2 , 3 } , { 4 ,5 , 6 }};    //完全初始化
int a[2][3]  = {{1} , {4}};    //部分初始化   第一行 1 0 0 第二行 4 0 0 

2、按线性存储形式给二维数组赋值初始化

int a[2][3]  = {1 , 2 , 3 , 4 , 5 , 6};
int a[2][3] = { 1 , 2};   //第一行 1 2 0  第二行 0 0 0

3、省略左边(行)下标范围方式初始化

int a[][3] = {1 , 2 , 3 , 4 , 5 , 6};  /第一行1 2 3  第二行 4 5 6 
//不能写int a[2][]这种形式
四、二维数组的内存分配

由于内存是一维的,C语言中,二维数组采取了和一维数组类似的存储方式,按行优先存,存储第一行的元素后,再存第二行的。

a[0]代表&a[0][0] ,a[0]+2代表&a[0][2]
(注意:在数组a[2][3]中,a代表二维数组名,a[0]代表一维数组名,只要是数组名就是地址常量,不可以直接写a++ a[0]++)
有如下例子,有6元素的二维数组,在内存中的组织形式可用代码验证:

#include 
int main(int argc, char *argv[])
{
	int a[2][3] = {{1,6}};
	int i = 0,j = 0;
	for(i = 0; i < 2; i++)
	{
		for(j = 0; j < 3; j++)
		{
			printf("%pt",&a[i][j]);
			printf("%dn",a[i][j]);
			
		}	
	}
	printf("%p %ld %ldrn",a,sizeof(a),sizeof(a[1][1]));
	
	return 0;
}

五、字符数组 5.1 字符数组定义

字符数组是元素的数据类型为字符类型的数组 char c[10],ch[3][4],diamond[][5];

5.2 字符数组初始化

①逐个字符元素赋值初始化

char ch[6] = {'a' , 'b' , 'c' , 'd' , 'e' , ''};

②使用字符串常量为数组元素赋值

char ch[6] = {"abcde"};   //要给留位置  会自动补
char ch[6] = "abcde";
char ch[] = "abcde";
char ch[5] = "abcde";  //会报错,因为字符串隐含'',5个位置不够放
六、字符串的定义、输入输出 6.1 字符串定义

字符串指的是以’’作为结束字符的一组字符,在C语言中没有专门的字符串变量,通常用一个字符数组来存放一个字符串。

6.2 字符串输入输出

使用scanf和printf进行字符串输入输出,此时格式化符号使用’%s’,见下面的代码:

#include 

#define N 20
int main(int argc, char const *argv[])
{
    int i = 0;
    char s[N] = {0};

    printf(">");
    while (scanf("%s", s) != EOF)    //scanf会以空格作为结束标识符
    {
        printf(">");
        printf("i = %d :%sn", i, s);
        i++;
    }
    return 0;
}

七、字符串处理函数

C库中,提供了很多字符串处理函数,利用好这些函数,能够让编程事半功倍。

7.1 字符串拷贝函数strcpy

可以在linux终端使用man 3 strcpy查看strcpy的详细用法(所有系统提供的都可以这样查)。

头文件:string.h
函数原型:char *strcpy(char *dest , const char *src)
功能:字符串拷贝
参数:src:源串起始地址   dest:目标串起始地址
返回值:目标串起始地址

示例:

#include 
#include 
#define N 50

int main(int argc, char const *argv[])
{
    char dest[N];
    char src[] = "welcome";
    strcpy(dest, src);
    printf("dest: %s src:%sn", dest,src);
    return 0;
}


注意:字符串结束字符’’也会一起拷贝。

7.2 字符串连接函数strcat
头文件:string.h
函数原型:char *strcat(char *dest , const char *src)
功能:字符串连接,把字符串src连接到dest后面
参数:src:源串起始地址   dest:目标串起始地址
返回值:目标串起始地址

示例:

#include 
#include 
#define N 50

int main(int argc, char const *argv[])
{
    char dest[N] = "welcome";
    char src[] = "china";
    strcat(dest, src);
    printf("dest: %s src:%sn", dest,src);
    return 0;
}


注意:在使用strcat函数时,需要注意目标串应该要有足够的空间。(目标串’’被删除然后连接源串)

7.3 字符串比较函数strcmp
头文件:string.h
函数原型:int strcmp(const char *s1 , const char *s2)
功能:对两串从左向右逐个字符比较
参数:s1 s2为两个串的起始地址
返回值:int型整数  若s1 < s2,返回负整数   s1 > s2 ,返回正整数   s1 = s2 , 返回0

示例:

#include 
#include 
#define N 50

int main(int argc, char const *argv[])
{
    int t = 0;
    char s1[N] = {0};
    char s2[N] = {0};
    printf(">");
    scanf("%s%s",s1,s2);
    t = strcmp(s1,s2);
    if (t == 0) 
        printf("s1 = s2n");
    else if(t > 0)
        printf("s1 > s2n");
    else
        printf("s1 < s2n");
    return 0;
}

7.4 求字符串长度函数strlen
头文件:string.h
函数原型:size_t strlen(const char *s)
功能:求字符串长度(不含'')
参数:s为字符串
返回值:字符串长度(不含'')

示例:

#include 
#include 
#define N 50

int main(int argc, char const *argv[])
{
    char s[N] = "welcome";
    printf("s strlen = %ldn", strlen(s));           //字符串长度
    printf("s sizeof = %ldn", sizeof(s)/sizeof(char));  //整个数组大小
    return 0;
}

7.5 字符串按特定格式分割函数 strtok(常用)
头文件:string.h
函数原型:char *strtok(char *s , const char *delim)
功能:将字符串分割成一个个片断
参数:s为要分解的字符串 delim为分隔符字符串
返回值:分解出的字符串地址

当strtok在参数s的字符串中发现了delim中包含的分隔符时,会将该字符串改为’’字符。在第一次调用时,strtok必须给参数s字符串,往后的调用,则将s设置为NULL。每次调用成功则返回指向被分割出片段的指针。
示例程序如下:

#include 
#include 

int main()
{
    char str[80] = "This is - www.baidu.com - website";
    const char s[2] = "-";
    char *token;

    
    token = strtok(str, s);

    
    while (token != NULL)
    {
        printf("%sn", token);

        token = strtok(NULL, s);
    }
    printf("n");
    for (int i = 0; i < 34;i++)
        printf("%c", str[i]);
    printf("n");
    return 0;
}

7.6 其他常用字符串函数(可用man手册查看用法,自行测试,学习一个函数最后的方法就是验证它)
char *strncpy(char *dest, const char *src, size_t n);   //复制src串指定长度n到目标dest串
char *strncat(char *dest, const char *src, size_t n);//附加指定长度字符串
int strcasecmp(const char *s1, const char *s2);   //忽略大小写比较字符
int strncmp(const char *s1, const char *s2, size_t n);  //比较两个串的前n个字符
char *strchr(const char *s, int c);    //在字符串s中查找指定字符c
char *strstr(const char *haystack, const char *needle);  //在字符串中查找字符串
int isalpha(int c);				//检查是否为字母字符
int islower(int c);				//检查是否为小写字母字符
int isupper(int c);				//检查是否为大写字母字符
int isdigit(int c);				//检查是否为数字
int toupper(int c);				//转换成大写
int tolower(int c);				//转换成小写
八、总结练习 1、从终端输入10个数字(乱序),分别利用冒泡排序和简单选择排序法对这10个数字排序,结果从小到大排列。(温馨提示:冒泡排序和简单选择排序是两个不同的原理。)

答:
①冒泡排序:
思路:冒泡排序概念:它重复地走访过要排序的数列,一次比较两个元素,如果顺序错误就交换。走访数列的工作是重复地进行直到没有再需要交换,也就是说该数列已经排序完成
程序:

#include 

#define N 10

int main(int argc, char const *argv[])
{
    int a[N] = {0};
    int i = 0 , j = 0 , t = 0;
    printf("please input %d numbers:n",N);
    for (i = 0; i < N; i++)
    {
        scanf("%d",&a[i]);
    }
    for (i = 0; i < N-1; i ++)
        for (j = 0; j < N - 1 - i; j++)
        {
            if (a[j] > a[j+1])
            {
                t = a[j];
                a[j] = a[j+1];
                a[j+1] = t;
            }
        }
    printf("the array after sort:n");
    for ( i = 0; i < N; i++)
    {
        printf("%5d",a[i]);
    }
    printf("n");
    
    return 0;
}

演示情况:

②简单选择排序
思路:首先在未排序序列中找到最小(大)元素,存放到排序序列的起始位置,然后,再从剩余未排序元素中继续寻找最小(大)元素,然后放到已排序序列的末尾。以此类推,直到所有元素均排序完毕。

程序:

#include 
#define N 10
int main(int argc, char const *argv[])
{
    int a[N] = {0};
    int i = 0 , j = 0 , r = 0 , t = 0;
    
    printf("please input %d numbers:n",N);
    for (i = 0; i < N; i++)
    {
        scanf("%d",&a[i]);
    }

    
    for ( i = 0; i < N - 1; i++)
    {
        r = i;
        for (j = i + 1; j < N; j++)
        {
            if (a[j] < a[r])
                r = j;
        }
        if (r != i)
        {
            t = a[r];
            a[r] = a[i];
            a[i] = t;

        }
    }
    
    
    printf("the array after sort:n");
    for ( i = 0; i < N; i++)
    {
        printf("%5d",a[i]);
    }
    printf("n");
    return 0;
}

演示情况:

2、有一个3×4的矩阵,找出其最大值并打印最大值的位置。

答:

#include 

int main(int argc, char const *argv[])
{
    int a[3][4] = {{1 , 65 , 34 , 67} , {23 , 33 , 57 , 24} , { 1 , 2 ,3 ,4} };
    int max = 0 , i = 0 , j = 0;
    int row = 0 , column = 0;
    max = a[0][0];   //假定第一个元素为最大值  用后面的和第一个比
    for ( i = 0; i < 3; i++)
    {
        for ( j = 0; j < 4; j++)
        {
            if ( a[i][j] > max )
            {
                max = a[i][j];
                row = i;
                column = j;

            }
        }
    }
    printf("max value is : %d , row = %d , column = %dn",max,row,column);
    
    return 0;
}

结果演示:

3、打印杨辉三角的前十行(学会复杂问题分解化:首先打印一个全为1的a[10][10],然后取对角线以下的数据,最后调整值)

代码如下:

#include 
int main(int argc, char *argv[])
{
	static int a[10][10];
	int i = 0,j = 0;
	for(i = 0; i < 10; i++)
	{
		a[i][0] = 1;
		for(j = 1; j <= i; j++)
		{
			a[i][j] = a[i-1][j-1]+a[i-1][j];
		}
	}
	for(i = 0;i<10;i++)
	{
		for(j = 0;j<=i;j++)
			printf("%d  ",a[i][j]);
		printf("n");
	}
	//printf("%dn",a[-1][1]);
	return 0;
}

结果演示:

4、删除字符串重复字符

答:


#include  
#include 
#define N 100
int main(int argc, char **argv)
{
	char str[N] = {0};
	printf("please input a string:n");
	scanf("%s",str) ;
	int length = strlen(str);

	int i = 0, j = 0 , pos = 0;
	for(i = 0;i < length;i++){
		for(j = i+1;j < length;j++)
        {
			if(str[i] == str[j])     //有相同字符
            {
				for(pos = j;pos < length; pos++)    
                {
				str[pos] = str[pos+1];		//下一个字符赋值给当前字符 (相当于删除字符操作) 
				}
				length--;
				j--;	                    //由于当前字符已删除,需要再次判断当前位置的字符是否和第i个字符相等 
			}
		}
	}
	printf("new string:%sn",str);
	return 0;
}

结果演示:

5、统计字符串中空格的数量

答:

#include 
#include 

#define N 100

int main(int argc, char const *argv[])
{
    int i = 0 , num = 0;
    char str[N] = {0};
    printf("please input a string:n");
    gets(str);                          //本来这里用的是scanf  但是scanf遇到空格认为是结束符了  改用gets
    while (str[i] != '')
    {
        if (str[i] == ' ')
        {
            num++;
        }
        i++;
    }
    printf("the space num is: %dn", num);

    return 0;
}


ps:欢迎大佬指正,共同学习进步。

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/1001291.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号