I wrote two sample programs to check for a palindrome string. But in both I am getting output like, its not a palindrome number. What I am missing?
I strictly assume somehow code is executing my if statement and put flag in to 1. May be because of that length calculation. Anyone has a better idea?
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <conio.h>
int main(void) {
setbuf(stdout,NULL);
char name[100];
int i,length,flag=0,k;
printf("Enter your name");
/*scanf("%s",name);*/
gets(name);
length=strlen(name);
for(i=0;i<=length-1;i++)
{
for(k=length-1;k>=0;k--)
{
if(name[i]!=name[k])
{
flag=1;
break;
}
}
}
if(flag==0)
{
printf("Give word is a palindrome");
}
if(flag==1)
{
printf("This is NOT a palindrome word");
}
return 0;
}
and
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <conio.h>
int main(void) {
setbuf(stdout,NULL);
char name[100];
int i,length,flag=0;
printf("Enter your name");
/*scanf("%s",name);*/
gets(name);
length=strlen(name);
for(i=0;i<=length/2;i++)
{
if(name[i]!=name[length-1])
{
flag=1;
}
}
if(flag==0)
{
printf("Give word is a palindrome");
}
if(flag==1)
{
printf("This is NOT a palindrome word");
}
return 0;
}
First Algorithm
The algorithm you are using in the first program involves comparing each letter to every other letter which does not help in determining if the number is a palindrome and it does not seem fixable.
Second Algorithm
The problem with the second approach, however, is you are always comparing name[i] to name[length]. Instead change it to length-i-1. This will start comparing from length-1 and decrement the length of the character by 1 for every next iteration:
for(i = 0;i <= length / 2;i++)
{
if(name[i] != name[length-i-1])
{
flag=1;
break;
}
}
gets() and buffer overflow
Do not use gets. This method is susceptible to a buffer overflow. If you enter a string longer than 100 characters, it will result in undefined behavior. Use fgets instead for deterministic behavior:
fgets(name, sizeof(name), stdin);
This takes in the size of the buffer and only reads up to sizeof(name) characters.
Full code
Ideally, you should consider wrapping the logic to check if the string is a palindrome in a function:
int is_palindrome(char*);
int main(void)
{
char name[100];
setbuf(stdout,NULL);
printf("Enter your name");
fgets(name, sizeof(name), stdin);
if(is_palindrome(name))
{
printf("The given word is a palindrome");
}
else
{
printf("This is NOT a palindrome word");
}
return 0;
}
int is_palindrome(char* name)
{
int length = strlen(name);
int flag = 0, i;
for(i = 0;i <= length / 2; i++)
{
if(name[i]!=name[length-i-1])
{
return 0;
}
}
return 1;
}
There is plenty wrong with both your attempts. I strongly suggest using a debugger to investigate how your code works (or doesn't).
Your first attempt performs length2 (incorrect) comparisons, when clearly only length / 2 comparisons are required. The second performs length / 2 comparisons but the comparison is incorrect:
name[i] != name[length-1] ;
should be:
name[i] != name[length - i - 1] ;
Finally you iterate exhaustively when you could terminate the comparison as soon as you know they are not palindromic (on first mismatch).
There may be other errors - to be honest I did not look further than the obvious, because there is a better solution.
Suggest:
#include <stdbool.h>
#include <string.h>
bool isPalindrome( const char* str )
{
bool is_palindrome = true ;
size_t rev = strlen( str ) - 1 ;
size_t fwd = 0 ;
while( is_palindrome && fwd < rev )
{
is_palindrome = (str[fwd] == str[rev]) ;
fwd++ ;
rev-- ;
}
return is_palindrome ;
}
In use:
int main()
{
const char* test[] = { "xyyx", "xyayx", "xyxy", "xyaxy" } ;
for( size_t t = 0; t < sizeof(test)/sizeof(*test); t++ )
{
printf("%s : %s palindrome\n", test[t],
isPalindrome( test[t] ) ? "Is" : "Is not" ) ;
}
return 0;
}
Output:
xyyx : Is palindrome
xyayx : Is palindrome
xyxy : Is not palindrome
xyaxy : Is not palindrome
Try this
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main() {
char text[100];
int begin, middle, end, length = 0;
printf("enter the name: ");
scanf("%s",text);
while ( text[length] != '\0' ){
length++;}
end = length - 1;
middle = length/2;
for ( begin = 0 ; begin < middle ; begin++ ) {
if ( text[begin] != text[end] ) {
printf("Not a palindrome.\n");
break;
}
end--;
}
if( begin == middle )
printf("Palindrome.\n");
return 0;
}
The problem with the first piece of code is you are comparing it more than required, compare it with length-i-1.
The main problem with the second code is you are comparing it with only the last letter of a word.
Hope you understood your mistake
Related
The function should check if an input string is a palindrome. It should not be case sensitive, and must ignore every other character except letters and numbers. The thing I am having problems with is when the string is empty(that means only the spaces are elements of the string), and when the string has a lot of other characters, but no letters or numbers.
This is my code, and it works well, except in the cases stated above.
#include <stdio.h>
#include <string.h>
#include <ctype.h>
int is_it_palindrome(const char* str){
int lenght;
lenght=strlen(str);
const char *start=str+0;
const char *end=str+lenght-1;
while(start<end){
if(!isalnum(*start)){
start++;
}
else if(!isalnum(*end)){
end--;
}
else if(toupper(*start)==toupper(*end)){
start++;
end--;
}
else{
return 0;
}
}
return 1;
}
int main() {
printf ("%d", is_it_palindrome(" "));
printf ("%d", is_it_palindrome("a"));
printf ("%d", is_it_palindrome(",./!\n+_[]{}#"));
printf ("%d", is_it_palindrome(",./!\n+_A[]{}#"));
return 0;
}
The function returns 0 if it is not a palindrome, and 1 if it is a palindrome. So the output here should be 0 1 0 1, but I get 1 1 1 1. I really don't know how to rewrite this program to contain the conditions that I need. I would really appreciate the help.
A string containing no alphanumeric characters is not a palindrome according to your rules yet it doesn't ever reach return 0; cause you skip over non alpha numeric characters.
To check it you have to add a flag that tracks if you have any alpha numeric characters at all.
Additionally to detect the single alnum char I go to start <= end instead of start < end
#include <stdio.h>
#include <string.h>
#include <ctype.h>
int is_it_palindrome(const char* str) {
int lenght;
int has_alnum = 0;
lenght=strlen(str);
const char* start = str + 0;
const char* end = str + lenght - 1;
while (start <= end) {
if (!isalnum(*start)) {
start++;
} else if (!isalnum(*end)) {
end--;
} else if (toupper(*start) == toupper(*end)) {
has_alnum = 1;
start++;
end--;
} else {
return 0;
}
}
return has_alnum;
}
int main(void) {
printf("%d", is_it_palindrome(" "));
printf("%d", is_it_palindrome("a"));
printf("%d", is_it_palindrome(",./!\n+_[]{}#"));
printf("%d", is_it_palindrome(",./!\n+_A[]{}#"));
return 0;
}
I'm working in a problem from the "C programming a Modern Approach 2nd Edition" text. I want to write a program that writes the smallest and largest words. The program stops accepting inputs when the user enters a 4-letter word.
I'm using an array of strings to solve this but I can't even get my program to store words in it.
#include <stdio.h>
#include <string.h>
#define WORD_LEN 20
int main()
{
char word[WORD_LEN]={0},ch;
char *a[10]={}; //Max 10 words in the array
int i=0,j;
for(;;)
{
printf("Enter a word: ");
fgets(word,WORD_LEN,stdin);
strtok(word, "\n"); //removes newline
a[i] = word;
if(strlen(word) == 4) //if word is 4 characters
break; //break out of loop
i++;
}
for(j=0;j<i;j++) //displaying array
printf("%s\n",a[j]);
return 0;
}
Output:
Enter a word: Analysis
Enter a word: Martin
Enter a word: Jonathan
Enter a word: Dana
Dana
Dana
Dana
Any idea into what I'm doing wrong? Thanks.
As BLUEPIXY mentioned, you are storing same address in all a[i]s. So at the end of the loop, it prints the last output i times.
Solution:
You need to allocate memory for a[i] and copy the strings.
#include <stdio.h>
#include <string.h>
#define WORD_LEN 20
#define MAX_NUM_WORD 10 //Max 10 words in the array
int main()
{
char word[WORD_LEN]={0},ch;
char *a[MAX_NUM_WORD]={0};
int i=0,j;
for(;;)
{
printf("Enter a word: ");
fgets(word,WORD_LEN,stdin);
strtok(word, "\n"); //removes newline
a[i] = malloc(sizeof(char)* (strlen(word)+1)); //1 for '\0'
strcpy(a[i], word);
i++;
if(strlen(word) == 4) //if word is 4 characters
break; //break out of loop
//i++; //You will be missing last 4 letter word if i++ is here.
if(MAX_NUM_WORD <= i) //You can store only MAX_NUM_WORD strings
break;
}
for(j=0;j<i;j++) //displaying array
printf("%s\n",a[j]);
//Your other code.
for(i=0; i<MAX_NUM_WORD && NULL != a[i]; i++)
free(a[i]); //Free the allocated memory.
return 0;
}
Adding to others answers, when using malloc to allocate memory for your strings, it is good to also check the return value of void* pointer returned from it.
Additionally, it is also safe to check the return value of fgets, just to be super safe.
This solution demonstrates these points:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define WORD_LEN 20
#define MAX_NUM_WORD 10
#define EXIT_LEN 4
int
main(void) {
char word[WORD_LEN];
char *a[MAX_NUM_WORD];
int i = 0, wrd;
while (i < MAX_NUM_WORD) {
printf("Enter a word: ");
if (fgets(word, WORD_LEN, stdin) != NULL) {
word[strlen(word)-1] = '\0';
}
a[i] = malloc(strlen(word)+1);
if (a[i] == NULL) {
fprintf(stderr, "%s\n", "Malloc Problem");
exit(EXIT_FAILURE);
}
strcpy(a[i], word);
i++;
if (strlen(word) == EXIT_LEN) {
break;
}
}
// Print and free, all at once.
for (wrd = 0; wrd < i; wrd++) {
printf("%s\n", a[wrd]);
free(a[wrd]);
a[wrd] = NULL;
}
return 0;
}
I am trying to take a user inputted string and look at each code to see if it appears in another string of strings. So far my code works.
If the word is successfully found then the alpha representation is to be added to an array that will eventually be printed, but only if all codes were found.
I am having issues with what gets stored in my array that is going to be printed.
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
typedef char *string;
typedef char *alpha;
int main(void)
{
string morse[4]={".-", "-...","----.", ".."};
string alpha[4]={"A", "B", "9", "I"};
char prntArr[50];
char *input;
char *hold;
input = malloc(200);
hold = malloc(50);
int i=0;
int j=0;
int ret;
int x;
int w=0;
int z=0;
printf("please enter a string\n");
scanf("%[^\n]",input);
do{
if (input[i] !=' ')
{
hold[j] = input[i];
j++;
}
else
{
hold[j]='\0';
for (x=0;x<4;x++)
{
printf("value of x %d\n",x);
ret = strcmp(morse[x], hold);
if (ret==0)
{
printf("%s\n",alpha[x]);
prntArr[w]=*hold;
w++;
x=4;
}
else
{
ret=1;
printf("invalid Morse code!");
}
}
j = 0;
}
i++;
}while(input[i] !='\0');
for (z=0;z<50;z++)
{
printf("%c",prntArr[z]);
}
return 0;
free(input);
}
The problem you asked about is caused by the way prntArr is used in the program. It really should be an array of character pointers into the alpha array. Instead, it's manipulated as an array of characters into which the first character of each morse code element is stored. And when it's printed, the variable that tracks how much of the array is used is simply ignored.
Another problem is that your code uses spaces to break the codes but there won't necessarily be a space at the end of the line so a code might get missed. In the program below, I switched out scanf() for fgets() which leaves a newline character on the end of the input which we can use, like space, to indicate the end of a code.
Other problems: you print the invalid Morse code message at the wrong point in the code and you print it to stdout instead of stderr; you remember to free input but forget to free hold; you put code after return that never gets called.
Below is a rework of your code that addresses the above problems along with some style issues:
#include <stdio.h>
#include <string.h>
#include <stdbool.h>
int main(void)
{
char *morse[] = {".-", "-...", "----.", ".."};
char *alpha[] = {"A" , "B" , "9" , "I" };
char *print_array[50];
int print_array_index = 0;
char hold[50];
int hold_index = 0;
char input[200];
int i = 0;
printf("please enter a string: ");
fgets(input, sizeof(input), stdin);
while (input[i] !='\0') {
if (input[i] ==' ' || input[i] == '\n')
{
hold[hold_index] = '\0';
bool found = false;
for (int x = 0; x < sizeof(morse) / sizeof(char *); x++)
{
if (strcmp(morse[x], hold) == 0)
{
print_array[print_array_index++] = alpha[x];
found = true;
break;
}
}
if (!found)
{
fprintf(stderr, "invalid Morse code: %s\n", hold);
}
hold_index = 0;
}
else
{
hold[hold_index++] = input[i];
}
i++;
}
for (int x = 0; x < print_array_index; x++)
{
printf("%s ", print_array[x]);
}
printf("\n");
return 0;
}
SAMPLE RUNS
> ./a.out
please enter a string: ----. -... .- ..
9 B A I
>
> ./a.out
please enter a string: .- --- ..
invalid Morse code: ---
A I
>
This is the problem I'm trying to solve:
Input:
First line contains N, the size of the string.
Second line contains the letters (only lowercase).
Output:
Print YES if all vowels are found in the string, NO otherwise.
Constraints:
The size of the string will not be greater than 10,000. 1 ≤ N ≤ 10000
The following code I wrote is always showing NO.
#include <stdio.h>
#include<conio.h>
int main()
{
int a,b,c=0,d=0,e=0,f=0,g=0,i;
char string[10000];
scanf("%d",&a);
scanf("%s",string);
for(i=0;i<a;a++)
{
if(string[i]==('a'))
c=1;
if(string[i]==('e'))
d=1;
if(string[i]==('i'))
e=1;
if(string[i]==('o'))
f=1;
if(string[i]==('u'))
g=1;
}
if((c==1)&&(d==1)&&(e==1)&&(f==1)&&(g==1))
printf("YES");
else
printf("NO");
return 0;
getch ();
}
Here is an infinite loop that causes a problem:
for(i=0;i<a;a++)
You should increment i, instead of a (length of a string). If you fix this one char in loop statement, the program will run well at all. Anyway, I changed your code a bit to be more readable. Take a look if you want, just for your information, sir:
#include <stdio.h>
#include <stdlib.h>
int main()
{
int len, a=0, e=0, i=0, o=0, u=0, it;
char string[10000];
scanf("%d", &len);
scanf("%s", string);
for(it=0;it<len;it++)
{
if(string[it]=='a') a = 1;
else if(string[it]=='e') e = 1;
else if(string[it]=='i') i = 1;
else if(string[it]=='o') o = 1;
else if(string[it]=='u') u = 1;
}
if(a && e && i && o && u) printf("YES\n");
else printf("NO\n");
system("PAUSE");
return 0;
}
I assume you are running your program under Windows, so instead of conio's getch() try to use system("PAUSE") or just even better way to do this (for both Windows for UNIX): getchar()
I've renamed all of your variables, but otherwise left the code the same.
#include <stdio.h>
#include<conio.h>
int main()
{
int foundA = 0, foundE = 0, foundI = 0, foundO = 0, foundU = 0;
int i, length;
char string[10000];
scanf("%d", &length);
scanf("%s", string);
for(i=0; i<length; length++)
{
if(string[i]==('a'))
foundA=1;
else if(string[i]==('e'))
foundE=1;
else if(string[i]==('i'))
foundI=1;
else if(string[i]==('o'))
foundO=1;
else if(string[i]==('u'))
foundU=1;
}
if((foundA==1)&&(foundE==1)&&(foundI==1)&&(foundO==1)&&(foundU==1))
printf("YES");
else
printf("NO");
return 0;
getch ();
}
Looking the the for-loop condition for(i=0; i<length; length++), I think it's pretty clear what's wrong. Instead of incrementing the counter, you're incrementing the length of the string. Eventually, the counter overflows to a negative number, and the loop terminates without ever looking at a character besides the first one. The lesson here is to name your variables properly.
If you want to be picky, then signed integer overflow is undefined behavior, but for most systems, INT_MAX + 1 will be INT_MIN.
This program can be done in more simpler way other as below.
#include <stdio.h>
#include<conio.h>
int main()
{
int i, flag = 0;
char string[10000], *ptr;
char cmp[] = "aeiou";
printf("Please enter string = " );
scanf("%s", string);
i = 0;
while(cmp[i])
{
ptr = string;
while(*ptr)
{
if(cmp[i] == *ptr)
break;
ptr++;
}
if(*ptr != cmp[i++])
{
flag = 1;
break;
}
}
if(flag == 1)
printf("NO");
else
printf("YES");
}
In this program I have used just one flag instead of 5 flags. Always try to write simple code rather then using unnecessary variable and flags.
I must do a program that tells me if a string is palindrome or not using the library string.h . I wrote the following code but the output is always "palindrome"
#include<stdio.h>
#include<conio.h>
#include<string.h>
int main()
{
char a[100],b[100];
int i,k;
printf("Type the string \n");
gets(a);
k=strlen(a);
for(i=0;i<strlen(a);i++)
{
a[i]=b[k];
k--;
} //at the end of this code the string "b" should be the reverse of "a"
k=strcmp(a,b);
if (k!=0) //here I check if a=b or not
{printf("palindrome");}
else
{printf("not palindrome");}
getch();
return 0;
}
Example: When my input is "non" the output should be "palindrome", if the input is "ship" the output should be "not palindrome". Could anyone help me to find what is wrong?
I think it's the line
a[i]=b[k];
Doesn't this put the contents of b[k] (which you have not initialized) into a[i] (which you have populated with the get)? This overwrites the test value in a with blanks, (or whatever was in b's memory) Shouldn't you do the opposite?
But better is not to do it at all - you can just compare the characters in place in the a array.
k=strlen(a);
for(i=0; i<k/2; i++)
if(a[i] != a[k-i])
return "Not Palindrome";
return "Palindrome";
/**
** Name: palindrome.c
** Description: This program checks if a word is palindrome or not
** Aldo Núñez Tovar
**/
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
int
isPalindrome ( char* str )
{
char* str2 = str + strlen ( str) - 1;
while ( str < str2 )
{
if ( *str++ != *str2-- )
{
return 0;
}
}
return 1;
}
int
main ( void )
{
char* str = "racecar"; /* level, civic, rotor, racecar */
printf ( "Is %s palindrome? %s\n", str, isPalindrome ( str )? "Yes": "No" );
return 0;
}
I fixed it for you, please note the comments:
#include<stdio.h>
#include<conio.h>
#include<string.h>
int main()
{
char a[100],b[100];
int i;
int stringLen;
printf("Type the string \n");
gets(a);
stringLen = strlen(a);
for(i=0; i < stringLen; i++)
{
//First you want to copy to B not A...
//second, you need to remove "1" from the size cause array start from "0".
b[stringLen-1-i] = a[i];
}//at the end of this code the string "b" should be the reverse of "a"
if (strcmp(a,b) == 0) //0 mean equal !
{
printf("palindrome");
}
else
{
printf("not palindrome");
}
getch();
return 0;
}
strcmp() returns zero value when both strings are equal.
It must be something like this:
#include<stdio.h>
#include<conio.h>
#include<string.h>
int main()
{
char a[100],b[100];
int i,k;
printf("Type the string \n");
gets(a);
k=strlen(a)-1;
for(i=0;i<strlen(a);i++)
{
b[i]=a[k]; //assign to b not to a
k--;
}
b[strlen(a)]='\0';//terminate the string with null character
//at the end of this code the string "b" should be the reverse of "a"
k=strcmp(a,b);
if (k==0) //here I check if a=b or not
{printf("palindrome");}
else
{printf("not palindrome");}
getch();
return 0;
}
Your code says this:
k=strlen(a);
Fix this like
k=strlen(a)-1;
This is because if the length is 15, then array index 0 to 14 equals 15.
So, reverse it from 14. That means length-1.
Got it?