寒假刷题之字符指针

简介: 寒假刷题之字符指针
 1.下面关于"指针"的描述不正确的是:( )😁

A.当使用free释放掉一个指针内容后,指针变量的值被置为NULL

B.32位系统下任何类型指针的长度都是4个字节

C.指针的数据类型声明的是指针实际指向内容的数据类型

D.野指针是指向未分配或者已经释放的内存地址

A.我们用malloc申请多少字节的内存空间,使用完我们用free释放空间,但是不会被置为NULL,我们需要手动置为空。 B/C/D正确
2.关于下面代码描述正确的是:( )char* p = "hello bit";😁

A.把字符串hello bit存放在p变量中

B.把字符串hello bit的第一个字符存放在p变量中

C.把字符串hello bit的第一个字符的地址存放在p变量中

D.*p等价于hello bit

C是正确的。D.*p等价于h
3.关于数组指针的描述正确的是:( )😁

A.数组指针是一种数组

B.数组指针是一种存放数组的指针

C.数组指针是一种指针

D.指针数组是一种指向数组的指针

C.正确。D.指针数组是一种指向指针的数组。B.数组指针是一种指向数组的指针。指针不可以存放数组!
4.下面哪个是数组指针( )😁

A.int** arr[10]

B.int (*arr[10])

C.char *(*arr)[10]

D.char(*)arr[10]

C正确。 C.是指针数组指针。A.B.D.由于[]的优先级高于*,所以*arr[],会先和[]结合变成数组,就不是指针了。
5.下面哪个是函数指针?( )😁

A.int* fun(int a, int b);

B.int(*)fun(int a, int b);

C.int (*fun)(int a, int b);

D.(int *)fun(int a, int n);

C正确。 A.是一个函数声明,参数是int,返回类型是int*。B.是一个函数声明,参数是int,返回类型是int*。C.是一个函数指针,*先和fun结合,参数是int,返回类型是int。D.是一个函数声明,参数是int,返回类型是int*。
6.定义一个函数指针,指向的函数有两个int形参并且返回一个函数指针,返回的指针指向一个有一个int形参且返回int的函数?下面哪个是正确的?( )😁

A.int (*(*F)(int, int))(int)

B.int (*F)(int, int)

C.int (*(*F)(int, int))

D.*(*F)(int, int)(int)

对A选项分析:存在*,这是一个指针,指向的是函数F,函数F有两个int形参且返回一个函数指针。返回的指针的类型是:int(*)(int),形参有int,返回int。选A。
7.在游戏设计中,经常会根据不同的游戏状态调用不同的函数,我们可以通过函数指针来实现这一功能,下面哪个是:一个参数为int *,返回值为int的函数指针( )😁

A.int (*fun)(int)

B.int (*fun)(int *)

C.int* fun(int *)

D.int* (*fun)(int *)

8.下面哪个代码是错误的?( )😁
#include <stdio.h>
int main()
{
  int *p = NULL;
  int arr[10] = {0};
  return 0;
}

image.gif

A.p = arr;

B.int (*ptr)[10] = &arr;

C.p = &arr[0];

D.p = &arr;

A.arr是数组首元素的地址放到整型指针p中,正确。B.取到数组的地址用数组指针接收,正确。C.取到数组首元素的地址存放到整型指针p中,正确。D.取到数组的地址存放到指针p中,按道理应该存放到数组指针中,所以 D是错误的。但是如果我们非要这么做,编译器也不会报错,只不过会进行一定转换,在语法上当然是错误的。
9.下面代码关于数组名描述不正确的是( )😁
int main()
{
  int arr[10] = {0};
  return 0;
}

image.gif

A.数组名arr和&arr是一样的

B.sizeof(arr),arr表示整个数组

C.&arr,arr表示整个数组

D.除了sizeof(arr)和&arr中的数组名,其他地方出现的数组名arr,都是数组首元素的地址。

A.数组名arr是首元素的地址,&arr是数组的地址。 A错误。B/C/D正确。
10.如何定义一个int类型的指针数组,数组元素个数为10个:( )😁

A.int a[10]

B.int (*a)[10]

C.int *a[10];

D.int (*a[10])(int);

A.是一个数组。B.是一个数组指针。C.是一个指针数组。D.是一个函数指针数组,类型为int(*)(int)。所以 C正确
11.设有以下函数void fun(int n,char *s){……},则下面对函数指针的定义和赋值均是正确的是:( )😁

A.void (*pf)(int,char); pf=&fun;

B.void (*pf)(int n,char *s); pf=fun;

C.void *pf(); *pf=fun;

D.void *pf(); pf=fun;

A.函数指针的形参是int和char*,A错误。 B正确。C.D.函数的形参错误,且不是一个指针。
12.杨氏矩阵💡

