Why this doesn't work

M

Milutin_Popovski

//It occures is a number palindrom,
//For example 1221 is plandrom, and 1231 is not...

#include<stdio.h>
#include<malloc.h>

struct lista{
int val;
struct lista *next;
struct lista *prev;
};

int main(int argc , char *argv[]){
int i,j, k, n, m;
struct lista *first, *temp, *temp_prev, *old, *last;
if(argc!=2 || !chk(argv[1])){
printf("\nWrong argument");
return 1;
}
m=atoi(argv[1]);
first=malloc(sizeof(struct lista));
temp=first;
old=first;
temp->next=NULL;
temp->prev=NULL;
old->prev=NULL;
n=m;
while(m>0){
temp->val=m%10;
old=temp;
temp->next=malloc(sizeof(struct lista));
temp=temp->next;
temp->next=NULL;
temp->prev=old;
m=m/10;
}
temp=first;
printf("\n======================\n");
while(temp->next){
printf("%d ", temp->val);
temp=temp->next;
}
temp=temp->prev;
last=temp;
printf("\n======================\n");
while(temp){
printf("%d ", temp->val);
temp=temp->prev;
}
temp=first;
temp_prev=last;
while(temp){
if(temp->val!=temp_prev->val) goto izlaz;
printf("\n<%d><%d>", temp->val, temp_prev->val);
temp=temp->next;
temp_prev=temp_prev->prev;
}
printf("\n%d is palindrom", n);
return 0;
izlaz:
printf("\n%d is not a palindrom", n);

return 0;
}



int chk(char *c){
if(!isdigit(*c) && *c!='\0') return 0;
if(*c=='\0') return 1;
*c++;
chk(c);
}
 
L

luser- -droog

