原创 DeRoy 编程学习基地 2020-12-09


点击蓝字 关注我们

梦凡&粉丝---问题交流第一期_c++

前言

之前有个粉丝问了我一些问题,聊天截图如下

梦凡&粉丝---问题交流第一期_c++_02粉丝&梦凡

问题&粉丝

他的代码是这个样子的

void Pop(MazeStack* S, MSElemType e) {
    if (S->size == 0)
        exit(0);
    e = S->top->data;
    ***
    ***
}

一些不必要的代码我省略了,大意就是「通过传参获取栈顶元素」,然后一直拿不到数据。

梦凡&粉丝---问题交流第一期_c++_03问题

这种错误我想如果不熟悉C语言的新手都会犯,「基础不牢地动山摇」

答疑&梦凡

C语言指针那一章都先学swap函数实现交换两个变量的值的功能,你还记得吗?

void swap(int *a,int *b){
    int temp = *a;
    *a = *b;
    *b = temp;
}

在函数体内交换两个变量的值为什么要传指针?

因为「函数调用传递实参」「函数体内通过形参拷贝实参数据」,并且形参只在函数体内存在,出了函数就被释放掉了

那么同样的道理,你传个变量就想获取栈顶元素无异于「痴人说梦」,解决办法当然是「传指针」

那么关于指针传参这一块,又有讲究,那么从一道面试题讲起...

面试题

先看题,题目很简单,但是你知道「答案」吗?

/*
*
*   修改程序, 使得程序正常输出 1234567890 
*
*/

#include<stdio.h>
#include<stdlib.h>
#include<string.h>
void ApplyMemory(char* p)
{
    p = (char*)malloc(10);
}
int main()
{
    char* val = NULL;
    ApplyMemory(val);
    strcpy(val, "1234567890");
    printf("%s", val);
    free(val);
    return 0;
}

现在我们有了前面的指针铺垫,那么你能「正确修改程序」吗?

我非常明确的告诉你不只是修改申请内存的大小为11('\0'需要一个字节)

这个时候你可能就会想起函数里面申请一块内存之后需要通过「返回值」返回申请内存地址

修改1:

#include<stdio.h>
#include<stdlib.h>
#include<string.h>
charApplyMemory()
{
    char* p = (char*)malloc(11);
    return p;
}
int main()
{
    char* val = NULL;
    val = ApplyMemory();
    strcpy(val, "1234567890");
    printf("%s", val);
    free(val);
    return 0;
}

嗯,没问题,正确打印1234567890

那么这个时候面试官又问了,如果不通过函数返回值,你可不可以拿到申请的内存地址?

「思考良久」「怀疑人生」「情绪奔溃」...

其实很简单嘛,你把 *p当成一个值,那么像「交换函数」一样,传递这个值的指针,问题不就解决了吗?

这个时候一直「无人问津」「二级指针」跳了出来,我这么重要,你才想起我

修改2:

#include<stdio.h>
#include<stdlib.h>
#include<string.h>
void ApplyMemory(char** p)
{
    (*p) = (char*)malloc(11);
}
int main()
{
    char* val = NULL;
    ApplyMemory(&val);
    strcpy(val, "1234567890");
    printf("%s", val);
    free(val);
    return 0;
}

当然,我这里少了个对指针的判断,但是这不重要,重要的是这个「过程」你明白了吗?

如果你觉得你这个理解到位了,那么你可以试着完成一下我之前发布的「图书信息管理系统」,里面都是这个操作

/*删除节点*/
int deroy_list_delete(deroy_list_t** list_head, int num)
{
    int counter = 1;
    deroy_node_pt current = NULL;
    deroy_node_pt tmp = NULL;
 if (list_head == NULL || *list_head == NULL || (*list_head)->limit_size <= 0)
 {
  errno = EINVAL;
  exit(errno);
 }
 current = (*list_head)->head;
 while (counter < num)
 {
  counter++;
  current = current->next;
 }
 if (counter == 1)
 {
  /*头删*/
  tmp = (*list_head)->head;
  (*list_head)->head = (*list_head)->head->next;
  free(tmp);
  tmp = NULL;
  (*list_head)->limit_size--;
  return 0;
 }
 if ((*list_head)->limit_size == counter)
 {
  /*尾删*/
  tmp = (*list_head)->tail;
  (*list_head)->tail = (*list_head)->tail->prev;
  free(tmp);
  tmp = NULL;
  (*list_head)->tail->next = NULL;
  (*list_head)->limit_size--;
  return 0;
 }
 tmp = current;
 current->prev->next = current->next;
 current->next->prev = current->prev;
 free(tmp);
 tmp = NULL;
 (*list_head)->limit_size--;
 return 0;
}

贴点代码,有兴趣去看看,今日兴趣分享blog