运行时错误SIGFPE。为什么?

时间:2014-08-19 03:56:23

标签: c runtime-error

我正在努力解决一个问题,即我必须找到正确句子的概率。我们假设只有一个句子的顺序是正确的。 让一句话“吃你米饭”。我们可以用六种类型重新排列这个句子。 如: “吃你米饭”, “吃米饭你”, “你吃米饭”, “你吃米饭”, “你吃饭”, “米饭吃了你”

结果是: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;
}

1 个答案:

答案 0 :(得分:0)

guess关于SIGFPE的来源是错误的,至少在我测试的Mac上是这样。在strcpy()内的set_line()调用中发生了崩溃。

错误检查输入,以便在没有(有效)输入时表现得很好。我开始崩溃,但只是通过错误检查解决了它:

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

这看起来似乎是前四个阶乘(这是一种复杂的计算方法)。


我并不热衷于修改后的输入代码。改进的第一阶段将失去tmpstrcpy()操作(并且还可以防止过长的单词 - 但不会对一行中的太多单词进行处理):

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;
}

但我不喜欢'count plus data'编程,特别是在这种情况下你不需要知道存储所有传入数据的计数。让计算机进行计数 - 他们擅长数字。你在计算中所做的就是一次读一行,然后将它分成单词,直到你达到计算的行数。最好将代码结构化为一次只读取一行并处理该行,直到没有其他行要读取为止。 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

因为计数现在被视为单个输入字线。