C语言习题练习5——指针
Posted Huang_ZhenSheng
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了C语言习题练习5——指针相关的知识,希望对你有一定的参考价值。
目录
6.写一个函数,判断一个字符串是否为另外一个字符串旋转之后的字符串
7.有一个数字矩阵,矩阵的每行从左到右是递增的,矩阵从上到下是递增的,请编写程序在这样的矩阵中查找某个数字是否存在
1.一维数组
int main()
{
//sizeof(数组名)-数组名表示整个数组,计算的是整个数组的大小
//&数组名-数组名表示整个数组,取出的是整个数组的地址
//除此之外,所有的数组名都是数组首元素的地址
int a[] = { 1, 2, 3, 4 };
printf("%d\\n", sizeof(a));//16
printf("%d\\n", sizeof(a + 0));//(a+0)是第一个元素的地址:4/8
printf("%d\\n", sizeof(*a));//*a是数组的第一个元素:4,计算的是第一个元素的大小
printf("%d\\n", sizeof(a + 1));//第二个元素的地址:4/8,sizeof(a+1)计算的是地址的大小
printf("%d\\n", sizeof(a[1]));//计算的是第二个元素的大小://4
printf("%d\\n", sizeof(&a));//&a虽然是数组的地址,但是也是地址,sizeof(&a)计算的也是一个地址的大小:4/8
printf("%d\\n", sizeof(*&a));// int(*p)[4] = &a,解引用:16
printf("%d\\n", sizeof(&a + 1));//跳过整个数组之后,下个空间的起始地址:4/8
printf("%d\\n", sizeof(&a[0]));//第一个元素的地址:4/8
printf("%d\\n", sizeof(&a[0] + 1));//第二个元素的地址:4/8
return 0;
}
2.字符数组
#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
int main()
{
char arr[] = { 'a', 'b', 'c', 'd', 'e', 'f' };
printf("%d\\n", sizeof(arr));//6
printf("%d\\n", sizeof(arr + 0));//4/8
printf("%d\\n", sizeof(*arr));//1
printf("%d\\n", sizeof(arr[1]));//1
printf("%d\\n", sizeof(&arr));//4/8
printf("%d\\n", sizeof(&arr + 1));//4/8
printf("%d\\n", sizeof(&arr[0] + 1));//b的地址 :4/8
printf("%d\\n", strlen(arr));//不知道什么时候遇到‘\\0’:随机值
printf("%d\\n", strlen(arr + 0));//随机值
printf("%d\\n", strlen(*arr));//出错,传的地址有问题
printf("%d\\n", strlen(arr[1]));//出错,传的地址有问题
printf("%d\\n", strlen(&arr));//随机值
printf("%d\\n", strlen(&arr + 1));//随机值
printf("%d\\n", strlen(&arr[0] + 1));//随机值
char arr[] = "abcdef";//[a,b,c,d,e,f,\\0]
printf("%d\\n", sizeof(arr));//7
printf("%d\\n", sizeof(arr + 0));//4/8
printf("%d\\n", sizeof(*arr));//1
printf("%d\\n", sizeof(arr[1]));//1
printf("%d\\n", sizeof(&arr));//4/8
printf("%d\\n", sizeof(&arr + 1));//4/8
printf("%d\\n", sizeof(&arr[0] + 1));//4/8
printf("%d\\n", strlen(arr));//6
printf("%d\\n", strlen(arr + 0));//6
printf("%d\\n", strlen(*arr));//出错
printf("%d\\n", strlen(arr[1]));//出错
printf("%d\\n", strlen(&arr));//6
printf("%d\\n", strlen(&arr + 1));//随机值
printf("%d\\n", strlen(&arr[0] + 1));//5
char *p = "abcdef";
printf("%d\\n", sizeof(p));//4/8
printf("%d\\n", sizeof(p + 1));//4/8
printf("%d\\n", sizeof(*p));//1
printf("%d\\n", sizeof(p[0]));//1--->p[0] = *(p+0)
printf("%d\\n", sizeof(&p));//4/8
printf("%d\\n", sizeof(&p + 1));//4/8
printf("%d\\n", sizeof(&p[0] + 1));//4/8
printf("%d\\n", strlen(p));//6
printf("%d\\n", strlen(p + 1));//5
printf("%d\\n", strlen(*p));//出错
printf("%d\\n", strlen(p[0]));//出错
printf("%d\\n", strlen(&p));//随机值!!!
printf("%d\\n", strlen(&p + 1));//随机值
printf("%d\\n", strlen(&p[0] + 1));//5
return 0;
}
3.二维数组
#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
int main()
{
int a[3][4] = { 0 };
printf("%d\\n", sizeof(a));//48
printf("%d\\n", sizeof(a[0][0]));//4
printf("%d\\n", sizeof(a[0]));
//数组名a[0]单独放在sizeof内部:16
//a[0]表示的整个第一行,sizeof(a[0])计算的就是第一行的大小
printf("%d\\n", sizeof(a[0]/*第一个元素的地址*/ + 1));//4
//a[0]作为数组名并没有单独放在sizeof内部,也没有取地址,所以a[0]就是第一行第一个元素的地址
printf("%d\\n", sizeof(*(a[0] + 1)));//4
printf("%d\\n", sizeof(a + 1));
//a是二维数组的数组名,并没有取地址
//也没有单独放在sizeof内部,所以a就表示二维数组首元素的地址,即第一行的地址:4
printf("%d\\n", sizeof(*(a + 1)));//*(a+1) = a[1] :16
printf("%d\\n", sizeof(&a[0] + 1));//4
printf("%d\\n", sizeof(*(&a[0] + 1)));//16
printf("%d\\n", sizeof(*a));//16
printf("%d\\n", sizeof(a[3]));//16
//a[3]其实是第四行的数据名(如果有的话)
//所以其实是不存在的,也能通过类型计算大小
//sizeof()内部的表达式是不算的
return 0;
}
下面代码的输出结果是2,5,因为sizeof()内部不参与计算!
int main()
{
short s = 5;
int a = 4;
printf("%d\\n",sizeof(s = a+6));
printf("%d\\n",s);
return 0;
}
总结:数组名的意义
1.sizeof(数组名),这里的数组名表示整个数组,计算的是整个数组的大小
2.&数组名,这里的数组名表示整个数组,取出的是整个数组的地址
3.除此之外的所有的数组名都表示首元素的地址
4.指针系列笔试题 (1-8题)
第一题:
int main()
{
int a[5] = { 1, 2, 3, 4, 5 };
int *ptr = (int *)(&a + 1);
printf("%d,%d", *(a + 1), *(ptr - 1));
return 0;
}
第二题:
//考察的是:指针类型决定指针的运算!
//由于还没学习结构体,这里告知结构体的大小是20个字节
struct Test
{
int Num;
char *pcName;
short sDate;
char cha[2];
short sBa[4];
}*p;
//假设p 的值为0x100000。 如下表表达式的值分别为多少?
int main()
{
printf("%p\\n", p + 0x1);
//结构体类型指针+1,0x100014
printf("%p\\n", (unsigned long)p + 0x1);
//P强制转化成整型类型 加1就是加1:0x100001
printf("%p\\n", (unsigned int*)p + 0x1);
//p指向无符号整型指针,加1跳过一个整型变量大小即加4:0x100004
return 0;
}
第三题:
int main()
{
int a[4] = { 1, 2, 3, 4 };
int *ptr1 = (int *)(&a + 1);
int *ptr2 = (int *)((int)a + 1);
printf("%x,%x", ptr1[-1], *ptr2);
return 0;
}
0x20---> 32 int+1 = 33--->0x21---->向后走了一个字节
第四题:
int main()
{
int a[3][2] = { (0, 1), (2, 3), (4, 5) };
int *p;
p = a[0];//表示的是首元素的地址
printf("%d", p[0]);//p[0] = *(p+0)
return 0;
}
第五题:
int main()
{
int a[5][5];
int(*p)[4];
p = a;
printf("%p,%d\\n", &p[4][2] - &a[4][2], &p[4][2] - &a[4][2]);
return 0;
}
第六题:
int main()
{
int aa[2][5] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
int *ptr1 = (int *)(&aa + 1);
int *ptr2 = (int *)(*(aa + 1));
//aa是数组名,数组名相当于首元素的地址(第一行的地址)
//*(aa + 1)==aa[1],整型地址赋给ptr2
printf("%d,%d", *(ptr1 - 1), *(ptr2 - 1));
return 0;
}
答案:10 和 5
第七题:
int main()
{
char* a[] = { "work", "at", "alibaba" };
char** pa = a;
//a代表首元素的地址,首元素是char*,首元素的地址是char**,放到pa里面去
pa++;
printf("%s\\n", *pa);
return 0;
}
第八题(BOSS!):
int main()
{
char* c[] = { "ENTER", "NEW", "POINT", "FIRST" };
char** cp[] = { c + 3, c + 2, c + 1, c };
char*** cpp = cp;
printf("%s\\n", **++cpp);
printf("%s\\n", *--*++cpp + 3);
printf("%s\\n", *cpp[-2] + 3);//==> **(cpp-2)+3 同理
printf("%s\\n", cpp[-1][-1] + 1);//*(*(cpp-1)-1)+1
return 0;
}
答案:POINT ER ST EW
5.实现一个函数,可以左旋字符串中的k个字符。
例如:
ABCD左旋一个字符得到BCDA
ABCD左旋两个字符得到CDAB
方法1:
void left_swap(char* str, int n)
{
int i = 0;
int len = strlen(str);
for (i = 0; i < n; i++)
{
//每次左旋转一个字符
char tmp = *str;
//后边的len-1个字符往前挪动
int j = 0;
for (j = 0; j < len; j++)
{
*(str + j) = *(str + j + 1);
}
//tmp放在最后
*(str + len - 1) = tmp;
}
}
int main()
{
char arr[] = "ABCDEFG";
int num = 0;
printf("请输入要旋转的个数:");
scanf(" %d",&num);
left_swap(arr, num);
printf("%s",arr);
return 0;
}
方法2:(三步逆序)左边逆序,右边逆序,整体逆序
#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
#include<string.h>
#include<assert.h>
//1左边逆序 2右边逆序 3整体逆序
void reverse(char* left, char* right)
{
assert(left);
assert(right);
while (left < right)
{
char tmp = *left;
*left = *right;
*right = tmp;
left++;
right--;
}
}
void left_swap(char* str, int num)
{
assert(str);
int n = strlen(str);
reverse(str, str+num-1);
reverse(str+num, str+n-1);
reverse(str, str+n-1);
}
int main()
{
char arr[] = "ABCDEFG";
printf("请输入要旋转的个数:");
int num = 0;
scanf("%d",&num);
left_swap(arr, num);
printf("%s\\n",arr);
return 0;
}
字符串右旋:
#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
#include<string.h>
#include<assert.h>
void right_roate(char* str,int num)
{
assert(str);
int n = strlen(str);
int i = 0;
for (i = 0; i < num; i++)
{
char tmp = *(str + n - 1);
for (int j = 0; j < n-1; j++)
{
*(str + n-1-j) = *(str + n-2-j);
}
*str = tmp;
}
}
int main()
{
char arr[] = "AABB";
printf("请输入要旋转的数:");
int num = 0;
scanf("%d", &num);
right_roate(arr,num);
printf("%s",arr);
}
6.写一个函数,判断一个字符串是否为另外一个字符串旋转之后的字符串
例如:给定s1 =AABCD和s2 = BCDAA,返回1
给定s1=abcd和s2=ACBD,返回0.
AABCD左旋一个字符得到ABCDA
AABCD左旋两个字符得到BCDAA
AABCD右旋一个字符得到DAABC
方法1:
#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
#include<string.h>
int is_left_swap(char* str1, char* str2)
{
int i = 0;
int n = strlen(str1);
for (i = 0; i < n; i++)
{
//每次左旋转一个字符
char tmp = *str1;
//后边的n-1个字符往前挪动
int j = 0;
for (j = 0; j < n-1; j++)
{
*(str1 + j) = *(str1 + j + 1);
}
//tmp放在最后
*(str1 + n - 1) = tmp;
if (strcmp(str1, str2) == 0)
{
return 1;
}
}
return 0;
}
int main()
{
char arr1[] = "AABCD";
char arr2[] = "BCDAA";
int ret = is_left_swap(arr1,arr2);
if (ret == 1)
{
printf("yes\\n");
}
else
{
printf("no\\n");
}
return 0;
}
方法2:
#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
#include<string.h>
int is_left_swap(char* str1, char* str2)
{
//长度不相等,肯定不是旋转得到的
if (strlen(str1) != strlen(str2))
{
return 0;
}
//1.str1字符串的后边追加一个str1
//AABCDAABCD
int len = strlen(str1);
strncat(str1,str2,len);
//2.判断str2是否为str1的字串
char* ret = strstr(str1, str2);
return ret!= NULL;
}
int main()
{
char arr1[] = "AABCD";//改为char arr1[20] = "AABCD",不然会出问题
char arr2[] = "BCDAA";
int ret = is_left_swap(arr1,arr2);
if (ret == 1)
{
printf("yes\\n");
}
else
{
printf("no\\n");
}
return 0;
}
7.有一个数字矩阵,矩阵的每行从左到右是递增的,矩阵从上到下是递增的,请编写程序在这样的矩阵中查找某个数字是否存在
要求:时间复杂度小于O(N); 遍历数组方法不满足
#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
#include<string.h>
int Find(int arr[3][3], int* r, int* c, int k)
{
int x = 0;
int y = *c - 1;
while (x <= 2 && y >= 0)
{
if (arr[x][y] < k)
{
x++;
}
else if (arr[x][y] > k)
{
y--;
}
else
{
*r = x;
*c = y;
return 1;
}
}
return 0;
}
int main()
{
int arr[3][3] = { 1, 2, 3, 4, 5, 6, 7, 8, 9 };
int k = 8;
int x = 3;
int y = 3;
//&x,&y作用:1.传入参数 2.带回值
int ret = Find(arr, &x, &y, k);
if (ret == 1)
{
printf("找到了\\n");
printf("%d %d",x,y);
}
else
{
printf("找不到\\n");
}
return 0;
}
以上是关于C语言习题练习5——指针的主要内容,如果未能解决你的问题,请参考以下文章