程序如下:
#include <iostream>
#include <vector>
#include <list>
using namespace std;
class Subjects;
class Observe
{
public:
virtual void update(Subjects* t)=0;
virtual char* getName()=0;
};
class Subjects
{
public:
virtual void addobs(Observe* o)=0;
virtual char* getPhone()=0;
virtual void notice()=0;
};
class Teacher;
class Student:public Observe
{
public:
Student(char* _name)
{
name =_name;
}
char* getName()
{
return name;
}
void update(Subjects* t)
{
phone = t->getPhone();
show();
}
void show()
{
cout<<getName()<<":The teacher's phone number is "<<phone<<endl;
}
private:
char* name;
char* phone;
};
class Teacher:public Subjects
{
public:
Teacher()
{
phone = "";
}
void addobs(Observe* o)
{
st.push_back(o);
}
void setPhone(char* phone)
{
this->phone = phone;
notice();
}
char* getPhone()
{
return phone;
}
void notice()
{
for(vector<Observe*>::iterator iter = st.begin();iter!=st.end();iter++)
{
(*iter)->update(this);
}
}
private:
char* phone;
vector<Observe*> st;
};
int main(int argc,char* argv[])
{
Teacher* teacher = new Teacher();
int i;
for(i=0;i<10;i++)
{
char strName[20];
sprintf(strName,"student%d",i+1);//这一句出错了,太奇怪了
Student* stu = new Student(strName);
teacher->addobs(stu);
}
teacher->setPhone("68948888");
cout<<"After setPhone(\"68947777\")"<<endl;
teacher->setPhone("68947777");
}
期望结果为:
student1:The teacher's phone number is 68948888
student2:The teacher's phone number is 68948888
student3:The teacher's phone number is 68948888
student4:The teacher's phone number is 68948888
student5:The teacher's phone number is 68948888
student6:The teacher's phone number is 68948888
student7:The teacher's phone number is 68948888
student8:The teacher's phone number is 68948888
student9:The teacher's phone number is 68948888
student10:The teacher's phone number is 68948888
After setPhone("68947777")
student1:The teacher's phone number is 68947777
student2:The teacher's phone number is 68947777
student3:The teacher's phone number is 68947777
student4:The teacher's phone number is 68947777
student5:The teacher's phone number is 68947777
student6:The teacher's phone number is 68947777
student7:The teacher's phone number is 68947777
student8:The teacher's phone number is 68947777
student9:The teacher's phone number is 68947777
student10:The teacher's phone number is 68947777
实际结果却是:
student10:The teacher's phone number is 68948888
student10:The teacher's phone number is 68948888
student10:The teacher's phone number is 68948888
student10:The teacher's phone number is 68948888
student10:The teacher's phone number is 68948888
student10:The teacher's phone number is 68948888
student10:The teacher's phone number is 68948888
student10:The teacher's phone number is 68948888
student10:The teacher's phone number is 68948888
student10:The teacher's phone number is 68948888
After setPhone("68947777")
student10:The teacher's phone number is 68947777
student10:The teacher's phone number is 68947777
student10:The teacher's phone number is 68947777
student10:The teacher's phone number is 68947777
student10:The teacher's phone number is 68947777
student10:The teacher's phone number is 68947777
student10:The teacher's phone number is 68947777
student10:The teacher's phone number is 68947777
student10:The teacher's phone number is 68947777
student10:The teacher's phone number is 68947777
经过调试以后,发现出错语句竟然在sprintf(strName,"student%d",i+1);我在这一句设了断点,发现在次之前,st中的各个元素是正确的,执行这一句之后就出错了。举个例子,当第一次循环(即i=0)时,执行完teacher->addobs(stu)后,st中含有一个指针元素,其name为“student1”,即st[0]->name=“student1”;第二次循环时,当执行完sprintf(strName,"student%d",i+1)后,竟然发现st[0]->name=“student2”。当第二次循环执行完毕后,结果自然变为了st[0]->name=“student2”,st[1]->name=“student2”,而第三次循环执行完出错的那一句后,结果同样奇怪地变为了st[0]->name=“student3”,st[1]->name=“student3”,这是为什么?sprintf(strName,"student%d",i+1)是怎么影响到st的?
7 个解决方案
#1
Student(char* _name)
{
name =_name;
}
char*的复制不要这样做,用strncpy
我估计是由于所有的name都指向的是main里面的char strName[20]所导致
{
name =_name;
}
char*的复制不要这样做,用strncpy
我估计是由于所有的name都指向的是main里面的char strName[20]所导致
#2
char strName[20];
你这就这个一个数组,写来写去,不就重复在这些么,不久覆盖了。
结果就是最后那个数 即9+1=10;
你这就这个一个数组,写来写去,不就重复在这些么,不久覆盖了。
结果就是最后那个数 即9+1=10;
#3
name是指针不是数组所以改一处就会影响其他
#4
改下试试
char* strName[10][20];
sprintf(strName[i],"student%d",i+1);//后面打印的时候也要相应的改下。
#5
改为
char *strName = new char[20];
char *strName = new char[20];
#6
原因有两个:
1.
在你的代码里,Student的构造函数将一个指针传给了char* name
这样做是非常危险的,因为你传的指针随时可能在其他代码被更改。这样你建立的这个student对象里面的name也随时可能被改掉。
而且有可能这个指针后来在别的地方被释放掉了,接下来再访问这个name就是没有意义的。
2.
在这里有一个局部的char数组。每次for循环进入,这个数组strName[20]都是在相同的内存地址,比如设为0x12345678。
也就是说,你每进入一次循环,就把内存0x12345678的字符串重新格式化了,然后把这个地址赋给了一个student。
这样的话,循环结束后,所有10个student对象里面的name都指着这个0x12345678的字符串,所以都是"student10".
第二个问题也是由第一部分引起的。对象里面的char*不能这样直接赋值,你可以考虑使用std::string代替。
1.
class Student:public Observe
{
public:
Student(char* _name)
{
name =_name;
}
...
private:
char* name;
char* phone;
};
在你的代码里,Student的构造函数将一个指针传给了char* name
这样做是非常危险的,因为你传的指针随时可能在其他代码被更改。这样你建立的这个student对象里面的name也随时可能被改掉。
而且有可能这个指针后来在别的地方被释放掉了,接下来再访问这个name就是没有意义的。
2.
for(i=0;i<10;i++)
{
char strName[20];
sprintf(strName,"student%d",i+1);//这一句出错了,太奇怪了
Student* stu = new Student(strName);
teacher->addobs(stu);
}
在这里有一个局部的char数组。每次for循环进入,这个数组strName[20]都是在相同的内存地址,比如设为0x12345678。
也就是说,你每进入一次循环,就把内存0x12345678的字符串重新格式化了,然后把这个地址赋给了一个student。
这样的话,循环结束后,所有10个student对象里面的name都指着这个0x12345678的字符串,所以都是"student10".
第二个问题也是由第一部分引起的。对象里面的char*不能这样直接赋值,你可以考虑使用std::string代替。
#7
1 char name[200];
2 重复擦写了strName
2 重复擦写了strName
#1
Student(char* _name)
{
name =_name;
}
char*的复制不要这样做,用strncpy
我估计是由于所有的name都指向的是main里面的char strName[20]所导致
{
name =_name;
}
char*的复制不要这样做,用strncpy
我估计是由于所有的name都指向的是main里面的char strName[20]所导致
#2
char strName[20];
你这就这个一个数组,写来写去,不就重复在这些么,不久覆盖了。
结果就是最后那个数 即9+1=10;
你这就这个一个数组,写来写去,不就重复在这些么,不久覆盖了。
结果就是最后那个数 即9+1=10;
#3
name是指针不是数组所以改一处就会影响其他
#4
改下试试
char* strName[10][20];
sprintf(strName[i],"student%d",i+1);//后面打印的时候也要相应的改下。
#5
改为
char *strName = new char[20];
char *strName = new char[20];
#6
原因有两个:
1.
在你的代码里,Student的构造函数将一个指针传给了char* name
这样做是非常危险的,因为你传的指针随时可能在其他代码被更改。这样你建立的这个student对象里面的name也随时可能被改掉。
而且有可能这个指针后来在别的地方被释放掉了,接下来再访问这个name就是没有意义的。
2.
在这里有一个局部的char数组。每次for循环进入,这个数组strName[20]都是在相同的内存地址,比如设为0x12345678。
也就是说,你每进入一次循环,就把内存0x12345678的字符串重新格式化了,然后把这个地址赋给了一个student。
这样的话,循环结束后,所有10个student对象里面的name都指着这个0x12345678的字符串,所以都是"student10".
第二个问题也是由第一部分引起的。对象里面的char*不能这样直接赋值,你可以考虑使用std::string代替。
1.
class Student:public Observe
{
public:
Student(char* _name)
{
name =_name;
}
...
private:
char* name;
char* phone;
};
在你的代码里,Student的构造函数将一个指针传给了char* name
这样做是非常危险的,因为你传的指针随时可能在其他代码被更改。这样你建立的这个student对象里面的name也随时可能被改掉。
而且有可能这个指针后来在别的地方被释放掉了,接下来再访问这个name就是没有意义的。
2.
for(i=0;i<10;i++)
{
char strName[20];
sprintf(strName,"student%d",i+1);//这一句出错了,太奇怪了
Student* stu = new Student(strName);
teacher->addobs(stu);
}
在这里有一个局部的char数组。每次for循环进入,这个数组strName[20]都是在相同的内存地址,比如设为0x12345678。
也就是说,你每进入一次循环,就把内存0x12345678的字符串重新格式化了,然后把这个地址赋给了一个student。
这样的话,循环结束后,所有10个student对象里面的name都指着这个0x12345678的字符串,所以都是"student10".
第二个问题也是由第一部分引起的。对象里面的char*不能这样直接赋值,你可以考虑使用std::string代替。
#7
1 char name[200];
2 重复擦写了strName
2 重复擦写了strName