#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;
}
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);
}
[ 运行错误 ] 传入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);
}
**[运行错误 ]**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 );
}
[运行正确,但有内存泄露 ] 避免了题目一的问题,传入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);
}
}
[运行正确,但有内存泄露 ] < 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;
}
错误的内在逻辑图例:
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;
}
动态类型转换:dynamic_cast(exp)
动态类型转换是依赖于虚函数的与继承关系,没有虚函数,就无法使用动态类型转换。
dynamic_cast是一个安全类型转换,因为他是依赖于函数实现动态转型。因为虚表中的第一个Slot位置保存了类型运行识别信息。
这个虚表的结构: