黑马程序员技术交流社区

标题: 定义变量后的赋值问题,求解释。 [打印本页]

作者: 宋清飞    时间: 2013-10-13 23:24
标题: 定义变量后的赋值问题,求解释。
本帖最后由 宋清飞 于 2013-10-14 12:56 编辑
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Linq;
  4. using System.Text;
  5. using System.Threading.Tasks;

  6. namespace method1
  7. {
  8.    class Program
  9.    {
  10.       static void Main(string[] args)
  11.       {
  12.             bool flag;
  13.             int year;
  14.             do
  15.             {
  16.                   try        //检验用户输入是否正确
  17.                  {
  18.                       Console.WriteLine("请输入一个年份:");
  19.                       year = int.Parse(Console.ReadLine());
  20.                       flag = false;
  21.                  }
  22.                   catch
  23.                  {
  24.                        Console.WriteLine("输入有误,请重新输入。");
  25.                         flag = true;
  26.                   }
  27.              } while (flag == true);
  28.              Console.WriteLine(year);    //屏幕输出year的值
  29.              Console.ReadKey();
  30.       }
  31.    }
  32. }
复制代码
让用户输入一个年份,如果不是整数提示错误重新输入,最后打印出结果。这样写编译时会出错,提示"使用了未赋值的year"。可如果在定义的时候写成int year=0,就不会出错。
在使用"year"之前已经在do循环里给"year"赋过值了,为什么还会出错?
求解释。

作者: Liu阳    时间: 2013-10-13 23:38
这是因为Try语句的原因,通俗的讲究是我试着执行这段代码,如果在没给year初始化之前就报了异常怎么办呢,console.writeline(year);肯定是没给year赋值啦。所以你编译不会通过了,你要把console.writeline(year);放在try中就没问题了。或者就老老实实的声明初始化,这是个好习惯的。
求加分!!!!!!
作者: 宋清飞    时间: 2013-10-13 23:48
Liu阳 发表于 2013-10-13 23:38
这是因为Try语句的原因,通俗的讲究是我试着执行这段代码,如果在没给year初始化之前就报了异常怎么办呢,c ...

是不是说从人的角度去看,逻辑上,程序在执行到Console.WriteLine(year);的时候,因为循环条件的关系year一定是被赋值了,可是对编译器来说,因为try语句的特性,不能把这样的year看成是已经赋值了。如果这么来想的话,大概明白了。
作者: Liu阳    时间: 2013-10-13 23:55
对的,就像一个人我试着干一下,有可能赚100W,你的投资人没等你干呢敢和别人说我已经赚了100W了吗?就是这个意思
作者: 面朝大海,春暖    时间: 2013-10-14 07:58
因为你定义的year和输出语句   : Console.WriteLine(year)在同一级别,按照程序执行的顺序,不管你do里执行没执行,    Console.WriteLine(year)这个输出语句都会执行,你没赋初始值,按照变量的定义当然会报错!
作者: 张锟-i    时间: 2013-10-14 11:41
LZ,year 和 最后输出的 Console.WriteLine(year)在同一个级别内,不管你do
            {
                  try        //检验用户输入是否正确
                 {
                      Console.WriteLine("请输入一个年份:");
                      year = int.Parse(Console.ReadLine());
                      flag = false;
                 }
                  catch
                 {
                       Console.WriteLine("输入有误,请重新输入。");
                        flag = true;
                  }
             }
内有没有执行 ,都会执行 Console.WriteLine(year);如果do语句没执行 ,Console.WriteLine(year)中的year相当于没有赋值,而year变量 你有没有初始化,当然会报错。

作者: 宋清飞    时间: 2013-10-14 11:50
面朝大海,春暖 发表于 2013-10-14 07:58
因为你定义的year和输出语句   : Console.WriteLine(year)在同一级别,按照程序执行的顺序,不管你do里执 ...

如果按照你的说法,在Console.WriteLine(year);旁边再写一个Console.WriteLine(flag);这个flag也应该没有赋值,无法通过编译。可是我试着运行了一下,这么写flag没有报错。也就是说,你的说法不适用了。
作者: 宋清飞    时间: 2013-10-14 11:52
Liu阳 发表于 2013-10-13 23:55
对的,就像一个人我试着干一下,有可能赚100W,你的投资人没等你干呢敢和别人说我已经赚了100W了吗?就是这 ...

又仔细想了想你的说法,按照你的说法,那么flag也是未赋值的,也无法通过编译,可是实际上flag通过编译了。所以,还是解释不通。
作者: Liu阳    时间: 2013-10-14 11:59
宋清飞 发表于 2013-10-14 11:52
又仔细想了想你的说法,按照你的说法,那么flag也是未赋值的,也无法通过编译,可是实际上flag通过编译了 ...

那是因为catch中的flag的问题,你把catch中的注释看一看,或者把year的初始赋值放在catch中,你看看你的console.writeln()提示什么?
作者: 夏闯富    时间: 2013-10-14 12:09
本帖最后由 夏闯富 于 2013-10-14 12:34 编辑

