简体   繁体   English

运行时错误SIGFPE。 为什么?

[英]runtime error SIGFPE . Why?

I am trying to solve a problem that is I have to found a probability of a correct sentence. 我正在尝试解决一个问题,那就是我必须找到正确句子的概率。 We assume that only one order of a sentence is correct. 我们假设一个句子只有一个顺序是正确的。 lets a sentence " eat you rice ". 让我们说一句“吃米饭”。 We can rearrange this sentence by six types. 我们可以将这句话重新排列为六种类型。 Such as: "eat you rice", "eat rice you", "you eat rice", "you rice eat", "rice you eat", "rice eat you" 如:“吃米饭”,“吃米饭”,“你吃米饭”,“你吃米饭”,“米饭你吃”,“米饭你吃”

So the result is: 1/6 . 因此结果是:1/6。

We also assume that each sentence consists with some words not exceed 10 words and the number of alphabet of each word is less than 21. 我们还假定每个句子包含不超过10个单词的单词,并且每个单词的字母数少于21。

I always get runtime error SIGFPE when i submitted (local programming practice website) it. 提交(本地编程实践网站)时,总是会收到运行时错误SIGFPE。

My code is given below: 我的代码如下:

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

My guess about the source of the SIGFPE was wrong, at least on the Mac where I tested. 我对SIGFPE来源的猜测是错误的,至少在我测试过的Mac上是这样。 The crash occurred in a call to strcpy() inside set_line() . 崩溃发生在对set_line()内部的strcpy()的调用中。

Error check your inputs to behave sanely when there is no (valid) input. 错误检查您的输入,使其在没有(有效)输入时行为正常。 I got the crash to start with, but resolved it by simply doing the error checking: 我从崩溃开始,但是通过简单地进行错误检查解决了它:

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

and in main() : 并在main()

    if (scanf("%d", &t_line) != 1)
    {
        printf("Invalid number in data\n");
        return 1;
    }

The output I got from the data file: 我从数据文件得到的输出:

4
monolexis
parsimony rules
rice is nice
cats and dogs too

was: 原为:

1/1
1/2
1/6
1/24

This looks plausible as the first four factorials (this is a convoluted way of calculating them). 作为前四个阶乘(这是计算它们的复杂方法),这似乎是合理的。


I'm not keen on the input code as amended. 我不喜欢修改后的输入代码。 The first stage of improvement would lose tmp and the strcpy() operations (and also protect against over-long words — but not against too many words in a line): 改进的第一步将丢失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;
}

But I don't like 'count plus data' programming, especially in a case like this where you don't need to know the count to store all the incoming data. 但是我不喜欢“计数加数据”编程,尤其是在这种情况下,您不需要知道存储所有传入数据的计数。 Let computers do the counting — they're good at numbers. 让计算机进行计数–他们擅长数字计算。 All you're doing with the count is reading one line at a time and then splitting it into words until you've reached the counted number of lines. 您要做的所有事情是一次读取一行,然后将其拆分为单词,直到达到计算的行数为止。 It would be better to structure the code to simply read one line at a time and process that line, up until there isn't another line to read. 最好将代码构造为一次只读取一行并处理该行,直到没有另一行要读取为止。 The set_line() function gets given a string — a line of data — to process, and the main() code simply loops while there's another line to read. set_line()函数得到一个字符串(一行数据)进行处理,并且main()代码只是在有另一行要读取的时候循环。 Granted, using %n to step through the input data is an advanced use of sscanf() , but it is also an extremely useful one in circumstances like this. 当然,使用%n逐步遍历输入数据是sscanf()的高级用法,但在这种情况下也是非常有用的。

The revised code is protected against both over-long words and against too many words in a line, and looks like: 修改后的代码可防止出现超长单词和一行中的单词过多的情况,其外观如下:

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

For the same input file, this now produces: 对于相同的输入文件,现在将产生:

1/1
1/1
1/2
1/6
1/24

because the count is now counted as a single word line of input. 因为现在该计数被视为输入的单个字行。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM