學生給我發了私信,一個程序運行了好久,在OJ就是提交不了。
題目是:
**Description**
輸入10個整數,將其中最小的數與第一個數對換,把最大的數與最后一個數對換。寫三個函數; ①輸入10個數;②進行處理;③輸出10個數。
**Input**
10個整數
**Output**
整理后的十個數,每個數后跟一個空格(注意最后一個數后也有空格)
**Sample Input**
2 1 3 4 5 6 7 8 10 9
**Sample Output**
1 2 3 4 5 6 7 8 9 10?
**HINT**
主函數已給定如下,提交時不需要包含下述主函數
~~~
/* C/C++代碼 */
int main()
{
const int n=10;
int a[n];
input(a,n);
handle(a,n);
output(a,n);
return 0;
}
~~~
學生的解答:
~~~
#include<iostream>
#include<cstdio>
using namespace std;
void input(int a[],int);
void handle(int a[],int);
void output(int a[],int);
int main()
{
const int n=10;
int a[n];
//freopen("input.txt","r",stdin);
input(a,n);
handle(a,n);
output(a,n);
return 0;
}
void input(int a[],int n)
{
for(int i=0;i<n;i++)
cin>>a[i];
}
void handle(int a[],int n)
{
int max,i=0,t,min,z,zd,zx;
max=a[i];
min=a[i];
for(i=0;i<n;i++)
{
if(max<a[i])
{
max=a[i];
zd=i; //記錄最大值的位置
}
if(min>a[i])
{
min=a[i];
zx=i; //記錄最小值的位置
}
}
t=a[9];
a[9]=max;
a[zd]=t; //進行值交換
z=a[0];
a[0]=min;
a[zx]=z;
}
void output(int a[],int n)
{
for(int i=0;i<n;i++)
{
cout<<a[i]<<" ";
}
}
~~~
這個解答在CodeBlocks中編譯通過,屢經測試數據,沒有異常,然而,提交后提示“Runtime error”,具體是:
Runtime Error:Segmentation fault
輔助解釋:Segmentation fault:段錯誤,檢查是否有數組越界,指針異常,訪問到不應該訪問的內存區域
這不科學!由“一定是我錯了”的思維,轉向了“可能是機器錯了”,利用管理員帳號,看了測試數據,也沒有問題。
再逐句看程序,一個地方引起我的注意,會是25、26行引用a[i],但 i 沒有賦值嗎?不是,i 的初值是0,于算法沒有問題。就在第24行,zd、zx兩個變量,也應該是同步賦值的,它們表示最大、最小的數的下標,后面循環中,也及時對這兩個數做了更新。
問題逐漸明白了,在24行不給zd、zx賦初值的情況下,如果29和34行的if條件有一個始終未能為真,zd、zx就不會賦值,40行開始的交換,就會出現數組越界。
** 在這個程序上小修改的辦法有了:第24行,加上給zd、zx賦初值,即:int max,i=0,t,min,z,zd=0,zx=0;**
這個程序,沒有用上單步執行。對這種小幾率的問題,單步可能也不管用,思維要嚴密。
這個程序寫得稍顯羅嗦,下面給出一個改寫版。
~~~
#include<iostream>
#include<cstdio>
using namespace std;
void input(int a[],int);
void handle(int a[],int);
void output(int a[],int);
int main()
{
const int n=10;
int a[n];
//freopen("input.txt","r",stdin);
input(a,n);
handle(a,n);
output(a,n);
return 0;
}
void input(int a[],int n)
{
for(int i=0;i<n;i++)
cin>>a[i];
}
void handle(int a[],int n)
{
int i,t,zd=0,zx=0;//默認第0個為最大、最小
for(i=1;i<n;i++) //從第1個開始
{
if(a[zd]<a[i])
zd=i; //記錄最大值的位置
if(a[zx]>a[i])
zx=i; //記錄最小值的位置
}
t=a[n-1]; //比用含有“神秘數”的a[9]好
a[n-1]=a[zd];
a[zd]=t; //進行值交換
t=a[0];
a[0]=a[zx];
a[zx]=t;
}
void output(int a[],int n)
{
for(int i=0;i<n;i++)
{
cout<<a[i]<<" ";
}
}
~~~