有一个数字矩阵,矩阵的每行从左到右是递增的,矩阵从上到下是递增的,请编写程序在这样的矩阵中查找某个数字是否存在。

要求:时间复杂度小于O(N);

1 2 3

4 5 6

7 8 9

进行分析:1.时间复杂度小于O(N),是我们运行程序进行次数的最坏情况,也就是说当有n个元素时,我们最多查找N次,此时时间复杂度就是O(N)。题目要求小于O(N)2.探寻杨氏矩阵规律:如上图,我们发现右上角的3和左下角的7最特殊。从右上角的3分析,3是这一行最大的元素,3是这一列最小的元素。假如我们需要寻找7是否存在,我们发现7>3,由于3是第一行最大的元素,说明7不在第一行。从第二行开始6是第二行最大的元素,6<7,说明7不在第二行。从第三行开始,7<9,9是第三行最大的元素,说明7在第三行,同时说明7不在第三行的第三列。从第三行的第二列开始,7<8,说明7不在第三行的第二列。从第三行第一列开始,7==7,说明7在第三行的第三列。同样从左下角推理道理相同。3.为什么特殊的元素规律不是1或是9呢?因为假如当我们寻找7时,我们从1的角度分析,7>1,说明7可能在第一行可能在第一列,此时我们无法确定7具体位置,不能进行对行和列的排除。
#include<stdio.h>
int Find(int arr[][3],int* r,int* c,int k)
{
    int x = 0;
    int y = *c - 1;
    int flag = 0;
    while (x<=*r-1&&y>=0)
    {
        if (arr[x][y] < k)
        {
            x++;
        }
        else if (arr[x][y] > k)
        {
            y--;
        }
        else
        {
            *r = x;
            *c = y;
            flag = 1;
            return 1;
        }
    }
    if (flag == 0)
    {
        return 0;
    }
}
int main()
{
    int arr[3][3] = { 1,2,3,4,5,6,7,8,9 };
    int k = 7;
    int x = 3;
    int y = 3;
    //int x,int y和函数参数的设计,即实现了输入值也实现了接收返回值。
    //由于return只能返回一个值,所以通过指针实现返回值的接收
    int ret=Find(arr, &x, &y,k);
    if (ret == 0)
    {
        printf("没找到!\n");
    }
    else
    {
        printf("找到了,下标为:[%d][%d]\n", x, y);
    }
    return 0;
}

image.gif

13.字符串左旋💡

实现一个函数,可以左旋字符串中的k个字符。

例如:

ABCD左旋一个字符得到BCDA

ABCD左旋两个字符得到CDAB

方法一
//字符会不断重复进行移动,效率不是很高
void left_move(char ch[], int k)
{
    int i = 0;
    int len = strlen(ch);
    //当旋转次数大于k次,实际进行旋转次数-k次,为防止重复进行:
    k %= len;
    //进行k次
    for (i = 0; i < k; i++)
    {
        //旋转一个字符
        //将第一个字符放到tmp中
        char tmp = ch[0];
        //将\n以及之前的字符向前移动
        int j = 0;
        for (j = 0; j < len - 1; j++)
        {
            ch[j] = ch[j + 1];
        }
        //将\n之前的字符覆盖成tmp中存放的最初第一个字符,\n在len-1处,\n之前一个就是len-2
        ch[len - 2] = tmp;
    }
}
int main()
{
    char ch[COUNT] = { 0 };
    printf("请输入字符串:\n");
    fgets(ch, sizeof(ch), stdin);
    int k = 0;
    printf("请输入左旋字符串个数:\n");
    scanf("%d", &k);
    left_move(ch, k);
    puts(ch);
    return 0;
}

image.gif

方法二算法规律:有一个字符串abcdef,逆序两个字符变成cdefab逆序左两个字符:ba cdef逆序右剩余字符:ba fedc整体逆序:cdefab
#include<assert.h>
//逆序字符串函数
void reverse(char*left,char*right)
{
    //保证指针有效性
    assert(left);
    assert(right);
    while (left < right)
    {
        char tmp = *left;
        *left = *right;
        *right = tmp;
        left++;
        right--;
    }
}
void left_move(char ch[], int k)
{
    int len = strlen(ch);
    k %= len;
    //逆序左,起始为数组首元素地址,逆序k个字符,终止位置是ch+k-1
    reverse(ch, ch + k - 1);
    //逆序右,起始位置是ch+k,终止位置ch+len-1(最后一个元素)
    reverse(ch+k, ch +len-1);
    //逆序整体
    reverse(ch,ch+len-1);
}
int main()
{
    char ch[] = "abcdef";
    int k = 0;
    printf("请输入左旋字符串个数:\n");
    scanf("%d", &k);
    left_move(ch, k);
    puts(ch);
    return 0;
}

