Logical error in recursive function - c

I'm writing a program to check whether a string is palindrome or not using recursion.Palindrome string is the one that can be read backwards just the same as reading it forward. However following is my code:
#include <stdio.h>
#include <stdlib.h>
int main()
{
int num;
printf("Enter the number of characters in your string\n");
scanf("%d",&num);
char string[num];
char string2[num];
int i;
printf("Enter your string\n");
for (i=0;i<num;i++)
{
scanf("%c",&string[i]);
}
fillString(string,string2,num);
int palin = isPalind(string,string2,num);
if (palin) printf("The string you entered is palindrome");
else printf("The string you entered is not palindrome");
return 0;
}
int isPalind(char string[],char string2[],int num)
{
int i=0;
while (i<num)
{
if (string[i]!=string2[i])
{
i++;
return 0;
}
else{
i++;
return 1*isPalind(string,string2,num);
}
}
}
void fillString(char string[],char string2[],int num)
{
int i;
for (i=1;i<num;i++)
string2[i-1]=string[num-i];
}
I have a logical error, the program compiles fine and executes but it always gives out "The string is not palindrome"

In the fillString the loop is iterating num-1 times (i is from 1 to num-1), so not the whole string is copied. The first character of the original string is omitted. You should do
for (i=1;i<=num;i++) ...
As for the recursive function, it is not really recursive. In recursive call modified input should be passed, but in your case exactly the same input is passed. So in case of true palindrome, it's likely you will get stack overflow due to non-termination. I would propose another approach, to work with single string recursively:
1) Base case: String is a palindrome if of length 0 or 1
2) Recursion step: String is a palindrome if the first character equals to the last and the string without first and last characters is palindrome.

Is your fillString() function reversing your string as expected? It looks like the first letter of string1 is not getting added into the last position of string2 because the for loop stops when i < num fails. Try switching it to i <= num and seeing if that helps.
Double-check this example:
Given: String1 = "Hello". String2 = null for now. num = 5.
void fillString(char string[],char string2[],int num)
{
int i;
for (i=1;i<num;i++)
string2[i-1]=string[num-i];
}
When i = 4, you have string2 = 'olle'. When i = 5, the for loop condition fails, so it doesn't populate string2[4] = 'H'.
updated:
void fillString(char string[],char string2[],int num)
{
int i;
for (i=1;i<=num;i++)
string2[i-1]=string[num-i];
}

The both functions are wrong. They can be written the following way
int isPalind( const char string[], const char string2[], int num )
{
return ( num == 0 ) ||
( string[0] == string[--num] && isPalind( string + 1, string2, num ) );
}
void fillString( const char string[], char string2[], int num )
{
int i;
for ( i = 0; i < num; i++ ) string2[i] = string[num-i-1];
}
If you need not necessary a recursive function then you could use simply standard function memcmp that to determine whether two strings are equal.

Related

Are the digits in a given string strictly ascending?

