case 3:后面必须加break;case 3:
pbook.Erase();
break;
pbook.Erase();
break;
解决方案 »
- 关于菜单menu的应用
- 简单的问题不简单
- 高手进来看一下,复杂数组问题
- 关于HttpWebRequest的简单问题
- DataGridView如何实现增删改查?谢谢~~~~~~~~~
- 如何在子类中屏蔽父类的事件和方法?
- 新人 求助大神 为什么程序运行到return ExecuteNonQuery ()老是自动跳出
- .NET平台以C#数据库编程如何实现ORM?
- WinForm中想实现当单击最小化按钮后,整个窗体以图标的形式缩小到右下角托盘中双击托盘的图标后恢复原窗体,怎么做?
- DataGrid如何显示行号?(C#,winform,微软自带的datagrid)
- C#精髓也没想象中那么好
- office xp与vs.net 7.0 beta2不能同时安装使用?
>>pw.WriteString(m_record.phone);// 'System.IO.BinaryWriter' does not contain a definition for 'WriteString'<<
BinaryWriter下面没有WriteString的方法,写字符串是通过重载Write(string)来实现的>> m_record.age=s_temp.ToUInt16;// 'string' does not contain a definition for 'ToUInt16'<<
s_temp是字符串变量不能用Toxxx的方法转换(虽然所有对象都有ToString()的方法,但没有Toxxx其他的方法了),要通过Convert类库来转
Convert.ToUInt16(string)来实现
using System.IO;namespace 通讯录{
struct Record
{
public string name;
public UInt16 age;
public string phone;
public string address;
}
/// <summary>
/// Summary description for Class1.
/// </summary>
class PhoneBook
{
FileStream f_srm;
string s_filename;
Record m_record;
public PhoneBook(string filename)
{
s_filename=filename;
}
public int Open()
{
Console.WriteLine("1.List Record");
Console.WriteLine("2.Add New Record");
Console.WriteLine("3.Erase Record");
Console.WriteLine("0.Exit");
Console.WriteLine("Programmer:Phoineer Stuido (C) .2001.");
int i=Console.Read()-'0';
return i;
} public void AddNew()
{
try
{
f_srm=new FileStream(s_filename,FileMode.OpenOrCreate);
}
catch
{
Console.WriteLine("PhoneBook Error!");
return;
}
BinaryWriter pw=new BinaryWriter (f_srm);
pw.Seek(0,SeekOrigin.End); //Seek起什么作用?(0,SeekOrigin.End)是什么意思?
string s_temp;
Console.Write("Name:");
Console.ReadLine(); //为什么要这一句(如不要则运行时产生The format of age is error,please ReEnter)
m_record.name=Console.ReadLine();
pw.Write(m_record.name); reenter:
Console.Write("Age:");
s_temp=Console.ReadLine();
try
{
m_record.age=Convert.ToUInt16(s_temp); //请介绍一些关于Convert的知识,我买的书中没找到它 }
catch
{
Console.WriteLine("The format of age is error,please ReEnter");
goto reenter;
}
pw.Write(m_record.age);
Console.Write("Phone Number:");
m_record.phone=Console.ReadLine();
pw.Write(m_record.phone);
Console.Write("Address:");
m_record.address=Console.ReadLine();
pw.Write(m_record.address);
f_srm.Close(); }
public void List()
{
try
{
f_srm=new FileStream(s_filename,FileMode.Open);
}
catch
{
Console.WriteLine("PhoneBook Error!");
return;
}
BinaryReader pr=new BinaryReader(f_srm);
Console.WriteLine("Name Age Phone Number Address");
Console.WriteLine("********************************************");
while(true) //这个循环是怎么一回事,什么时候退出
{
try
{
m_record.name=pr.ReadString();
m_record.age=pr.ReadUInt16();
m_record.phone=pr.ReadString();
m_record.address=pr.ReadString(); //请介绍一下以上四句是怎么读出的,编译器怎么定位
}
catch{return;}
Console.WriteLine("{0,-9}{1,-6}{2,18}{3}",m_record.name,m_record.age,m_record.phone,m_record.address); //输出时{}中的参数是怎么回事 }
f_srm.Close(); }
public void Erase()
{
try
{
f_srm=new FileStream(s_filename,FileMode.Create); //请解释一下FileMode.Create与FileMode.OpenOrCreate的差异
}
catch
{
Console.WriteLine("PhoneBook Error!");
return;
}
f_srm.Close();
Console.WriteLine("Now the book is empty!"); } }
class Class1
{
public static void Main() //下面这段程序我改了之后错在什么地方(编译能通过,执行出错)
{
PhoneBook pbook=new PhoneBook("E:\\学习作品\\通讯录\\bin\\Debug\\phonebook"); //为什么要用\\而不能用\
while(true){
int i=pbook.Open();
switch (i)
{
case 0:break;
case 1:
pbook.List();
break;
case 2:
pbook.AddNew();
break;
case 3:
pbook.Erase();
break;
}if(i==0)break;
}
}
}
}
把写入(或读取)的地方指向这个流(文件)的末尾,这样再写入时就不会覆盖原来的内容。
具体请参考这个sample
ms-help://MS.VSCC/MS.MSDNVS/cpref/html/frlrfsystemioseekoriginclasstopic.htm>>Console.Write("Name:");
>>Console.ReadLine(); //为什么要这一句(如不要则运行时产生The format of age is error,please ReEnter)
>>m_record.name=Console.ReadLine();
>>pw.Write(m_record.name);
出现错误是因为输入的name和age给错了变量,导致一个不是只有数的字符变量无法转换成数值型变量。为什么会给错了,因为作者(原来不是你写的)想要输入的界面好看,希望能在Name后面直接输入姓名,而不是Name一行,输入在另一行。而输入给变量的时候是用readline的,那这个Name到底算不算姓名的一部分呢?作者发现通过加一个readline可以解决这个问题,于是
调试方法:在vs.net中,在后面的try上按F9,设置一个断点,运行到输入会回到程序中,你把鼠标移到m_record.name和s_temp上,看看他们的值是什么(有readline那行和没有,分两次比较一下)Convert类,在vs.net环境下键入Convert. 之后就会列出可转换成的类型,很方便的。请好好利用手上的资料,如MSDN,有很详细的文档和sample,搜索一下就可以了。
先敲这么多
我还是没弄懂是怎么回事:
> > Console.Write("Name:");
> > Console.ReadLine(); //把这一句去掉后,
> > m_record.name=Console.ReadLine();//这一句为什么就不执行呢?
> > pw.Write(m_record.name);还有这一段:
public static void Main() //下面这段程序我改了之后错在什么地方(编译能通过,执行出错)
{
while(true){
PhoneBook pbook=new PhoneBook("E:\\学习作品\\通讯录\\bin\\Debug\\phonebook"); int i=pbook.Open();
if(i==0)break;
if(i==1) pbook.List();
if(i==2) pbook.AddNew();
if(i==3) pbook.Erase();
}
}希望jhnhu兄能回答,如有其它问题,将另开贴;
最后一个问题:
怎么把分给你?
2>>Console.ReadLine(); //为什么要这一句(如不要则运行时产生The format of age is error,please ReEnter)
3>>m_record.name=Console.ReadLine();
4>>pw.Write(m_record.name);
5>>reenter:
6>>Console.Write("Age:");
7>>s_temp=Console.ReadLine();ReadLine()的作用是接收一行输入的信息
而输入的那行是由 程序打印的Name 和 用户输入的姓名 混合成的
Name:jhnhu
2>>Console.ReadLine(); //这行得到 "Name:"
3>>m_record.name=Console.ReadLine(); //这行得到 "jhnhu"
如果不混合可以分两行来做
Name: //WiteLine("Name:");
jhnhu //m_record.name=Console.ReadLine();
这样就不用2了,但没有一行的好看
但6 7之见为何没有ReadLine()我就不知道了
我试过你所说的方法,但不行.在第一行改为Console.WritLine("Name")后,取消第二行,编译后运行,显示:
Name:
Age:
输入字母出错!
还有最关键的是这段:(我是怎么也搞不懂了)
public static void Main() //下面这段程序我改了之后错在什么地方(编译能通过,执行出错)
{
while(true){
PhoneBook pbook=new PhoneBook("E:\\学习作品\\通讯录\\bin\\Debug\\phonebook"); int i=pbook.Open();
if(i==0)break;
if(i==1) pbook.List();
if(i==2) pbook.AddNew();
if(i==3) pbook.Erase();
}
}
这家伙的水平也太差了吧!编程风格十分恶劣!快把这本书扔了吧,浪费大家的时间!你改的循环没有问题,出错是由这家伙的,投机取巧的心理造成的
public int Open()
{
Console.WriteLine("1.List Record");
Console.WriteLine("2.Add New Record");
Console.WriteLine("3.Erase Record");
Console.WriteLine("0.Exit");
Console.WriteLine("Programmer:Phoineer Stuido (C) .2001.");
int i=Console.Read()-'0'; //这是非常不好的做法,根本就不知道其中的原理,而这个应该是在C的时候就会有的问题
return i;
}
为了能简单地取得这个数字,用char减char得到int(这里用了隐式地使用了类型转换,初学者会看不懂)。既然需要char就不能用ReadLine(),数字是得到了,但在你按下回车的时候,却把 chr(13) chr(10)这两个字符留在了缓冲区中(13是回车-把光标移到第一列;10是换行-把光标移到下一行;这两个字符才是你看见按回车后换了一行的效果)。
为什么选了1以后会显示3次菜单,第一次显示后Read()从缓冲里拿了chr(13)这个字符;第二次显示后Read()拿了chr(10)这个字符;第三次显示后,因为缓冲空了,所以才停下来等你输入。如果你在输入1的地方输入111,它肯定会显示5次。
这也造成了在AddNew()需要添加一行ReadLine()来清空缓冲区里的东西,而后面的输入没有前没有这个语句,如果不清空,Name得到的是chr(13)chr(10),也就是一个空字符串,然后age得到你输入的姓名(这当然不能转换成数值型啦)。那家伙还以为是输入Name时有问题,结果给他碰对了,暂时不会出错,多么愚蠢啊!只要把Read()那行换成:
int i = Convert.ToInt16(Console.ReadLine());
把多出来的ReadLine();去掉,一切都会正常!还有这里
while(true) //这个循环是怎么一回事,什么时候退出
{
try
{
m_record.name=pr.ReadString();
m_record.age=pr.ReadUInt16();
m_record.phone=pr.ReadString();
m_record.address=pr.ReadString();
}
catch{return;} //文件读到末尾不能再读了,会出错,就会执行catch里的命令,达到跳出循环的目的
Console.WriteLine("{0,-9}{1,-6}{2,18}{3}",m_record.name,m_record.age,m_record.phone,m_record.address); }
多么野蛮啊!要是各位来写,肯定是用 判断到文件尾了没有 来做循环条件的。关于参考资料,第一是微软的文档,能啃E文,绝对比别人学得快;还有论坛上推荐的书也可以买。
谢谢你如此耐心的回答,我将给你加分,已表感谢!
再问一个问题,怎么判断到了文件尾,来做循环条件?
像这个BinaryReader有一个PeekChar()的方法
public virtual int PeekChar();
Returns the next available character and does not advance the byte or character position.
Return Value:
The next available character, or -1 if no more characters are available or the stream does not support seeking.
(查一查文档就能知道的)
所以把那个循环改为
while(pr.PeekChar() != -1)
{
}
就可以了,那个catch留着也行,以防有其他错误