image.gif

14.字符串旋转结果💡

写一个函数,判断一个字符串是否为另外一个字符串旋转之后的字符串。

例如:给定s1 =AABCD和s2 = BCDAA,返回1

给定s1=abcd和s2=ACBD,返回0.

AABCD左旋一个字符得到ABCDA

AABCD左旋两个字符得到BCDAA

AABCD右旋一个字符得到DAABC

//方法一
#include<string.h>
#include<assert.h>
void reverse(char*left,char*right)
{
    //保证指针有效性
    assert(left);
    assert(right);
    while (left < right)
    {
        char tmp = *left;
        *left = *right;
        *right = tmp;
        left++;
        right--;
    }
}
void left_move(char ch[], int k)
{
    int len = strlen(ch);
    k %= len;
    //逆序左
    reverse(ch, ch + k - 1);
    //逆序右
    reverse(ch+k, ch +len-1);
    //逆序整体
    reverse(ch,ch+len-1);
}
int is_left_move(char arr1[],char arr2[])
{
    int len1 = strlen(arr1);
    int len2 = strlen(arr2);
    if (len1 != len2)
    {
        return 0;
    }
    int i = 0;
    for (i = 0; i < len1; i++)
    {
        left_move(arr1, 1);
        if (strcmp(arr1, arr2) == 0)
        {
            return 1;
        }
    }
    return 0;
}
int main()
{
    char arr1[]= "AABCD";
    char arr2[] = "BCDAA";
    int ret=is_left_move(arr1, arr2);
    if (ret == 1)
    {
        printf("YES!\n");
    }
    else
    {
        printf("NO\n");
    }
    return 0;
}

image.gif

铺垫三个函数:
int main()
{
    char arr1[20] = "hello ";
    char arr2[20] = "hello ";
    //追加字符串,空间够大的前提
    strcat(arr1, "world!");
    //可控制追加字符串
    strncat(arr2, "world!", 3);
    //在arr1字符串中查找arr2是否存在
    //如果存在,则返回arr2在arr1中的位置(地址)
    //如果不存在,返回空指针(NULL)
    char*ret=strstr(arr1, arr2);
    puts(arr1);
    puts(arr2);
    if (ret == NULL)
    {
        printf("NO!\n");
    }
    else
    {
        printf("%s\n", ret);
    }
    return 0;
}

image.gif

目录
相关文章
|
9月前
|
算法 容器
OJ刷题日记:2、双指针(2)
OJ刷题日记:2、双指针(2)
68 0
|
9月前
|
存储 编译器 C语言
函数指针&&数组指针&&数组传参的本质&&字符指针(进阶篇)
函数指针&&数组指针&&数组传参的本质&&字符指针(进阶篇)
154 0
|
9月前
|
存储 C++
使用字符指针变量和字符数组的比较
使用字符指针变量和字符数组的比较
90 0
|
6月前
|
Python
【Leetcode刷题Python】138. 复制带随机指针的链表
LeetCode上题目“138. 复制带随机指针的链表”的Python解决方案,包括两种方法:一种是在每个节点后复制一个新节点然后再分离出来形成新链表;另一种是构建一个字典来跟踪原始节点与其副本之间的映射关系,从而处理新链表的构建。
38 1
|
9月前
|
算法 测试技术 容器
【刷题】双指针入门
经过这四道题目的洗礼,我大概对双指针有了初步印象,接下来我会继续努力!!!
99 13
【刷题】双指针入门
|
7月前
|
算法 Java C语言
刷题训练之双指针问题
刷题训练之双指针问题
49 0
|
9月前
|
存储 C语言
字符指针变量与字符数组的比较
字符指针变量与字符数组的比较
78 3
|
9月前
|
存储 C语言
字符指针作为函数参数
字符指针作为函数参数
83 2
|
9月前
DAY-2 | 哈希表、指针与区间划分:字符种数统计问题
```markdown ## 题干 [牛客网链接](https://www.nowcoder.com/practice/eb94f6a5b2ba49c6ac72d40b5ce95f50) ## 题解 1. **查表法(哈希表)**:利用数组标记出现过的 ASCII 值小于127的字符,首次出现计数,重复则忽略。 2. **指针与区间划分(回头法)**:遍历字符串,对每个字符检查其前所有字符是否重复,重复则不计数。 ## 方法总结 - 哈希表在去重问题中非常实用,可多做相关练习。 - 使用`continue`时注意避免死循环,确保循环变量会改变。 - 多回顾此类问题以巩固理解。 ```
62 2
|
9月前
|
算法 测试技术 容器
【刷题】双指针进阶
请看入门篇 :双指针入门
46 0
【刷题】双指针进阶