I am a beginner programmer and I'm having trouble with this task.
I have to write a function that checks if the digits in the given string are strictly ascending, or better say is each digit larger than the previous one.
Function returns true or false, but it also has to be able to return -1 if there are no numbers in the string.
So for the string: "a1b2c3d" the function should return 1,
but for "a1b3c3d" the function should return 0 because they are not strictly ascending.
I cannot use arrays or create new strings.
#include <stdio.h>
#include<ctype.h>
//we have to enter our strings like this
void unesi(char niz[],int velicina)
{
char znak=getchar();
if(znak=='\n')
znak=getchar();
int i=0;
while(i<velicina-1 && znak!='\n')
{
niz[i]=znak;
i++;
znak=getchar();
}
niz[i]='\0';
}
//function checks if the string contains any digits
int cifre(const char *s)
{
int istina=1;
if(isdigit(*s++))
istina=0;
return istina;
}
int srce(const char *s)
{
int broj=1,istina=0;
if(cifre(s)==1)
return -1;
else
{
while(*s!='\0')
{
if(isdigit(*s)==1)
{
if(*s<broj)
{
broj=*s;
istina=1;
s++;
}
}
else
s++;
}
return istina;
}
}
int main() {
char a[100];
unesi(a,100);
printf("%d",srce(a));
return 0;
}
Logic is quite simple.
The function returns -1 if there is no digits
1 if they are sorted in ascending order or zero if not
int isAsc(char *str)
{
int result = -1;
int last = -1;
while(*str)
{
if(isdigit((unsigned char)*str))
{
result = 1;
if(last != -1)
{
if(*str - '0' < last)
{
result = 0;
break;
}
}
last = *str - '0';
}
str++;
}
return result;
}
int main(void)
{
printf("%d\n", isAsc("dsfgdfgdfgfgd"));
printf("%d\n", isAsc("d0sfg1dfg4dfg7fgd"));
printf("%d\n", isAsc("d0sfg1dfg4dfg7f2gd"));
}
//we have to enter our strings like this
It's unclear to me if the whole unesi function is given as part of the assignment and can't be modified or not, so I won't comment it.
Just read about fgets, in the future.
I cannot use arrays
Well, I guess that restriction is somehow relaxed:
char a[100];
That's "literally" an array of 100 chars. Hopefully, it will be null-terminated, so that we can consider it a "string".
//function checks if the string contains any digits
That comment is lying, cifre is only checking the first character, because there is no loop, nor any calling to a function that could traverse a char array inside it.
Besides, instead of checking beforehand if the string contains any digit, you could start searching for the first digit and then check if the other digits are in strictly ascending order.
In srce function, we can find
int srce(const char *s)
{
int broj=1, istina=0;
// ^^^^^^ ^^ Note that the starting value of broj is 1.
// [...]
while(*s!='\0')
{
if(isdigit(*s)==1)
{
if( *s < broj )
{ //^^^^^^^^^ Are any of '0', '1', '2'... less than 1?
// Is this supposed to be the path taken when
// the digits are not in STRICTLY ascending order?
// In that case you should check if the current digit
// is less than OR EQUAL to the previous one.
broj=*s;
istina=1; // Shouldn't it be 0 when the order is not correct?
s++; // Shouldn't the traversal of the string just end now?
}
}
else
s++;
}
return istina;
}
Another subtle issue with the previous code is that isdigit1 returns a non-zero value if the character is a numeric character, not necessarly 1.
(1) About isdigit call, see also: Why is it OK to pass mismatch argument into isdigit function?

Reversing String Only Using For Loop

I have been trying to reverse(and print it that way) a given string only using for loops and nothing more. I think I have built up the basic logic, but it has some defects. When run, it only reverses the first two characters and then stops. Please help me find the defect in my logic.
#include<stdio.h>
#include<stdlib.h>
int main()
{
char a[20];
int i;
printf("Enter any String\n");
gets(a);
for(i=0;a[i]!=NULL;i++)
{}
for(i=1;i>=0;i--)
{
printf("%c",a[i]);
}
}
For starters the function gets is not a standard C function any more. it is unsafe. Instead use the standard C function fgets. The function can append the new line character '\n' to the entered string that should be excluded from the string.
It is unclear from your question whether you are allowed to use standard string functions.
Nevertheless here is a demonstrative program that does the task without using standard C string functions and that uses only for loops (neither while loop nor do-while loop).
#include <stdio.h>
int main(void)
{
enum { N = 20 };
char s[N];
printf( "Enter any String less than %d symbols: ", N );
fgets( s, N, stdin );
// remove the new line character and calculate the length of the string
size_t n = 0;
for ( ; s[n] != '\0' && s[n] != '\n'; ) ++n;
s[n] = '\0';
// reverse the string
for ( size_t i = 0; i < n / 2; i++ )
{
char c = s[i];
s[i] = s[n-i-1];
s[n-i-1] = c;
}
puts( s );
return 0;
}
Its output might look the following way
Enter any String less than 20 symbols: Hello dev.aniruddha
ahddurina.ved olleH
If you want just to output the original string in the reverse order then the program can look like
#include <stdio.h>
int main(void)
{
enum { N = 20 };
char s[N];
printf( "Enter any String less than %d symbols: ", N );
fgets( s, N, stdin );
// remove the new line character and calculate the length of the string
size_t n = 0;
for ( ; s[n] != '\0' && s[n] != '\n'; ) ++n;
s[n] = '\0';
// reverse the string
for ( ; n-- != 0; )
{
putchar( s[n] );
}
putchar( '\n' );
return 0;
}
Its output is the same as shown above
Enter any String less than 20 symbols: Hello dev.aniruddha
ahddurina.ved olleH
gets() is a bad idea as you can easily get overflows and it is no longer part of the c standard.
So let's assume that the string entered fits the array and this is just for an excercise with no reallife usage.
Your first loop finds the terminator. That's good.
Your second loop sets the variable that indicates the terminator to 1, destroying the result.
If you remove the assignment i=1, your program compiles with gcc and does what you want.
#include<stdio.h>
#include<stdlib.h>
int main()
{
char a[20];
int i;
printf("Enter any String\n");
gets(a);
for(i=0;a[i]!=NULL;i++)
{}
for(;i>=0;i--) //removed i=1 here
{
printf("%c",a[i]);
}
}
But there are still some issues to be addressed.
You will also reverse the terminator, instead you should start from i-1
I would advise to not use a for loop if you do not have a counter criterion The first loop should rather be a while loop, but as it was part of the assignment you had no choice still I will replace it in my recommendation. As they can easily be swapped.
Then you could use another variable for the second loop for clarity.
Also NULL is the NULL-pointer not the value 0 (also namend NUL apperantly) . So you should replace this either with 0 or with '\0'
Also stdlib.h is not required here
#include<stdio.h>
int main()
{
char a[20];
int i = 0;
printf("Enter any String\n");
gets(a);
while (a[i] != 0)
{
i++;
}
for(int j = i-1; j>=0; j--) // -1 to get the value in front of the terminator
{
printf("%c",a[j]);
}
printf("\n"); //to flush the output.
}
Here is the solution code.
The first for loop is to be used for determining the length of the string and the second for loop is for traversing the string from the last position to the first.
#include<stdio.h>
int main()
{
char a[20];
int i,j,len;
printf("Enter a String\n");
gets(a);
for(i=0;a[i]!=NULL;i++)
{}
len=i;
for(j=len-1;j>=0;j--)
{
printf("%c",a[j]);
}
}
I think why only two chars are been return is because of the condition statement in your second "for loop".
for(i=1;i>=0;i--)
Note:
it repeats from 1~0 (1,0): meaning it will repeat only twice
first iteration: when i == 1
second iteration: when i == 0 ; then it ends .
Please note that you created two "for loops" with the first one having no content.
Bonus:
I tried to fixed your code but realized that my C language skills isnt the best lol . Anyways, i came up with something that you could reference but it only reverse strings of less than 8 elements.
#include<stdio.h>
#include<stdlib.h>
int findlength(char a[]);
int main()
{
char a[20];
int i;
printf("Enter any String\n");
gets(a);
int len = findlength(a);
printf("Lenght of the String is: %d \n",len);
printf("Reversed String is: ");
for(i=len;i>-1;i--){
printf("%c",a[i]);
}
}
int findlength(char a[]){
int result = 0;
int i;
for(i=0;i<sizeof(a) / sizeof(char);i++){ // sizeof(char) is 1
if(a[i] == '\0') //end of string
return result;
result += 1;
}
return result;
}

Program that checks if an array is a palindrome

