简体   繁体   中英

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 .

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.

I always get runtime error SIGFPE when i submitted (local programming practice website) it.

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. The crash occurred in a call to strcpy() inside set_line() .

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() :

    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):

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. 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.

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.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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