//It occures is a number palindrom,
//For example 1221 is plandrom, and 1231 is not...
[...]
int main(int argc , char *argv[]){
   int i,j, k, n, m;
   struct lista *first, *temp, *temp_prev, *old, *last;
   if(argc!=2 || !chk(argv[1])){
      printf("\nWrong argument");
      return 1;
   } [...]
int chk(char *c){
   if(!isdigit(*c) && *c!='\0') return 0;
   if(*c=='\0') return 1;
   *c++;
   chk(c);

}

This is as far as I read. Is chk() supposed to
check that the char array contains all digits?
if not isdigit *c and *c is not nul?
The more I look at it, the less it makes sense..
How about something like ... [OTOH]

int chk(char *c){
do {
if (!isdigit(*c)) return 0;
} while(*c++);
return 1;
}
 
A

August Karlstrom

//It occures is a number palindrom,
//For example 1221 is plandrom, and 1231 is not...

As a first step I would fix the code so that it compiles without warnings.

$ gcc -Wall -Wextra -ansi -pedantic test.c
test.c: In function ‘main’:
test.c:13: warning: implicit declaration of function ‘chk’
test.c:17: warning: implicit declaration of function ‘atoi’
test.c:11: warning: unused variable ‘k’
test.c:11: warning: unused variable ‘j’
test.c:11: warning: unused variable ‘i’
test.c: In function ‘chk’:
test.c:66: warning: implicit declaration of function ‘isdigit’
test.c:68: warning: value computed is not used
test.c:70: warning: control reaches end of non-void function


/August
 
I

Ike Naar

//It occures is a number palindrom,
//For example 1221 is plandrom, and 1231 is not...

If you write 1231 in base 11 notation, it becomes a1a which _is_ a palindrome.
 
U

Ulrich Bellgardt

//It occures is a number palindrom,
//For example 1221 is plandrom, and 1231 is not...

#include<stdio.h>
#include<malloc.h>

struct lista{
int val;
struct lista *next;
struct lista *prev;
};

int main(int argc , char *argv[]){
int i,j, k, n, m;
struct lista *first, *temp, *temp_prev, *old, *last;
if(argc!=2 || !chk(argv[1])){
printf("\nWrong argument");
return 1;
}
m=atoi(argv[1]);
first=malloc(sizeof(struct lista));
temp=first;
old=first;
temp->next=NULL;
temp->prev=NULL;
old->prev=NULL;
n=m;
while(m>0){
temp->val=m%10;
old=temp;
temp->next=malloc(sizeof(struct lista));
temp=temp->next;
temp->next=NULL;
temp->prev=old;
m=m/10;
}

Now you have allocated one "struct lista" too many, the last
one being empty.
temp=first;
printf("\n======================\n");
while(temp->next){
printf("%d ", temp->val);
temp=temp->next;
}
temp=temp->prev;
last=temp;

This "last" struct lista contains the last digit, but it also
has a successor, namely the empty one that has been allocated
above.
printf("\n======================\n");
while(temp){
printf("%d ", temp->val);
temp=temp->prev;
}
temp=first;
temp_prev=last;

The following loop iterates to the empty, "really last" list
element, but then temp_prev is NULL and the program crashes
while evaluating temp_prev->val.
while(temp){
if(temp->val!=temp_prev->val) goto izlaz;
printf("\n<%d><%d>", temp->val, temp_prev->val);
temp=temp->next;
temp_prev=temp_prev->prev;
}

[... the rest snipped ...]


One fix would be to cleanup the initialisation phase, so that it
allocates only as many list elements as really required. A second,
rather quick and dirty repair would be to replace the while(temp)
condition by while(temp->next).

The code contains more issues, such as missing error handling in the
cases where the malloc() operations fail, or failing to free() the
allocated memory portions when they are not needed anymore.

-Uli
 
I

Ike Naar

//It occures is a number palindrom,
//For example 1221 is plandrom, and 1231 is not...
[code snipped]

Hint: you can check if an integer is a palindrome without converting
it to a string representation (so, working with integers only).
This may lead to a program that is much simpler than what you wrote.
 
B

BartC

Milutin_Popovski said:
//It occures is a number palindrom,
//For example 1221 is plandrom, and 1231 is not...

#include<stdio.h>
#include<malloc.h>

struct lista{
int val;
struct lista *next;
struct lista *prev;
};

int main(int argc , char *argv[]){
int i,j, k, n, m;
struct lista *first, *temp, *temp_prev, *old, *last;

I'm pretty sure you don't need linked lists to find out if an int value is a
palindrome when represented as a decimal.

Use a different method, and it might be easier to debug.
m=atoi(argv[1]);

(And if the number starts off as a string anyway, you might as well keep it
as one. That's then even easier. And means that 01210 will be palindromic,
but 1210 won't be after converting to a number)
 
B

Ben Pfaff

Are there any numbers that are not palindromes in any base,
with the proviso that the palindrome must have at least two
"digits"? If so, which is the smallest?

I think that 2 is the smallest, because it is not a palindrome in
base 2, and with bases higher than 2 it has only one digit.
 
J

James Waldby

I think that 2 is the smallest, because it is not a palindrome in base
2, and with bases higher than 2 it has only one digit.

But 2 is a palindrome in base 1. Indeed, every number n>1 is
a palindrome in base 1 and in base n-1, so if n>1, n is not a
number that is not a palindrome in any base. However, no number
that is preceded by a minus sign is a palindrome in a
number system with a positive base.
 
N

Nick

James Waldby said:
But 2 is a palindrome in base 1. Indeed, every number n>1 is
a palindrome in base 1 and in base n-1, so if n>1, n is not a
number that is not a palindrome in any base. However, no number
that is preceded by a minus sign is a palindrome in a
number system with a positive base.

But base 1 doesn't really exist, at least not in the way the others do,
because there's no place value. For example, you can't - as far as I
can see - take a generic multiplication algorithm that works in base 2
to base something-very-large and use it on base 1 numbers.
 
K

Keith Thompson

Which suggests a little puzzle. Are there any numbers that are not
palindromes in any base, with the proviso that the palindrome must
have at least two "digits"? If so, which is the smallest?

Yes. 0 is the smallest.

Given your conditions, neither 1 nor 2 can be expressed as a
palindrome with at least two digits. Any number N > 2 can be
expressed as 11 base N-1. (Base 1 doesn't work with the usual
positional notation; if you relax the rules, 2 can be expressed as
11 base 1.)

But I think there's a non-trivial puzzle hiding in there if you
restrict the possibilities to sufficiently large numbers and
disallow 11.
 
B

Barry Schwarz

On Fri, 31 Dec 2010 01:41:07 -0800 (PST), Milutin_Popovski

It would be nice if you told us why you think it is not working.
//It occures is a number palindrom,
//For example 1221 is plandrom, and 1231 is not...

#include<stdio.h>
#include<malloc.h>

struct lista{
int val;
struct lista *next;
struct lista *prev;
};

int main(int argc , char *argv[]){
int i,j, k, n, m;
struct lista *first, *temp, *temp_prev, *old, *last;
if(argc!=2 || !chk(argv[1])){
printf("\nWrong argument");
return 1;
}
m=atoi(argv[1]);
first=malloc(sizeof(struct lista));
temp=first;
old=first;
temp->next=NULL;
temp->prev=NULL;
old->prev=NULL;

How many times do you need to set the same object to NULL?
n=m;
while(m>0){
temp->val=m%10;
old=temp;
temp->next=malloc(sizeof(struct lista));
temp=temp->next;
temp->next=NULL;
temp->prev=old;
m=m/10;
}
temp=first;
printf("\n======================\n");
while(temp->next){
printf("%d ", temp->val);
temp=temp->next;
}
temp=temp->prev;
last=temp;
printf("\n======================\n");
while(temp){
printf("%d ", temp->val);
temp=temp->prev;
}
temp=first;
temp_prev=last;
while(temp){
if(temp->val!=temp_prev->val) goto izlaz;

There is an "else" construct in the language which eliminates the need
for an unstructured goto like this.
printf("\n<%d><%d>", temp->val, temp_prev->val);
temp=temp->next;
temp_prev=temp_prev->prev;
}
printf("\n%d is palindrom", n);
return 0;
izlaz:
printf("\n%d is not a palindrom", n);

return 0;
}



int chk(char *c){
if(!isdigit(*c) && *c!='\0') return 0;
if(*c=='\0') return 1;
*c++;

Why are you bothering to dereference the pointer and then throw the
resulting char away?

You call the function recursively yet you ignore the value it returns.
What value will get passed back to main if the first character is a
valid digit?
 
T

Thad Smith

No. This argument can be generalized: N is not a palindrome in
base N, and in bases greater than N it has only one digit.

Yes. For integers greater than two, N is a palindrome in base (N-1).
 
L

luser- -droog

While the update is slightly more efficient, it has no practical
difference from the original.

Um, I think it does. I think it's crucial, in fact.
Consider chk("5");
!isdigit('5') : 0
*c++ : 1
!isdigit('\0') : 1
return 0

If you don't increment BEFORE dereferencing, you're
not checking the same value that the next iteration
will encounter.
 
B

Barry Schwarz

Um, I think it does. I think it's crucial, in fact.
Consider chk("5");
!isdigit('5') : 0
*c++ : 1
!isdigit('\0') : 1
return 0

If you don't increment BEFORE dereferencing, you're
not checking the same value that the next iteration
will encounter.

You are correct. My mistake. Sorry.
 
L

luser- -droog

You are correct.  My mistake.  Sorry.

No sweat. There's something about 'do if' that's easy
to misinterpret. I suggested something similar about
a year ago; and someone said it wasn't C.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,769
Messages
2,569,579
Members
45,053
Latest member
BrodieSola

Latest Threads

Top