I'm trying to create a program that checks if a given array/string is a palindrome or not and its not working. The program just prints "0" on every given array, even on palindromes.
int main()
{
char string[100]= {0};
char stringReverse[100]= {0};
int temp = 0;
int firstLetter = 0;
int lastLetter = 0;
printf("Please enter a word or a sentence: ");
fgets(string, 100, stdin);
strcpy(stringReverse , string); // This function copies the scanned array to a new array called "stringReverse"
firstLetter = 0;
lastLetter = strlen(string) - 1; //because in array, the last cell is NULL
// This while reverses the array and insert it to a new array called "stringReverse"
while(firstLetter < lastLetter)
{
temp = stringReverse[firstLetter];
stringReverse[firstLetter] = stringReverse[lastLetter];
stringReverse[lastLetter] = temp;
firstLetter++;
lastLetter--;
}
printf("%s %s", stringReverse, string);
if ( strcmp(stringReverse , string) == 0)
{
printf("1");
}
else
{
printf("0");
}
}
Lets say we implement a simple fun to do that
int check_palindrome (const char *s) {
int i,j;
for (i=0,j=strlen(s)-1 ; i<j ; ++i, --j) {
if (s[i] != s[j]) return 0; // Not palindrome
}
return 1; //Palindrome
}
I think this is far more simpler ;)
For the code posted in question:
Be aware of fgets(). It stops in the first '\n' or EOF and keeps the '\n' character.
So if you give radar for ex, the result string will be "radar\n", which doesn't match with "\nradar"
The Problem:
Let's say you enter the string RACECAR as input for your program and press enter, this puts a newline character or a '\n' in your buffer stream and this is also read as part of your string by fgets, and so your program effectively ends up checking if RACECAR\n is a palindrome, which it is not.
The Solution:
After you initialize lastLetter to strlen(string) - 1 check if the last character in your string (or the character at the lastLetter index is the newline character (\n) and if so, decrease lastLetter by one so that your program checks if the rest of your string (RACECAR) is a palindrome.
lastLetter = strlen(string) - 1; //because in array, the last cell is NULL
// Add these 2 lines to your code
// Checks if the last character of the string read by fgets is newline
if (string[lastLetter] == '\n')
lastLetter--;
fgets adds a '\n' at the end.
So if the user entered "aba", string contains "aba\n".
reverseString contains "\naba".
So it doesn't match.
After the fgets, add this code
int l = strlen(string) - 1;
string[l] = 0;
This will strip out the '\n' at the end before copying it to reverseString.
That aside, you can do this whole program inplace without the need of a second buffer or strcpy or strlen calls.
You have several issues in your code:
first you forgot the last closing brace };
then you forgot to remove the trailing \n (or maybe also \r under Windows) in string;
you don't need to revert the string into a new string; a one-pass check is enough:
Here is a working code:
#include <stdio.h>
#include <string.h>
int main()
{
char string[100]= {0};
int temp = 0;
int firstLetter = 0;
int lastLetter = 0;
printf("Please enter a word or a sentence: ");
fgets(string, 100, stdin);
firstLetter = 0;
lastLetter = strlen(string) - 1; //because in array, the last cell is NULL
while ((string[lastLetter]=='\n')||(string[lastLetter]=='\r')) {
lastLetter--;
}
// This while reverses the array and insert it to a new array called "stringReverse"
temp = 1;
while(firstLetter < lastLetter)
{
if (string[firstLetter] != string[lastLetter]) {
temp = 0;
break;
}
firstLetter++;
lastLetter--;
}
if ( temp )
{
printf("1");
}
else
{
printf("0");
}
}
You can do it by this simpleway also.
#include <stdio.h>
#include <string.h>
int main()
{
char string[10], revString[10];
printf("Enter string for reversing it...\n");
scanf("%s", string);
int stringLength = strlen(string);
for(int i = 0; string[i] != '\0'; i++, stringLength--)
{
revString[i] = string[stringLength - 1];
}
if(strcmp(string, revString) == 0)
printf("Given string is pelindrom\n");
else
printf("Given string is not pelindrom\n");
}
#include<stdio.h>
#include<string.h>`enter code here`
void fun(char *a);
int main ()
{
char p[100];
char *s=p;
printf("enter the string");
scanf("%[^\n]",s);
fun(s);
}
void fun(char *a)
{
if(*a && *a!='\n')
{
fun(a+1);
putchar(*a);
}
}
// use this approach better time complexity and easier work hope this helps

Check if a word is palindrome with string.h

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?

