SPOJ解决方案中的分段错误 - 下一个回文

时间:2014-12-08 19:07:49

标签: c

这是我对SPOJ问题的解决方案 - The Next Palindrome

我尝试运行它,但每次输入一个no。像9XXXXX ......,它给出了seg。故障,例如 -

    $ ./a.exe
    1
99999

Palin string i++: 99999
Non-Palin String: 99999
Palin string i++: 99999
Non-Palin String: 99999
Palin string i++: 99999
Non-Palin String: 99999
Change string: 99999
9 Palin String: 99099
Palin Str j = 2
Palin Str j-- = 1
9 Palin String: 90099
Palin Str j = 1
Segmentation fault (core dumped)

我的代码 -

#include <stdio.h>
#include <string.h>

#define MAX 1000000

int main(void)
{
    unsigned int t;
    scanf("%u",&t);

    unsigned long int i,j,k,len,change;
    char str[MAX];
    while(t--){                             //For every test case
        scanf("%s",str);
        i = 0;
        change = 0;
        len = strlen(str) - 1;
        Recheck:
        while(i <= (len/2)){                //If the input no. is a palindrome, then don't change it, else change it
            if(str[i] != str[len-i]){       //Compare 1st & last digit, then 2nd & 2nd last, so on....., if not same, then...
                if(str[i] > str[len-i]){    //if 1st digit > last digit,
                    str[len-i] = str[i];    //then make last one the same as 1st one 
                    i++;
                    change++;
                }
                else if(str[i] < str[len-i]){   //if <, then make the last one same as 1st one,
                    str[len-i] = str[i];        //but also increment it's left digit,
                    j = (len-i) - 1;            //if required, the next one too, and so on...
                    while(j >= 0){              //j moves from right to left (digits) in the string
                        if(str[j] != '9'){
                            str[j]++;
                            change++;
                            break;
                        }
                        else if(str[j] == '9'){
                            str[j] = '0';
                            if(j == 0){                 //If the no. becomes like 9......'\0'
                                for(k=len+1;k>=0;k--)   //and we need to increment, so shift the elements,
                                    str[k+1] = str[k];  //and make the string: 00.......'\0
                                str[0] = '0';           //Next loop will make str[0] = 1 & break.
                                len++;
                                j++;
                            }
                            change++;
                        }
                        printf("\n9 Non-Palin String: %s",str);
                        j--;
                    }

                    if(j <= i)              //if the change reaches even before from where we compared(in 1st half, that is, i),
                        i = j;              //then change i to j, so that the no. can be checked again from j, as changes are till j.
                    else
                        i++;
                }
            }
            else if(str[i] == str[len-i]){  //No change to a palindrome
                printf("\nPalin string i++: %s",str);
                i++;
            }
            printf("\nNon-Palin String: %s",str);
        }

        if(change==0){              //change == 0 means that the no. was already a palindrome
            printf("\nChange string: %s",str);  //so we have to find the next no. which is a palindrome
            if(len%2)
                j = (len/2) + 1;
            else
                j = len/2;

            if(str[j] == '9'){      //So, if the mid char(s) is/are 9 then change the no. as we did before
                while(j >= 0){
                    if(str[j] != '9'){
                        str[j]++;
                        change++;
                        break;
                    }
                    else if(str[j] == '9'){
                        str[j] = '0';
                        if(j == 0){
                            for(k=len+1;k>=0;k--)
                                str[k+1] = str[k];
                            str[0] = '0';
                            len++;
                            j++;
                            printf("\nIncrement string");
                        }
                        change++;
                    }
                    printf("\n9 Palin String: %s",str);
                    printf("\nPalin Str j = %lu",j);
                    j -= 1;
                    printf("\nPalin Str j-- = %lu",j);
                }
                printf("\nPalin to Recheck: %s",str);
                i = j;
                goto Recheck;
            }
            else{               //else, just increment the mid char/s
                if(len%2){
                    str[j]++;
                    str[j-1]++;
                }
                else{
                    str[j]++;
                }
            }
        }
        printf("\n%s",str);
    }

    return 0;
}

我添加了评论来理解代码。 对于每个编号,9,99,999等,它会给出分段错误错误。

2 个答案:

答案 0 :(得分:0)

回答我自己的问题似乎很奇怪,但仍然......

解决方案的问题在于变量k是unsigned int,因此k永远不会< 0,因此无限循环。

感谢pm100&amp;天气风向标为他们提供帮助。

答案 1 :(得分:0)

不是一个完整的答案,但是评论太多了。

“stdin输入缓冲区”是什么意思?您输入系统缓冲区直到您按“Enter”键,此时内容将被传输到您的str的数组scanf()。使用的stream是预定义的系统流调用stdin。您可以使用类似的文件函数fscanf(stdin,"%s",str);,但scanf()更方便(并且无论如何都不是非常理想的字符串方法)。但是,系统缓冲区不太可能容纳100万个字符,所以我建议你自己构建字符串,如下所示:

#include <stdio.h>
#include <conio.h>

#define MAX 1000000

int main(void)
{
    char str [MAX] = "";         // initialise string to the empty string
    int str_len = 0;             // length (and index into) str
    int c;
    do {
        c = getch ();            // gets a char but the type returned is int
        printf("%c", c);
        if (c != 13)
            str [str_len++] = c; // insert in array
    }
    while (c != 13 && str_len < MAX-1);
    str [str_len] = 0;          // terminate array
    printf("\n%s\n", str);
    printf("Length %d\n", str_len);
    return 0;
}