[英]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.