Search most right string in another string - in c [duplicate]

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Is there a reverse fn() for strstr
I wrote this main and function that get two string and check if the second string exist within the first one,
then return the most right index appear place.
If wasn't found return -1.
This is the code I wrote:
#include <stdio.h>
int strindex(char[], char[]);
int main()
{
char a[100];
char b[100];
int search;
printf("Enter two strings, To search the second one in the first one:\n");
printf("Enter the first string to search in:\n");
fgets(a,100,stdin);
printf("Enter the second string to search in the first:\n");
fgets(b,100,stdin);
printf("\n\n THE FIRST STRING IS:%s\n\n THE SEARCH STRING IS:%s",a, b);
printf("\n\n");
search = strindex(a, b);
if(search==-1)
printf("The second String didnt found in the first string\n");
else printf("The second string appear in the first string at most right at index:%d\n",search);
return 0;
}
int strindex(char s[], char t[])
{
int foundIndex = -1;
int tempFound, startNext;
int i,j;
i = j = 0;
while (s[i]!='\0')
{
if(s[i]==t[j])
{
startNext = i+1;
tempFound = i;
while(s[i]!='\0' && t[j]!='\0' && s[i]==t[j])
i++,j++;
if (t[j]=='\0') /**check if it null**/
{
printf("found match");
foundIndex = tempFound;
}
i = startNext;
j = 0;
}
else i++;
}
return foundIndex;
}
I think I have a problem in this line:
if (t[j]=='\0') /**check if it null**/
cause I tried put two string that the second one contain in the first but although t[j] is equal to null it doesn't perform the inside if statement.
I know there are many other ways of writing this program. But I know this one should work too and i am trying to make it work.
You're juggling with indexes, which is quite confusing. Use the indexes for one purpose only and don't set and reset at will. I would suggest to rewrite your function a bit and cleanup the used indexes
int strindex(char s[], char t[])
{
int foundIndex = -1;
int i,j;
for (i = 0; s[i]!='\0'; i++)
{
if(s[i]==t[0])
{
for(j = 1; s[i + j]!='\0' && t[j]!='\0' && s[i + j]==t[j]; j++)
;
if (t[j]=='\0') /**check if it null**/
{
printf("found match");
foundIndex = i;
}
}
}
return foundIndex;
}
You can replace the inner loop with strncmp of course.
And now to your question ;-). Your strindex works as intended. As #wildplasser already noted, fgets stores the final newline \n in the buffer. Since there's no newline in the string to be searched except at the end, you never get a match, if the string to search for is in the middle and not at the end.
When you either strip the newline from a[] and b[], you will see, that strindex works.
Another approach could be to give the strings on the command line instead of reading with fgets.
int main(int argc, char **argv)
{
int search;
printf("\n\n THE FIRST STRING IS:%s\n\n THE SEARCH STRING IS:%s", argv[1], argv[2]);
printf("\n\n");
search = strindex(argv[1], argv[2]);
if(search==-1)
printf("The second String didnt found in the first string\n");
else printf("The second string appear in the first string at most right at index:%d\n",search);
return 0;
}
OK friends. this is the solution that works:-):
thanks to Olaf Dietsche
#include <stdio.h>
int strindex(char[], char[]);
int main()
{
char a[100];
char b[100];
int search;
printf("Enter two strings, To search the second one in the first one:\n");
printf("Enter the first string to search in:\n");
fgets(a,100,stdin);
printf("Enter the second string to search in the first:\n");
fgets(b,100,stdin);
printf("\n\n THE FIRST STRING IS:%s\n\n THE SEARCH STRING IS:%s",a, b);
printf("\n\n");
search = strindex(a, b);
if(search==-1)
printf("The second String didnt found in the first string\n");
else printf("The second string appear in the first string at most right at index:%d\n",search);
return 0;
}
int strindex(char s[], char t[])
{
int foundIndex = -1;
int tempFound, startNext;
int i,j;
i = j = 0;
while (s[i]!='\n')
{
if(s[i]==t[j])
{
startNext = i+1;
tempFound = i;
while(s[i]!='\n' && t[j]!='\n' && s[i]==t[j])
i++,j++;
if (t[j]=='\n')
foundIndex = tempFound;
i = startNext;
j = 0;
}
else i++;
}
return foundIndex;
}

Resources