[英]runtime error SIGFPE . Why?
我正在嘗試解決一個問題,那就是我必須找到正確句子的概率。 我們假設一個句子只有一個順序是正確的。 讓我們說一句“吃米飯”。 我們可以將這句話重新排列為六種類型。 如:“吃米飯”,“吃米飯”,“你吃米飯”,“你吃米飯”,“米飯你吃”,“米飯你吃”
因此結果是:1/6。
我們還假定每個句子包含不超過10個單詞的單詞,並且每個單詞的字母數少於21。
提交(本地編程實踐網站)時,總是會收到運行時錯誤SIGFPE。
我的代碼如下:
#include<stdio.h>
#include<string.h>
int t[11];
char line[11][21];
int set_line()
{
int j=1;
char tmp[21],m;
scanf("%s",tmp);
strcpy(line[0],tmp);
while(getchar() != '\n' )
{
scanf("%s",tmp);
strcpy(line[j],tmp);
j++;
}
return j;
}
void ib()
{
int i;
t[0]=1;
t[1]=1;
t[2]=2;
for(i=3;i<11;i++)
{
t[i]=t[i-1] * i;
}
}
int main()
{
int t_line,word_cnt,n=1,i,j,tmp,p=1;
scanf("%d",&t_line);
ib();
while(t_line--)
{
word_cnt=set_line();
tmp=word_cnt;
for(i=0;i<word_cnt;i++)
{
if((strcmp(line[i],"01"))==0)
continue;
for(j=i+1;j<word_cnt;j++)
{
if((strcmp(line[i],line[j]))==0)
{
n++;
strcpy(line[j],"01");
}
}
if(n>1)
{
p=(t[tmp] / (t[tmp-n]*t[n])) * p;
tmp=tmp-n;
}
n=1;
}
p=t[tmp]*p;
printf("1/%d\n",p);
p=1;
}
return 0;
}
我對SIGFPE來源的猜測是錯誤的,至少在我測試過的Mac上是這樣。 崩潰發生在對set_line()
內部的strcpy()
的調用中。
錯誤檢查您的輸入,使其在沒有(有效)輸入時行為正常。 我從崩潰開始,但是通過簡單地進行錯誤檢查解決了它:
int set_line(void)
{
int j = 1;
char tmp[21];
if (scanf("%s", tmp) != 1)
return 0;
strcpy(line[0], tmp);
while (getchar() != '\n')
{
if (scanf("%s", tmp) != 1)
break;
strcpy(line[j], tmp);
j++;
}
return j;
}
並在main()
:
if (scanf("%d", &t_line) != 1)
{
printf("Invalid number in data\n");
return 1;
}
我從數據文件得到的輸出:
4
monolexis
parsimony rules
rice is nice
cats and dogs too
原為:
1/1
1/2
1/6
1/24
作為前四個階乘(這是計算它們的復雜方法),這似乎是合理的。
我不喜歡修改后的輸入代碼。 改進的第一步將丟失tmp
和strcpy()
操作(並且還可以防止出現過長的單詞,但不能防止一行中的單詞過多):
int set_line(void)
{
int j = 0;
if (scanf("%20s", line[j++]) != 1)
return 0;
while (getchar() != '\n')
{
if (scanf("%20s", line[j]) != 1)
break;
j++;
}
return j;
}
但是我不喜歡“計數加數據”編程,尤其是在這種情況下,您不需要知道存儲所有傳入數據的計數。 讓計算機進行計數–他們擅長數字計算。 您要做的所有事情是一次讀取一行,然后將其拆分為單詞,直到達到計算的行數為止。 最好將代碼構造為一次只讀取一行並處理該行,直到沒有另一行要讀取為止。 set_line()
函數得到一個字符串(一行數據)進行處理,並且main()
代碼只是在有另一行要讀取的時候循環。 當然,使用%n
逐步遍歷輸入數據是sscanf()
的高級用法,但在這種情況下也是非常有用的。
修改后的代碼可防止出現超長單詞和一行中的單詞過多的情況,其外觀如下:
int set_line(char *data)
{
int j;
int offset = 0;
int eow; // end of word
for (j = 0; j < 11 && sscanf(data + offset, "%20s%n", line[j], &eow) == 1; j++)
offset += eow;
return j;
}
…
int main(void)
{
char data[11*21];
int word_cnt, n = 1, i, j, tmp, p = 1;
ib();
while (fgets(data, sizeof(data), stdin) != 0)
{
word_cnt = set_line(data);
tmp = word_cnt;
…
對於相同的輸入文件,現在將產生:
1/1
1/1
1/2
1/6
1/24
因為現在該計數被視為輸入的單個字行。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.