这是一段代码:
public class TestArray
{
public static void main(String[] args)
{
//声明一个长度和args数组一样的数组b
int[] b = new int[args.length];
//交换数据用的临时变量
int temp;
//遍历
for(int i=0;i<args.length;i++)
{
//将args数组中的数据依次赋给b[i]
b[i]=Integer.parseInt(args[i]); //出现问题是从这里开始的
//遍历,从i+1开始遍历,
for(int j=i+1;j<args.length;j++)
{
//比较大小
if(b[i]>b[j])
{
//不是从小到大,就交换顺序
temp=b[i];
b[i]=b[j];
b[j]=temp;
}
}
//将调整好顺序的数组b依次打印出来
System.out.print(b[i]+" ");
}
}
}
运行效果如下:
奇怪,不对啊,我要的效果应该是输出2 3 4 5.怎么变成0 0 0 3了?
从头到尾看一遍代码,声明变量略过,从遍历开始,运行将5 2 4 3赋到b[]上,所以b[0]=5,b[1]=2;b[2]=4;b[3]=3;然后比较b[0]和b[1],b[2],b[3];第一轮由于b[0]>b[1],所以交换b[0]=2,b[1]=5;然后b[0]=2,就比b[2],b[3]小了,就不用交换,照这样下去,可以得到结果的啊,为什么出了0 0 0 3这种结果?
在这段代码中间加上System.out.print打印出来,
temp=b[i];
b[i]=b[j];
b[j]=temp;
变成这样
System.out.println("b[j]=" + b[j]);
System.out.println("b[i]=" + b[i]);
temp=b[i];
System.out.println("temp=" + temp);
b[i]=b[j];
System.out.println("b[i]=" + b[i]);
b[j]=temp;
System.out.println("b[j]=" + b[j]);
System.out.println("");
发现b[j]从最开始的时候就一直都是0.为什么b[j]没有赋上值呢?一想循环的时候,第一轮循环i=0时,只给了b[0]赋值,b[1]还没有赋值.所以修改代码变为
//遍历,从i+1开始遍历,
for(int j=i+1;j<args.length;j++)
{
//将args数组中的数据依次赋给b[j]
b[j]=Integer.parseInt(args[j]); //添加这条语句
//比较大小
if(b[i]>b[j])
{
//不是从小到大,就交换顺序
temp=b[i];
b[i]=b[j];
b[j]=temp;
}
}
然后运行效果就是这个样子了,
还是不对.问题出在了哪?没想通,试着用内存分析来解决这个问题.
输入还是5 2 4 3,这是第一轮循环结束的样子.第一轮挺正常的
一开始的时候args数组是有5 2 4 3,这几个值的;但是b数组最开始是全为0的.然后执行遍历中的这条语句,
b[i]=Integer.parseInt(args[i]);
将args[0]中的值赋值到了b[0]中,所以b[0]=5了,而执行这条语句
b[j]=Integer.parseInt(args[j]),b[1]=2;
比较b[0],b[1],交换,所以b[0]变成2,而b[1]变成5;后面由于b[0]=2<4,2<3;不用执行.
这是第二轮结束的样子.问题出现了
由于这两条语句,
b[i]=Integer.parseInt(args[i]);
b[j]=Integer.parseInt(args[j]),所以
b[1]=args[1]=2;b[2]=args[2]=4;
b[3]=args[3]=3;
由于2<4,2<3,所以不用交换.其中b[1]重新指向了args[1]变成了2,而实际我要的应该是上一轮调整好的b[1]=5才对.
从这里发现,不应该再执行一次b[i]=Integer.parseInt(args[i]),让b[1]=args[1]=2,b数组中的数据应该是已经赋值好了,然后直接进行比较即可.
所以代码变为这样,有两次for循环,第一次将args上的数据全都赋值到b数组上,这样就不会再被args赋值一次.所以b[j]=Integer.parseInt(args[j])这条语句也是多余的,不能让b中的值再被args覆盖掉.
//遍历args,将所有的值依次赋值到b上
for(int i=0;i<args.length;i++)
{
b[i]=Integer.parseInt(args[i]); //差不多就是修改了这里
}
//遍历
for(int i=0;i<args.length;i++)
{
//遍历,从i+1开始遍历,
for(int j=i+1;j<args.length;j++)
{
//比较大小
if(b[i]>b[j])
{
//不是从小到大,就交换顺序
temp=b[j];
b[j]=b[i];
b[i]=temp;
}
}
//将调整好顺序的数组b依次打印出来
System.out.print(b[i]+" ");
}
最后的运行效果:
最后,以前这些代码我总是不敲,看完就觉得自己会了.可是实际上自己敲,就会出现一些很奇怪的问题.就像这段代码,语句基本都是对的,但是for循环没整明白.
在这里,比如执行这条语句,b[i]=Integer.parseInt(args[i]),我发现我会想当然的以为args数组上的所有数据都依次赋值上去了.但实际他每一次for循环执行一次,后面的根本还没赋上值.所以我只看代码,始终也没发现代码有什么问题.
所以出现问题,静下心来,用用内存分析的法子,也许就能清楚明白问题在哪了,那么问题也就能迎刃而解了.