一、数组基本语法
1. 什么是数组
数组是c语言的一种数据结构,用于存储一组具有相同数据类型的数据;
数组中每个元素可以通过下标进行访问,索引从0开始,最大值为数组长度-1。
2. 数组的使用
类型 数组名[元素个数];
int arr[5];下标从0开始 因此5个元素分别是arr[0],arr[1],arr[2],arr[3],arr[4]
数组名不能与其他变量名相同,同一作用域内是唯一的。
#include <stdio.h>int main() {// 定义了一个数组,名字叫a,有10个成员,每个成员都是int类型int a[10]; // a[0]…… a[9],没有a[10]// 没有a这个变量,a是数组的名字,但不是变量名,它是常量a[0] = 0;// ……a[9] = 9;// 数据越界,超出范围,错误// a[10] = 10; // errfor (int i = 0; i < 10; i++) {a[i] = i; // 给数组赋值}// 遍历数组,并输出每个成员的值for (int i = 0; i < 10; i++) {printf("%d ", a[i]);}printf("\n");return 0;
}
3. 数组的初始化
在定义数组的同时进行赋值,称为初始化
全局数组若不初始化,编译器将其初始化为零
局部数组若不初始化,内容为随机值
int a1[10] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 }; // 定义一个数组,同时初始化所有成员变量int a2[10] = { 1, 2, 3 }; // 初始化前三个成员,后面所有元素都设置为0int a3[10] = { 0 }; // 所有的成员都设置为0// []中不定义元素个数,定义时必须初始化int a4[] = { 1, 2, 3, 4, 5 }; // 定义了一个数组,有5个成员
4. 数组名
数组名是一个地址的常量,代表数组中首元素的地址
#include <stdio.h>int main() {// 定义一个数组,同时初始化所有成员变量int a[10] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10}; // 数组名是一个地址的常量,代表数组中首元素的地址printf("a = %p\n", a);printf("&a[0] = %p\n", &a[0]);int n = sizeof(a); // 数组占用内存的大小,10个int类型,10 * 4 = 40int n0 = sizeof(a[0]); // 数组第0个元素占用内存大小,第0个元素为int,4int num = n / n0; // 元素个数printf("n = %d, n0 = %d, num = %d\n", n, n0, num);return 0;
}
二、数组和指针
数组名字是数组的首元素地址,它是一个常量;
*和[]一样,都是操作指针所指向的内存
#include <stdio.h>int main() {int a[] = {1, 2, 3, 4, 5, 6, 7, 8, 9};int i = 0;int n = sizeof(a) / sizeof(a[0]);for (i = 0; i < n; i++) {// * 和 [] 效果一样,都是操作指针所指向的内存// printf("%d, ", a[i]);printf("%d, ", *(a + i));}printf("\n");// 定义一个指针变量保存a的地址int *p = a; for (i = 0; i < n; i++) {// printf("%d, ", p[i]);printf("%d, ", *(p + i));}printf("\n");return 0;
}
1. 指针数组
数组的每个元素都是指针类型
#include <stdio.h>int main() {// 指针数组int *p[3];int a = 1;int b = 2;int c = 3;// 指针变量赋值p[0] = &a;p[1] = &b;p[2] = &c;for (int i = 0; i < sizeof(p) / sizeof(p[0]); i++) {printf("%d, ", *(*(p + i)));// printf("%d, ", *(p[i]));}printf("\n");return 0;
}
2. 数组名做函数参数
函数做函数参数,函数的形参本质上就是指针
#include <stdio.h>// 下面3种写法完全等价
// void print_arr(int a[10], int n)
// void print_arr(int a[], int n)
void print_arr(int *a, int n) {int i = 0;for (i = 0; i < n; i++) {printf("%d, ", a[i]);}printf("\n");
}int main() {int a[] = {1, 2, 3, 4, 5, 6, 7, 8, 9};int n = sizeof(a) / sizeof(a[0]);// 数组名做函数参数print_arr(a, n);return 0;
}
三、字符数组与字符串
1. 字符数组与字符串区别
c语言中没有字符串,可以通过char的数组来代替
数字0(等于字符'\0')结尾的char就是字符串,字符串是一中特殊的char的数组
如果char字符中没有以0结尾 那么就不是一个字符串 是普通的字符数组
#include <stdio.h>int main() {char c1[] = {'c', ' ', 'p', 'r', 'o', 'g'}; // 普通字符数组printf("c1 = %s\n", c1); // 有可能乱码,因为没有'\0'结束符// 以'\0'('\0'就是数字0)结尾的字符数组是字符串char c2[] = {'c', ' ', 'p', 'r', 'o', 'g', '\0'};printf("c2 = %s\n", c2);// 字符串处理以'\0'(数字0)作为结束符,后面的'h', 'l', 'l', 'e', 'o'不会输出char c3[] = {'c', ' ', 'p', 'r', 'o', 'g', '\0', 'h', 'l', 'l', 'e', 'o', '\0'};printf("c3 = %s\n", c3);// 使用字符串初始化,编译器自动在后面补0,常用char c4[] = "c prog";printf("c4 = %s\n", c4);return 0;
}
2. 字符串的输入输出
#include <stdio.h>int main()
{char str[100];printf("input string1: ");// scanf("%s",str) 默认以空格分隔// 可以输入空格gets(str);printf("output: %s\n", str);return 0;
}
3. 字符指针
字符指针可直接赋值为字符串 保存的实际是字符串的首地址;
字符串指向的内存不能更改 指针变量本身可以更改
#include <stdio.h>int main() {char *p = "hello"; // 和 const char *p = 'hello' 等价,有没有const都一样// 指针变量所指向的内存不能修改// *p = 'a'; // errprintf("p = %s\n", p);// 指针变量可以修改p = "world";printf("p = %s\n", p);return 0;
}
4. 字符串常用库函数
4.1 strlen
#include <stdio.h>
#include <string.h>
// size_t strlen(const char *s);
// 功能:计算指定指定字符串s的长度,不包含字符串结束符‘\0’
// 参数:
// s:字符串首地址
// 返回值:字符串s的长度,size_t为unsigned int类型,不同平台会不一样int main() {char str[] = "abcdefg";int n = strlen(str);printf("n = %d\n", n); // n = 7return 0;
}
4.2 strcpy
#include <stdio.h>
#include <string.h>// char *strcpy(char *dest, const char *src);
// 功能:把src所指向的字符串复制到dest所指向的空间中,'\0'也会拷贝过去
// 参数:
// dest:目的字符串首地址,如果参数dest所指的内存空间不够大,可能会造成缓冲溢出的错误情况
// src:源字符首地址
// 返回值:
// 成功:返回dest字符串的首地址
// 失败:NULLint main() {char dest[20] = "123456789";char src[] = "hello world";strcpy(dest, src);printf("%s\n", dest); // hello worldreturn 0;
}
4.3 strcat
#include <stdio.h>
#include <string.h>// char *strcat(char *dest, const char *src);
// 功能:将src字符串连接到dest的尾部,‘\0’也会追加过去
// 参数:
// dest:目的字符串首地址
// src:源字符首地址
// 返回值:
// 成功:返回dest字符串的首地址
// 失败:NULLint main() {char str[20] = "123";char *src = "hello world";strcat(str, src);printf("%s\n", str); // 123hello worldreturn 0;
}
4.4 strcmp
#include <stdio.h>
#include <string.h>// int strcmp(const char *s1, const char *s2);
// 功能:比较 s1 和 s2 的大小,比较的是字符ASCII码大小。
// 参数:
// s1:字符串1首地址
// s2:字符串2首地址
// 返回值:
// 相等:0
// 大于:>0
// 小于:<0int main() {char *str1 = "hello world";char *str2 = "hello mike";if (strcmp(str1, str2) == 0) {printf("str1==str2\n");} else if (strcmp(str1, str2) > 0) {printf("str1>str2\n");} else {printf("str1<str2\n");}// str1>str2return 0;
}