在C语言的面试中,指针数组是一个非常重要的知识点。它不仅是C语言中最基本的数据结构之一,也是面试官经常考察的知识点。在本篇博客中,我们将为大家整理一些常见的C语言指针数组类面试题,并为大家提供详细的解答和示例代码。希望能够帮助大家在面试中更好地掌握这个知识点。
在C语言中,指针数组是由若干个指针变量组成的数组。每个指针变量都指向一个特定的内存地址,可以用来存储不同类型的数据。指针数组常用于存储字符串、结构体等复杂类型的数据。
定义指针数组的语法如下:
int *arr[10];
这里定义了一个包含10个指向int类型变量的指针的数组。可以根据需要修改数组大小和指向的数据类型。
访问指针数组中的元素可以使用下标操作符[],例如:
int *arr[10];
int a = 10;
arr[0] = &a;
printf("%d", *arr[0]);
这里创建了一个包含10个指向int类型变量的指针的数组,并将a的地址赋给了数组的第一个元素。然后通过*arr[0]访问了a的值并输出。
指针数组和数组指针是两个不同的概念。
指针数组是一个数组,其元素都是指针类型。这意味着,每个数组元素都存储了一个指向某个数据类型的指针。例如:
int* ptrArray[10]; // 声明了一个包含10个整型指针的数组
在上面的例子中,ptrArray是一个包含10个整型指针的数组。
数组指针是一个指针,它指向一个数组。这意味着,该指针存储了数组的地址,可以用于访问该数组的元素。例如:
int (*ptr)[10]; // 声明了一个指向包含10个整数的数组的指针
在上面的例子中,ptr是一个指向包含10个整数的数组的指针。
因此,指针数组和数组指针有以下区别:
将一个数组作为参数传递给函数时,可以使用指针或者数组的方式。例如:
void func(int arr[], int n)
{
// ...
}
void func(int *arr, int n)
{
// ...
}
这里定义了两个函数,一个使用数组作为参数,一个使用指针作为参数。在函数内部,可以使用下标操作符[]或指针操作符*来访问数组元素。
在函数中返回一个指针数组时,需要使用静态数组或动态内存分配来创建数组。例如:
int *func()
{
static int arr[10];
// ...
return arr;
}
int *func()
{
int *arr = (int*)malloc(sizeof(int) * 10);
// ...
return arr;
}
这里定义了两个函数,一个使用静态数组创建指针数组,一个使用动态内存分配创建指针数组。在函数内部,可以使用下标操作符[]或指针操作符*来访问数组元素。
使用指针数组实现字符串的拷贝时,可以使用strcpy函数。例如:
char *str1 = "hello";
char *str2 = (char*)malloc(sizeof(char) * strlen(str1) + 1);
strcpy(str2, str1);
这里使用了malloc函数动态分配了内存,然后使用strcpy函数将str1中的字符串拷贝到str2中。
使用指针数组实现字符串的反转时,可以使用指针操作符*和下标操作符[]。例如:
char *str = "hello";
int len = strlen(str);
for (int i = 0; i < len / 2; i++) {
char tmp = *(str + i);
*(str + i) = *(str + len - i - 1);
*(str + len - i - 1) = tmp;
}
这里使用了指针操作符*和下标操作符[]来交换字符串中的字符。
使用指针数组实现字符串的比较时,可以使用strcmp函数。例如:
char *str1 = "hello";
char *str2 = "world";
int res = strcmp(str1, str2);
if (res < 0) {
printf("str1 < str2");
} else if (res > 0) {
printf("str1 > str2");
} else {
printf("str1 == str2");
}
这里使用了strcmp函数比较了两个字符串的大小。
使用指针数组实现字符串的连接时,可以使用strcat函数。例如:
char *str1 = "hello";
char *str2 = "world";
char *str3 = (char*)malloc(sizeof(char) * (strlen(str1) + strlen(str2) + 1));
strcpy(str3, str1);
strcat(str3, str2);
这里使用了malloc函数动态分配了内存,然后使用strcpy函数将str1中的字符串拷贝到str3中,最后使用strcat函数将str2中的字符串连接到str3中。
使用指针数组实现字符串的分割时,可以使用strtok函数。例如:
char str[] = "hello,world";
char *token = strtok(str, ",");
while (token != NULL) {
printf("%sn", token);
token = strtok(NULL, ",");
}
这里使用了strtok函数将字符串按照指定的分隔符分割成若干个子字符串,并依次输出。
使用指针数组实现二维数组的访问时,可以使用指针操作符*和下标操作符[]。例如:
int arr[3][4] = {{1,2,3,4},{5,6,7,8},{9,10,11,12}};
int **p = (int**)malloc(sizeof(int*) * 3);
for (int i = 0; i < 3; i++) {
*(p + i) = *(arr + i);
}
for (int i = 0; i < 3; i++) {
for (int j = 0; j < 4; j++) {
printf("%d ", *(*(p + i) + j));
}
printf("n");
}
这里使用了指针操作符*和下标操作符[]来访问二维数组中的元素。
使用指针数组实现动态内存分配时,可以使用malloc函数。例如:
int *arr[10];
for (int i = 0; i < 10; i++) {
*(arr + i) = (int*)malloc(sizeof(int));
**(arr + i) = i;
}
for (int i = 0; i < 10; i++) {
printf("%d ", **(arr + i));
}
这里使用了malloc函数动态分配了内存,并将分配的内存地址存储到指针数组中。
使用指针数组实现链表结构时,可以使用结构体和指针数组相结合的方式。例如:
typedef struct Node {
int data;
int next;
} Node;
Node arr[10];
int head = 0;
int tAIl = 0;
void add(int data)
{
arr[tail].data = data;
arr[tail].next = tail + 1;
tail++;
}
void print()
{
int p = head;
while (p != tail) {
printf("%d ", arr[p].data);
p = arr[p].next;
}
}
这里使用了一个结构体Node来表示链表的每个节点,然后使用指针数组arr来存储节点的信息。head和tail分别表示链表的头和尾,add函数用于向链表中添加元素,print函数用于遍历链表并输出。
使用指针数组实现树结构时,可以使用结构体和指针数组相结合的方式。例如:
typedef struct Node {
int data;
int left;
int right;
} Node;
Node arr[10];
int root = 0;
void add(int data)
{
int p = root;
while (1) {
if (data < arr[p].data) {
if (arr[p].left == -1) {
arr[p].left = tail;
break;
} else {
p = arr[p].left;
}
} else {
if (arr[p].right == -1) {
arr[p].right = tail;
break;
} else {
p = arr[p].right;
}
}
}
arr[tail].data = data;
arr[tail].left = -1;
arr[tail].right = -1;
tail++;
}
void print(int p)
{
if (p == -1) {
return;
}
printf("%d ", arr[p].data);
print(arr[p].left);
print(arr[p].right);
}
这里使用了一个结构体Node来表示树的每个节点,然后使用指针数组arr来存储节点的信息。root表示树的根节点,add函数用于向树中添加元素,print函数用于遍历树并输出。
请实现一个函数,将一个二维数组按照从小到大的顺序排序,并输出排序后的结果。要求使用指针数组实现。