I am Writing a simple calculator that accepts arguments from command line and evaluates the string.
Intentionally, it should accept the mathematical expression and evaluate it but it throws some errors while running it. However it gets compiled successfully.
It throws following errors:-
Segmentation fault
free(): double free detected in tcache 2
Aborted
realloc(): invalid next size
Aborted
Here is my calc.c
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<ctype.h>
#include<math.h>
#include"replace.h"
#define EXPL 200 //expression lenght
#define MAXLEN 512
#define HAFLEN 256
void DisplayHelp(void);
int validate(char*);
int issign(char);
char* evaluate(char*);
long double calculate(char*);
long double getNext(char*);
long double getPrev(char*, char*);
int calcValidate(char*);
void operate(char*, char);
int issign(char);
long double strtonum(char*);
void DisplayHelp(){
char str[] = "calc <expression>\n"\
"expression: it is the mathematical expression that is to be calculated or evaluated.\n"\
"You can also use just 'calc' without any argument to start a calculator program.\n";
printf("%s\n",str);
}
int issign(char s)
{
char signs[8] = "-+/*^";
if(strchr(signs, s))
return 1;
return 0;
}
int validate(char *src)
{
char *init = src;
//check if all the characters are acceptable
while (*src){
if(
isdigit(*src)
|| *src == '(' || *src == ')'
|| *src == '.' || *src == '+'
|| *src == '-' || *src == '^'
|| *src == '/' || *src == '*'
)
src++;
else{
puts(init);
printf("Expression Contains Illegal Character at position %d.\n", (int)(src - init) + 1);
return 0;
}
}
//check if there is brace after operator
src = init;
if(strstr(src, "-)") || strstr(src, "+)")
|| strstr(src, "/)") || strstr(src, "*)")
|| strstr(src, "^)")){
printf("Expected a number after after operator. Got brace ')'\n");
return 0;
}
//check missing brackets
int hasBrace = 0;
if(strchr(src, '('))
hasBrace = 1;
src = init;
int brace = 0;
while(*src){
if(*src == '(')
++brace;
else if(*src == ')')
brace -= 1;
++src;
}
if(brace){
printf("%d Missing braces\n", brace);
return 0;
}
//check for missing operator after or before braces and add multiply operator in between
if(hasBrace){
//first count how many * should be inserted and store the index
src = init;
int insCount = 0;
int index[(int)strlen(src)];
// printf("%ld size of array, %ld\n", sizeof(index)/sizeof(int), strlen(init));
while(*src){
if(*src == '(' || *src == ')'){
if(*src == '('){
if(src != init) --src;
if(isdigit(*src)){
index[insCount] = (int)(src - init) + 1; // index of (
++insCount;
}
++src;
}
else if(*src == ')'){
++src;
if(isdigit(*src) || *src == '('){
index[insCount] = (int)(src - init);
++insCount;
}
--src;
}
}
++src;
}
//now insert * in the indexed position
src = init;
char *tmp = (char*)malloc(((int)strlen(src) + insCount + 1) * (int)sizeof(char)); //+1 for \0
if(tmp == NULL)
exit(-1);
strcpy(tmp, src);
//store how many * added as it will change the other stored index in the array
int added = 0;
for(int i = 0; i < insCount; ++i){
char *ret = insert(tmp, "*", index[i] + added);
strcpy(tmp, ret);
++added;
free(ret);
}
src = realloc(src, strlen(tmp) + 1);
strcpy(src, tmp);
free(tmp);
}
//check for empty braces
src = init;
if(hasBrace){
while(*src){
if(*src == '('){
++src;
if(*src == ')'){
printf("Empty braces.\n");
return 0;
}
--src;
}
src++;
}
}
//check if expression contains operators in invalid place
if(!calcValidate(init)){
puts("Got unexpected operator(s) at unexpected place");
return 0;
}
return 1;
}
char* evaluate(char *exp)
{
//since we will insert every result of evaluation in the exp, it may contain exp and resutl or brac exp like 3^4^3 so very long
exp = realloc(exp, MAXLEN);
if(!exp)
exit(-1);
char *init = exp;
long expl = strlen(exp);
//count total open brackets
int brace = 0;
while(*exp){
if(*exp == '(')
++brace;
++exp;
}
exp = init;
int isWholeInsideBrace = 0;
if(*exp == '(')
isWholeInsideBrace = 1;
if(brace){
for(int i = brace; i > 0; --i){
int bracth = 0; //nth brace e.g. 4th brace
char bracexp[MAXLEN] = "";
char curAns[MAXLEN] = ""; //store current ans, later replace bracexp in exp with it
char *bracclos = "";
while(*exp){
if(*exp == '('){
++bracth;
if(bracth != i){
++exp;
continue;
}
bracclos = strchr(exp, ')');
strncpy(bracexp, exp, bracclos - exp + 1); //copy from '(' to ')'
snprintf(curAns, MAXLEN, "%.256Lg", calculate(bracexp));
char *replExp = replace(init, bracexp, curAns, 1);
strcpy(init, replExp);
free(replExp);
// exit(0);
break;
}
++exp;
}
exp = init;
}
}
if(!isWholeInsideBrace){
snprintf(exp, MAXLEN, "%.256Lg", calculate(exp));
}
return exp;
}
long double calculate(char* expre)
{
char tmp[MAXLEN] = "";
long double ans = 0.0;
char* ptr = tmp;
//remove brace from if exist
while(*expre){
if(*expre != '(' && *expre != ')'){
*ptr = *expre;
++ptr;
}
++expre;
}
*ptr = '\0';
ptr = tmp;
if(strchr(tmp, '^'))
operate(tmp, '^');
if(strchr(tmp, '/'))
operate(tmp, '/');
if(strchr(tmp, '*'))
operate(tmp, '*');
// for + and - need to check if there is only one number, else infinite loop
if(strchr(tmp, '+') )
operate(tmp, '+');
if(strchr(tmp, '-') )
operate(tmp, '-');
//if the exp does not contain any signs means it if already calculated or it is single number
return atof(tmp);
}
void operate(char *temp, char sign)
{
long double num1 = 0;
long double num2 = 0;
char curExp[MAXLEN] = "";
char curAns[MAXLEN] = "";
char *replaced;
char *oper;
long double ans = 0;
while((oper = strchr(temp,sign))){
num1 = getPrev(temp, oper);
num2 = getNext(oper);
if(sign == '^')
ans = pow(num1, num2);
else if(sign == '/')
ans = num1 / num2;
else if(sign == '*')
ans = num1 * num2;
else if(sign == '+')
ans = num1 + num2;
else if(sign == '-')
ans = num1 - num2;
//if first letter is + or - , getPrev returns 0 so ignore it
//check and specify the format
char secfor[15] = "";
char ansfor[10] = "";
if(oper == temp && !isdigit(*oper))
snprintf(curExp, MAXLEN,((int)num2 == num2)? "%c%.0Lf" : "%c%.4Lf", *oper, num2);
else{
int a,b;
a = (int)num1;
b = (int)num2;
if(a == num1 && b == num2)
strcpy(secfor, "%.0Lf%c%.0Lf");
else if(a == num1)
strcpy(secfor, "%.0Lf%c%.4Lf");
else if(b == num2)
strcpy(secfor, "%.4Lf%c%.0Lf");
else
strcpy(secfor, "%.4Lf%c%.4Lf");
snprintf(curExp, MAXLEN, secfor, num1, *oper, num2);
}
snprintf(curAns, MAXLEN,((int)ans == ans)? "%.0Lf" : "%.4Lf", ans);
replaced = replace(temp, curExp, curAns, 1);
// printf("%s\n%s\t%s\n%s\n", temp, curExp, curAns, replaced);
strcpy(temp, replaced);
printf("new temp: %s\n\n", temp);
free(replaced);
//special cases:-
//if first letter is + or - and there is only one number, so break the loop
if(sign == '+' || sign == '-'){
char *ptr = temp;
if(sign == '+'){
if(strrchr(temp, '+') == ptr && !strchr(temp, '-'))
break;
}
else if(sign == '-'){
if(strrchr(temp, '-') == ptr)
break;
}
}
}
}
int calcValidate(char *val)
{
char *point = val;
char first = *point;
//take pointer to end of string
point = strchr(point, '\0');
--point;
char last = *point;
point = val;
if(!isdigit(first) && (first != '-' || first != '+'))
return 0;
else if(!isdigit(last) && last != '(' && last != ')')
return 0;
//check whether operators are doubled
int doubled = 0;
while(*point){
if(isdigit(*point) || *point == '(' || *point == ')')
doubled = 0;
else if(issign(*point)){
if(doubled)
return 0;
doubled = 1;
}
++point;
}
return 1;
}
long double getNext(char* pos)
{
char *tmp = pos;
//pos is the position of operator, ignore it, and return numbers from it to next operator
++tmp;
return strtonum(tmp);
}
long double getPrev(char* str, char* pos)
{
char *tmp = str;
char *tmpp = pos;
//if + or - is at first, return 0
if(tmpp == str)
return 0;
--tmpp;
while(tmpp != str && isdigit(*tmpp))
--tmpp;
//tmpp now is the position of operator , so get number between this operator to another operator i.e. pos
if(tmpp != str)
++tmpp;
return strtonum(tmpp);
}
long double strtonum(char* s)
{
char *ptr = s;
char sign = '\0';
long double beforeDecimal = 0.0;
float afterDecimal = 0.0;
float a, c = 10;
int exp = 1;
if(*ptr == '+' || *ptr == '-'){
sign = *ptr;
++ptr;
}
while(isdigit(*ptr)){
a = *ptr - '0';
beforeDecimal = beforeDecimal * c + a;
++ptr;
}
if(*ptr == '.'){
++ptr;
while(isdigit(*ptr)){
a = *ptr - '0';
afterDecimal = afterDecimal + a/pow(c, exp);
++exp;
++ptr;
}
}
beforeDecimal += afterDecimal;
if(beforeDecimal){
if(sign && sign == '-')
beforeDecimal = -beforeDecimal;
return beforeDecimal;
}
return 0;
}
int main(int argc, char const *argv[])
{
//parse and store the expression for calculation
char *exp = (char*)malloc(sizeof(char) * (EXPL +1)); // 1 is for null terminator \0
if(exp == NULL)
exit(-1);
int count = 1; //extra 1 will store \0
int i = 1, j = 1;
// check whether argument are supplied
if(argc < 2)
return 0;
//calculate the total size of arguments
while(j < argc){
count += strlen(argv[j]);
++j;
}
char *temp = malloc(sizeof(char) * count);
if(!temp) exit(-1);
//copy all arguments to temp
for(i = 1; i < argc; ++i)
strcat(temp, argv[i]);
//check if the expression contains whitespaces
//first check if it contains multiline argument and make it single line
//then remove whitespaces
if(strstr(temp," ") || strstr(temp, "\n")){
char *tmp = temp;
char *init = temp;
while(*temp != '\0'){
//remove all the \n
if(*temp != ' ' && *temp != '\n'){
*tmp = *temp;
++tmp;
}
++temp;
}
*tmp = '\0';
temp = init;
}
// check if the expression is within the limit i.e EXPL
if(count > EXPL){
printf("Expression is too long;\nMax %d digits.\nGiven %d\n ", EXPL, count);
return 1;
}
else
strcpy(exp, temp);
free(temp);
if(!validate(exp)){
free(exp);
return 1;
}
//since the expression is ready to be evaluated, let's evaluate it to produce the result
evaluate(exp);
puts(exp);
free(exp);
return 0;
}
here is replace.c
#include"replace.h"
char *replace(char *str,char *substr, char *seed, int recursive)
{
char *firstPos = strstr(str, substr);
if(!firstPos)
return NULL;
long size = 0;
long strS, substrS, seedS, occurance;
strS = substrS = seedS = occurance = 0;
//calculate length of substr, seed and str
strS = strlen(str);
substrS = strlen(substr);
seedS = strlen(seed);
//declare a __temp string variable
char *__tmp = malloc(strS + 1);
if(!__tmp){
puts("memory allocation failed!");
return NULL;
}
//calculate the size of string required to hold the replaced string and replace its occurence
if(!recursive){
size = strS + (seedS - substrS);
__tmp = realloc(__tmp, size + 1);
if(!__tmp)
return NULL;
//remove substr and store its index
long ind = (long)(firstPos - str);
strncpy(__tmp, str, ind);
__tmp[ind] = '\0';
strcat(__tmp, firstPos + substrS);
if(!seedS)
return __tmp;
return insert(__tmp, seed, ind);
}
else if(recursive){
//count the occurance of substr
strcpy(__tmp, str);
char* pos;
while((pos = strstr(__tmp, substr))){
size = strlen(__tmp) + (seedS - substrS);
long ind = (long)(pos - __tmp);
__tmp = realloc(__tmp, size + 1);
char *__temp = malloc(size + 1);
if(!__tmp || !__temp)
return NULL;
strcpy(__temp, __tmp);
// printf(">%s\n",__tmp);
strncpy(__tmp, __temp, ind);
__tmp[ind] = '\0';
// printf(">>%s\n",__tmp);
strcat(__tmp, __temp + ind + substrS);
// printf(">>>%s\n",__tmp);
free(__temp);
if(seedS){
__temp = insert(__tmp, seed, ind);
strcpy(__tmp, __temp);
free(__temp);
}
}
return __tmp;
}
return NULL;
}
char *insert(char *str, char *sed, int index)
{
int strl, sedl;
strl = (int)strlen(str);
sedl = (int)strlen(sed);
char *dest = (char*)malloc(sizeof(char) * (strl + sedl +1));
if(dest == NULL) return NULL;
strncpy(dest, str, index );
dest[index] = '\0';
strcat(dest, sed);
strcat(dest, str + index);
return dest;
}
and here is the test file
test.py
from ast import Return
import subprocess as sp
tests = ["243 + 45*3 -43 + 45/9 + 6^6",
"34 + 23 -54 + '6(76(32(56 + 45 -34(56- 34)) + 44)) *' 45 -7 ^ 5 - 4",
"43 + 3.543 - 543.36 - 56.84*23.456 + 18/5 - '45.465(56 + 45 -34(59- 24))63.86' + 34",
"5 ^ 3.543 - 543.36 - 56.84*23.456 + 18/5 - '45.465(56 + 45 -34(65- 41))63.86' + 3.345 ^ 4.65 + 456 - 29/3 ^ 2.34 - 11/4 ^ 3",
'''23 + 345- 240*4 + '6+ 4 * 4' - '(5-2) / (4+ (5-3))' *6 + "45 - 23 +24 * (3+(4+3))
+987543-45345+8635
6453354 --"''',
'''23*240*4 *'6+ 4 * 4 - (5-2) (4+ (5-3))' "45345 - 8(4+3) + 3(5-2)6 - (7+5)4 - 6(5+3^2)9 (5 * 4 -6)5 ^7" - 6 + "45 - 23 +24 * (3+(4+3))(6)"''',
" '54( 34 + 34 - 23 + 34/12 + 3 ^4)'",
" '5+54+( 34 + 34 - 23 + 256/16^2*8 + 34) - 32'",
" '69( 31 + 4 - 23 + 72/6^2*8 + 34) - 32'",
" '5+54+ 34 + 34 - 23 + (8) - 32'"
]
com = sp.run("gcc calc.c replace.c -o calc -lm", shell = True, capture_output = True, text = True)
if (com.returncode):
print(com.stderr)
exit(0)
print("~~~Compiled Successfully~~~")
for test in tests:
ret = sp.run("./calc " + test,shell=True, capture_output = True, text = True)
if(ret.stderr):
print(ret.stderr)
else:
print(ret.stdout)
Everything works fine, in the file replace.c, (tested it many time)
the error occurs in the function
evaluate()
calculate() and
operate()
in the calc.c file.
I need to 2 strings (10-bit binary numbers). I's easy when i'm adding 1+0 0+0
But how I can modify this, to situation when i'll need to make 11-bit
like
1010101010+1111111111=11010101001
i = MAX+1;
while( i!=0) {
if ((str1[i - 1] == str2[i - 1]) && (str1[i - 1] == '0' )) {
str3[i] = '0';
}
else if ((str1[i - 1] != str2[i - 1])) {
str3[i] = '1';
}
else if ((str1[i - 1] == str2[i - 1]) && (str1[i - 1] == '1')) {
str3[i] = '0';
}
i--;
}
MAX=10
It's not clear exactly what the requirements are, but I wrote a function that takes three strings, figures out their lengths using strlen, and then sets the third string equal to the sum of the first two. Here is a program that adds the two 10-bit numbers you gave and prints the expected result of "11010101001".
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
void binary_string_add(const char * a, const char * b, char * sum)
{
size_t alen = strlen(a);
size_t blen = strlen(b);
size_t sumlen = strlen(sum);
int carry = 0;
for (size_t i = 0; i < sumlen; i++)
{
if (i < alen) { carry += a[alen - 1 - i] == '1'; }
if (i < blen) { carry += b[blen - 1 - i] == '1'; }
sum[sumlen - 1 - i] = '0' + (carry & 1);
carry >>= 1;
}
}
int main()
{
char str1[] = "1010101010";
char str2[] = "1111111111";
char str3[] = "xxxxxxxxxxx";
binary_string_add(str1, str2, str3);
printf("Sum: %s\n", str3);
}
By the way, each iteration of the loop actually implements a 1-bit adder.
Update: If you want an easier interface that allocates an output string for you of the appropriate length and returns it, this works:
char * binary_string_add2(const char * a, const char * b)
{
size_t alen = strlen(a);
size_t blen = strlen(b);
size_t sumlen = (alen > blen ? alen : blen) + 1;
char * sum = malloc(sumlen + 1);
if (sum == NULL) { /** Add error handling here. **/ }
memset(sum, 'x', sumlen);
sum[sumlen] = 0;
binary_string_add(a, b, sum);
return sum;
}
#define ADDCHAR(c1,c2) (((c1) == '1') + ((c2) == '1'))
char *add(char *res, const char *n1, const char *n2)
{
size_t ln1 = strlen(n1);
size_t ln2 = strlen(n2);
char *resend = res + (ln2 > ln1 ? ln2 + 2 : ln1 + 2);
unsigned rem = 0;
*resend-- = 0;
while(ln1 || ln2)
{
unsigned pres = rem + ADDCHAR(ln1 ? n1[ln1 - 1] : '0', ln2 ? n2[ln2 - 1] : '0');
*resend-- = '0' + (pres & 1);
rem = pres >> 1;
ln1 -= !!ln1;
ln2 -= !!ln2;
}
if(rem) *resend-- = '0' + rem;
while(resend >= res) *resend-- = ' ';
return res;
}
int a = 0 ;
for(int i = 0 ; i < 10 ; i++){
str3[i] = str1[i] + str2[i] + a ;
if(str3[i] > 1){
str3[i] %= 2 ;
a = 1 ;
}
else{
a = 0 ;
}
}
I am currently doing exercices on Kattis and I meet a problem at the time of recovering the character of scanf...
I manage to recover my characters before my conditions but not during these latter...
Here is my code with comments to target my problems
#include <stdio.h>
void bela(int m, char c)
{
char card[2];
int point = 0;
printf("0 = %c\n",c); // Here c = my enter of scanf
for(int i = 0; i != m * 4; i += 1) {
scanf("%s", card);
for(int i = 0; card[i] != '\0'; i += 1) {
if(card[i] == 'A') {
point = point + 11;
printf("A = %i\n", point);
}
if(card[i] == 'K') {
point = point + 4;
printf("K = %i\n", point);
}
if(card[i] == 'Q') {
point = point + 3;
printf("Q = %i\n", point);
}
printf("1 = %c\n",c); // Here c = nothing instead of the value of c
if(card[i] == 'J' && card[i + 1] == c) { // Here c can not to be compared since he's equal to nothing...
point = point + 20;
printf("%c", card[i + 1]);// Here card[i + 1] = nothing instead of the value of c
}
else if(card[i] == 'J' && card[i + 1] != c)
point = point + 2;
if(card[i] == 'T') {
point = point + 10;
printf("T = %i\n", point);
}
if(card[i] == '9' && card[i + 1] == c) {
point = point + 14;
printf("9 + S %i\n", point);
}
}
}
printf("%i\n", point);
}
int main(void)
{
int m = 0;
char c = 0;
scanf("%i %c", &m, &c);
bela(m, c);
return (0);
}
Do you have any ideas for solve the problems ?
Thanks for your help.
PtiCassarin
in leetcode problems 67. Add Binary. I use c to solve it.
There is a confused trouble to interface the code.
#include <string.h>
char* addBinary(char* a, char* b)
{
if(a[0] == '0' && b[0] == '0')
return a;
size_t len_a = strlen(a), len_b = strlen(b);
size_t n = len_a >= len_b ? len_a : len_b;
int flag = -1;
char* num1;
char* num2;
char* res = (char*)malloc(sizeof(char) * (n + 2)); // not sizeof()*n + 2
res[n] = '\0'; // 0..n
if(len_a > len_b){
flag = 0;
num1 = a;
}
else if(len_a < len_b){
flag = 1;
num1 = b;
} else {
num1 = a;
num2 = b;
}
int i;
if(flag == 0 || flag == 1){
num2 = (char *)malloc(sizeof(char) * (n + 2));
for(i = 0; i < n; i++)
num2[i] = '0';
num2[i] = '\0';
}
//
if(flag == 0){
for(i = 0; i < len_b ; i++){
num2[n - len_b + i] = b[i];
}
} else if(flag == 1){
for(i = 0; i < len_a; i++){
num2[n - len_a + i] = a[i];
}
}
int remainder = 0, j;
for(i = n -1 ; i >= 0; i--){
j = (num1[i] - '0' + num2[i] - '0' + remainder) % 2;
res[i] = j + '0';
remainder = (num1[i] - '0' + num2[i] - '0' + remainder) / 2;
}
if (remainder == 1){
char *ans = (char*)malloc(sizeof(char) * (n + 2));
for(i = 1;i <= n; i++){
ans[i] = res[i - 1];
}
ans[0] = 1 + '0';
ans[i] = '\0';
free(res);
return ans;
} else {
free(num2);
return res;
}
}
int main()
{
char *a = "10111", *b = "110010";
char *c = addBinary(a, b);
free(c);
}
As you can see, the terrible code is mess.Different case can execute different path in addBinary func and free char *num2(freed by addBinary) or char *res(freed by main). Use main, my goal is to test case by hand,if
gcc -g -fsanitize=address leetcode-67.c -o 67
vimerbf#debian:~/test/leetcode$ ./67
it will throw:
==2252==ERROR: LeakSanitizer: detected memory leaks
Direct leak of 8 byte(s) in 1 object(s) allocated from:
#0 0x7fcd3ec9dd28 in malloc (/usr/lib/x86_64-linux-gnu/libasan.so.3+0xc1d28)
#1 0x5623d45f7d0b in addBinary /home/vimerbf/test/leetcode/leetcode-67.c:39
#2 0x5623d45f82a9 in main /home/vimerbf/test/leetcode/leetcode-67.c:99
#3 0x7fcd3e85d2e0 in __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x202e0)
SUMMARY: AddressSanitizer: 8 byte(s) leaked in 1 allocation(s).
The line 39 is:
if(flag == 0 || flag == 1){
char *num2 = (char *)malloc(sizeof(char) * (n + 2));
for(i = 0; i < n; i++)
num2[i] = '0';
num2[i] = '\0';
}
I know the num2 must be freed.But why leetcode pass my code above?
Are there some problem in my main function?
Thanks!
I have a C code(find next smallest palindrome), which when I run in my local Mac(osx: 10.11.4) and in ideone, it gives wrong result for the same input. It does not give wrong for all the inputs but for some of the inputs.
For example here is ran by ideone: http://ideone.com/T4tqak
Here are my results for same input:
input in local:
8
97795375756122352572879826552151654387112262
1892388497169516734992356528466
19891859448286167812
47737795782241879811566697829238862994263278849942632926438725
857751275744476297149515661
699
5119783738665448121162642286
4177118624313412937235746451
output in local:
97795375756122352572877827525322165757359779
1892388497169516159617948832981
19891859444495819891
47737795782241879811566697829233292879666511897814228759773774
857751275744474447572157758
707
5119783738665445668373879115
4177118624313443134268117714
Here is the C code for reference:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int all_nine(char* input){
int result = 1, i;
for(i = 0; i < strlen(input); ++i){
if(input[i] != '9')
return 0;
}
return result;
}
char* increase_one(char* input){
int i;
for(i = strlen(input) - 1; i >= 0; --i) {
if(input[i] < '9'){
input[i] += 1;
break;
}
else{
input[i] = '0';
}
}
return input;
}
char* increase_make_palin(char* input){
int input_len = strlen(input);
int half_len = input_len%2 ? input_len/2 : input_len/2 - 1;
int carry = 1, i;
for(i = half_len; i >= 0; --i) {
int cur_val = input[i] - '0';
carry = (cur_val + carry) / 10;
int new_val = (cur_val + carry) % 10;
input[i] = input[input_len - 1 - i] = '0' + new_val;
}
return input;
}
char* next_palin_for_me(char* input){
int input_len = strlen(input);
int half_len = input_len/2 - 1, i;
for(i = half_len; i >= 0; --i) {
if(input[i] > input[input_len - 1 - i]){
input[input_len - 1 - i] = input[i];
} else {
return increase_make_palin(input);
}
}
return input;
}
char* next_palin(char* input){
int input_len = strlen(input);
if(all_nine(input)){
return next_palin_for_me(increase_one(input));
}
if(input_len == 1){
input[0] += 1;
return input;
}
input = increase_one(input);
return next_palin_for_me(input);
}
int main() {
int n, i;
scanf("%d", &n);
char input[1000010];
for(i = 0 ; i < n ; i++){
scanf("%s", input);
char* result = next_palin(input);
printf("%s\n", result);
}
return 0;
}
The problem is here:
char* increase_make_palin(char* input){
...
carry = (cur_val + carry) / 10;
int new_val = (cur_val + carry) % 10;
...
}
Note that you change carry before you use it. Reverse the order of these two lines, and your code will work as you expect.
You can use 8799 as test input, to see how this works. You could have discovered this yourself, by stepping through with a debugger, or reducing your failure case to a simpler one.
As for why it gave the correct answer with the wrong code on ideone (if it actually did; I haven't tried it), I can only guess that perhaps the encoding of the numerals is different there, which would cause trouble with your "- '0'" approach.
Edit:
char* increase_make_palin(char* input){
int input_len = strlen(input);
int half_len = input_len%2 ? input_len/2 : input_len/2 - 1;
int carry = 1, i = half_len;
while(i > 0){
if(input_len%2 == 0){
if(input[i] == input[input_len - 1 - i]) {
i--;
continue;
}
if(input[i] > input[input_len - 1 - i]) {
carry = 0;
break;
}
else{
break;
}
}
if(input_len%2){
if(input[i-1] == input[input_len - i]){
i--;
continue;
}
if(input[i-1] > input[input_len - i]){
carry = 0;
break;
}
else{
break;
}
}
}
for(i = half_len; i >= 0; --i) {
int cur_val = input[i] - '0';
int new_val = (cur_val + carry) % 10;
carry = (cur_val + carry) / 10;
input[i] = input[input_len - 1 - i] = '0' + new_val;
}
return input;
}