为什么会提示:使用了未赋值的yaer
原因:主要是用了Try-catch的语句的原因(try语句里面的代码不会编译  “其实这里说不编译是不科学的,严格的说是try{}之外的代码先编译,try{}在第二级别编译,为了方便理解,就先把它认为不编译”,只会在运行的时候执行。而其它的你输入后,程序会即时进行编译)
详细介绍:
在 try 块内部时应该只初始化其中声明的变量;否则,完成该块的执行前可能发生异常。 例如,在下面的代码示例中,变量 x 在 try 块内初始化。 如果尝试在 Write(x) 语句中的 try 块外部使用此变量,则会生成编译器错误。




static void Main() {    int x;   
   try//try语句里面的代码不会编译,只会在运行的时候执行。而其它的你输入后,程序会即时进行编译。  
  {      
        x = 123;//此处还未编译(运行时才执行),并没有初始化变量
  }  
  catch
  {   
  
  }
   Console.Write(x);//此处会提示错误:使用了未赋值的x
}








作者: 宋清飞    时间: 2013-10-14 12:17
Liu阳 发表于 2013-10-14 11:59
那是因为catch中的flag的问题,你把catch中的注释看一看,或者把year的初始赋值放在catch中,你看看你的c ...

catch中给year赋值的话,编译就通过了。哦,try catch两条线是并行的,每条路单独都走得通才行。明白了
作者: 宋清飞    时间: 2013-10-14 12:21
张锟-i 发表于 2013-10-14 11:41
LZ,year 和 最后输出的 Console.WriteLine(year)在同一个级别内,不管你do
            {
                 ...

用你这个同级别的说法,怎么解释flag不报错?flag的定义在do语句内,按你的说法和Console.WriteLine(flag)不是一个级别的。
作者: 宋清飞    时间: 2013-10-14 12:31
夏闯富 发表于 2013-10-14 12:09
为什么会提示:使用了未赋值的yaer
原因:主要是用了Try-catch的语句的原因(try语句里面的代码不会编译, ...

那为什么int year;
            try { year = 1; }
            catch { year = 2; }
             Console.WriteLine(year);
可以通过。
int year;
            try { year = 1; }
            catch { }
             Console.WriteLine(year);
就不能通过呢?
作者: 夏闯富    时间: 2013-10-14 12:36
宋清飞 发表于 2013-10-14 12:31
那为什么int year;
            try { year = 1; }
            catch { year = 2; }

我重新再写详细了一下,你看再理解么
作者: 夏闯富    时间: 2013-10-14 12:44
夏闯富 发表于 2013-10-14 12:36
我重新再写详细了一下,你看再理解么

重点在try{} 不在catch{}.  try{}才在第二级别,catch是和普通的其它的一样,在第一级别。
作者: 夏闯富    时间: 2013-10-14 12:48
宋清飞 发表于 2013-10-14 12:31
那为什么int year;
            try { year = 1; }
            catch { year = 2; }

虽说try-catch是一起用的一个整体,但 重点在try{}块 不在catch{}块.  
try{}才在第二级别,catch{}是和普通的其它的一样,在第一级别
作者: 夏闯富    时间: 2013-10-14 12:50
宋清飞 发表于 2013-10-14 12:31
那为什么int year;
            try { year = 1; }
            catch { year = 2; }

双击你程序中的try关键字  按F1
作者: ˋ初°见    时间: 2013-10-14 12:59
当执行catch时,未给year赋值,只要把输出语句放到catch里面就可以了,这样就实现了当是数字时,就输出,不是时提示重新输入。

1.png (53.81 KB, 下载次数: 91)

1.png

作者: ˋ初°见    时间: 2013-10-14 13:08
ˋ初°见 发表于 2013-10-14 12:59
当执行catch时,未给year赋值,只要把输出语句放到catch里面就可以了,这样就实现了当是数字时,就输出,不 ...

最好把定义的变量都放在try里面,因为try catch语句,当程序没错误是执行try里面的语句,当执行有错误时,就执行catch里面的语句。
作者: 面朝大海,春暖    时间: 2013-10-14 19:30
本帖最后由 面朝大海,春暖 于 2013-10-14 19:31 编辑
宋清飞 发表于 2013-10-14 11:50
如果按照你的说法,在Console.WriteLine(year);旁边再写一个Console.WriteLine(flag);这个flag也应该没 ...

flag是bool类型,它的默认值是false或true,所以输出flag不会报错。。
作者: 面朝大海,春暖    时间: 2013-10-14 20:53
本帖最后由 面朝大海,春暖 于 2013-10-14 20:56 编辑
面朝大海,春暖 发表于 2013-10-14 19:30
flag是bool类型,它的默认值是false或true,所以输出flag不会报错。。
好吧!你对了。。




欢迎光临 黑马程序员技术交流社区 (http://bbs.itheima.com/) 黑马程序员IT技术论坛 X3.2