• AI人机对话-无能版


    在这里插入图片描述

    AI人机对话-无能版

    • 本质就是中文字符截取
    • 64位的Linux系统下,编译器utf-8编码格式下,中文字符占3字节

    text.c

    #include 
    #include 
    #include 
    #define SIZE 128
    int main(int argc, char const *argv[])
    {
        char *str = (char *)malloc(SIZE);
        memset(str, 0, sizeof(SIZE));
        char str1[SIZE] = {0};
        char buf[SIZE] = {0};
        int i,flag=0;
        printf("\n");
        while (1)
        {
            memset(str1, 0, sizeof(SIZE));
            printf("input>");
            scanf("%s", str);
            printf("\n");
            for (i = 0; str[i] != 0;)
            {
                if (!((str[i] >= '0' && str[i] <= '9') || (str[i] >= 'a' && str[i] <= 'z')) || (str[i] >= 'A' && str[i] <= 'Z'))
                {
    
                    memset(buf, 0, sizeof(buf));
                    if (str[i] != '?' && (!(str[i] >= '!' && str[i] <= '/')))
                        sprintf(buf, "%c%c%c", str[i], str[i + 1], str[i + 2]);
    
                    if (strcmp(buf, "吗") != 0 && strcmp(buf, "?") != 0) //注意:中文?(3字节),和英文?(1字节)
                        strcat(str1, buf);
                    else if (strcmp(buf, "?") == 0||strcmp(buf, "吗") == 0)
                    {
                        if (flag==0) 
                            strcat(str1, "!");
                        flag=1;
                    }
                        
                    i += 3;
                }
                else
                {
                    memset(buf, 0, sizeof(buf));
                    sprintf(buf, "%c", str[i]);
                    strcat(str1, buf);
                    i++;
    
                }
                    
            }
            printf("AI: [ %s ]\n", str1);
            printf("\n");
            flag=0;
        }
        free(str);
        return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55

    以下C++面试题占字数

    3、内存问题
    1.

    void GetMemory(char *p){
        p = new char[100];
    }
    void Test(void){
        char *str = NULL;
        GetMemory(str);
        strcpy(str, "hello world");
        printf(str);
    }请问运行 Test 函数会有什么样的结果? 
    ---------------------------------------------------------------------
    void GetMemory(char **p) // char *p就是错的,因为p没有传出来
    {
        *p = new char[100];
    }
    void Test(void)
    {
        char *str = NULL;
        GetMemory(&str);
        strcpy(str, "hello world");
        printf(str);
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21

    [ 运行错误 ] 传入GetMemory(char* p)函数的形参为字符串指针,在函数内部修改形参并不能真正的改变传入形参的值。执行完后的str仍然为NULL。
    实质:编译器总是要为每个参数制作临时副本,指针参数p的副本是_p,编译器使_p=p。如果函数体内的程序修改了_p的内容,就导致参数p的内容作相应的修改,这就是指针可以用作输出参数的原因。在本例中,_p申请了新的内存,只是把_p所指的内存地址改变了,但是p丝毫未变。所以GetMemory并不能输出任何东西。事实上,每执行一次GetMemory就会泄露一块内存,因为没有用free释放内存。

    char *GetMemory(void)
    {
        char p[] = "hello world";
        return p; /* char *p = (char *)malloc(100);strcpy(p,"Hello World!");这才是对的*/
    }//因为p的生命周期在GetMemory函数执行完了就被销毁了,str指向的是个野指针
    void Test(void)
    {
        char *str = NULL;
        str = GetMemory();
        printf(str);
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    **[运行错误 ]**GetMemory中的p[ ]为函数内的局部自动变量,在函数调用返回后,内存已经被释放。所以打印出来的数据不是我们要求打印的数据,但是返回的指针指向的地址是一定的。这是很多程序员常犯的错误,其根源在于不理解变量的生存期。用调试器逐步跟踪Test,发现执行str=GetMemory语句后str不再是NULL指针,但是str的内容不是“hello world”,而是垃圾。

    void GetMemory( char **p, int num )  
    {  
     *p = (char *) malloc( num );  
    }  
      
    void Test( void )  
    {  
     char *str = NULL;  
     GetMemory( &str, 100 );  
     strcpy( str, "hello" );   
     printf( str );   
    }  
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    [运行正确,但有内存泄露 ] 避免了题目一的问题,传入GetMemory的参数为字符串指针的指针,但是在GetMemory中执行申请及赋值语句
    *p = (char *) malloc( num );
    后未判断内存是否申请成功,应加上
    if ( *p == NULL ){
     ...//进行申请内存失败处理
    }

    void Test( void ){
     char *str = new char[100];
     strcpy( str, "hello" );
     free( str );
     if (str != NULL){
            strcpy(str, "world");
            printf(str);
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    [运行正确,但有内存泄露 ] < 4> 与 < 3> 存在同样的问题,在执行malloc后未进行内存是否申请成功的判断。此外,在free(str)后未置str为空,导致可能变成一个“野指针”,应加上
    str = NULL;
    < 3> 的Test函数中也未对malloc的内存进行释放。

    class Person
    {
    public:
        Person(int weight,int num)
        {
            m_weight=weight;
            m_height = new int;
            *m_height = num;
            cout << "num"<< endl;
        }
        ~Person()
        {
            if (m_height != NULL)
            {
                delete m_height;
                m_height = NULL;
                cout << "~Person"<< endl;
            }
        }
    public:
        int m_weight;
        int *m_height;
    };
    void test01()
    {
        Person  p1(50,10);
        cout << " 1高度: " << *p1.m_height << endl;
        Person  p2(p1);
        cout << " 2高度: " << *p2.m_height << endl;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30

    错误的内在逻辑图例:
    在这里插入图片描述

    class AA{
    public:
        virtual void fun1(){cout<<"AA_fun1"<<endl;}
        void fun2(){cout<<"AA_fun2"<<endl;}
    };
    class BB:public AA{
    public:
        void fun1(){cout<<"BB_fun1"<<endl;}
        void fun2(){cout<<"BB_fun2"<<endl;}
    };
    void showFun(AA* aa){
        if (aa != NULL){
            aa->fun1();
            aa->fun2();
        }
    }
    int main(){
        BB* cl = new BB();
        showFun(dynamic_cast<AA*>(cl));
        delete cl;
        return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22

    动态类型转换:dynamic_cast(exp)
    动态类型转换是依赖于虚函数的与继承关系,没有虚函数,就无法使用动态类型转换。
    dynamic_cast是一个安全类型转换,因为他是依赖于函数实现动态转型。因为虚表中的第一个Slot位置保存了类型运行识别信息。
    这个虚表的结构:
    在这里插入图片描述

  • 相关阅读:
    基于springboot+vue的中小企业财务管理系统(源码+论文)
    leetcode-数组中的第K个最大元素-215-最大堆
    滑动谜题 -- BFS
    opencv 图像的缩放(放大,缩小),翻转与旋转
    常见vue问题
    分类预测 | MATLAB实现NGO-CNN北方苍鹰算法优化卷积神经网络数据分类预测
    【机器学习300问】118、循环神经网络(RNN)的基本结构是怎样的?
    Linux多线程服务端编程:使用muduo C++网络库 学习笔记 第三章 多线程服务器的适用场合与常用编程模型
    教你2种常用的电商高并发处理解决方案
    聊聊设计模式——迭代器模式
  • 原文地址:https://blog.csdn.net/qq_47355554/article/details/126356174