c - reverse string comparison (palindrome) - c

I want to check an entered text for a palindrome.
However, when I enter a palindrome, I always get that it is NOT a palindrome. Have I done something wrong with the stored linefeed character?
#include<stdio.h>
#include<string.h>
int main()
{
char text[256], reverse[256];
int i, j;
printf("Type a text: ");
fgets(text, 255, stdin);
j = strlen(text)-1;
for (i=0; i<=j; ++i)
{
if(text[i] >= 'A' && text[i] <= 'Z')
{
text[i] += 32;
}
if(text[i] == '\n')
{
text[i] = i - 1;
}
}
i = strlen(text)-1;
for (i = i, j = 0 ;i >= 0 ; --i, ++j)
{
reverse[j] = text[i];
}
printf("Text: %s\n", text);
printf("Reverse: %s\n", reverse);
if (strcmp(text, reverse) == 0)
{
printf("The entered text \"%s\" is a palindrome!\n", text);
}
else
{
printf("The entered text \"%s\" is NOT a palindrome!\n", text);
}
}

Yes, your treatment of the linefeed character is wrong.
You replaced the linefeed character with some other (or maybe same) character, but it means there will be an extra character in the string and the extra character will prevent the string from being jugded as a palindrome.
You should replace the linefeed character to '\0' (NUL character), which is used as string termination mark in C.

This if statement
if(text[i] == '\n')
{
text[i] = i - 1;
}
does not make a sense. Moreover as the new line character '\n' is a single character in an entered string then keeping it within the string will result that the string is not a palindrome.
You need to substitute it for the zero character '\0'.
And the array reverse does not contain a string after this loop
for (i = i, j = 0 ;i >= 0 ; --i, ++j)
{
reverse[j] = text[i];
}
Also using the function strlen is redundant and inefficient.
The program can look the following way.
#include <stdio.h>
#include <ctype.h>
#include <string.h>
int main(void)
{
char text[256], reverse[256];
printf( "Type a text: " );
fgets( text, sizeof( text ), stdin );
size_t n = 0;
while ( text[n] != '\0' )
{
if ( text[n] == '\n' )
{
text[n] = '\0';
}
else
{
text[n] = tolower( ( unsigned char )text[n] );
++n;
}
}
reverse[n] = '\0';
for ( size_t i = 0; n-- != 0; i++ )
{
reverse[n] = text[i];
}
printf( "Text: \"%s\"\n", text );
printf( "Reverse: \"%s\"\n", reverse);
if ( strcmp( text, reverse ) == 0 )
{
printf( "The entered text \"%s\" is a palindrome!\n", text );
}
else
{
printf( "The entered text \"%s\" is NOT a palindrome!\n", text );
}
return 0;
}
The program output might look like
Type a text: ABC cba
Text: "abc cba"
Reverse: "abc cba"
The entered text "abc cba" is a palindrome!
In general the used by you approach when you need an auxiliary array and when the source string is being changed is not good.
Your could write a simple function as it is shown in this demonstrative program.
#include <stdio.h>
#include <ctype.h>
#include <string.h>
int is_palindrome( const char *s )
{
size_t n = strlen( s );
size_t i = 0;
while ( i < n / 2 && tolower( ( unsigned char )s[i] ) ==
tolower( ( unsigned char )s[n -i -1] ) )
{
++i;
}
return i == n / 2;
}
int main(void)
{
char text[256];
printf( "Type a text: " );
fgets( text, sizeof( text ), stdin );
text[ strcspn( text, "\n" ) ] = '\0';
printf( "Text: \"%s\"\n", text );
if ( is_palindrome( text ) )
{
printf( "The entered text \"%s\" is a palindrome!\n", text );
}
else
{
printf( "The entered text \"%s\" is NOT a palindrome!\n", text );
}
return 0;
}
The program output might look like
Type a text: ABC cba
Text: "ABC cba"
The entered text "ABC cba" is a palindrome!
As you see the original string was not changed except the new line character '\n' was substituted for the zero character '\0'.

Related

I need a program in C, which finds all the words that start and end with the same letter

I'm trying to make a program that counts all the words that start and end with the same character. in C
It tells me correctly which is the first and which is the last, I don't know how to make it show me the ones that are equal.
#include <stdio.h>
#include <string.h>
int main()
{
char s[50];
printf("Introdu propozitia : ");
gets(s);
int i, j = 0;
// Traversing the Character array
for (i = 0; i < strlen(s); i++) {
// To store first character of
// String if it is not a
// whitespace.
if (i == 0 && s[i] != ' ') {
printf("%c ", s[i]);
}
if (s[i] == ' ')
printf("%c", s[i -1]);
// To check whether Character
// is first character of
// word and if yes store it.
else if (i > 0 && s[i - 1] == ' ') {
printf(" %c ", s[i]);
}
else if (i>0 && s[i] == ' ')
printf("%c", s[i -1]);
if(s[i]==s[i-1])
Total ++;
printf("\n Sunt : %d", Total);
}
return 0;
}
For starters the function gets is unsafe and is not supported by the C Standard. Instead use either scanf or fgtes.
This if statement
if(s[i]==s[i-1])
Total ++;
does not make sense.
Using the function strlen in the for loop is inefficient and redundant.
To find starts and ends of words in a string you can use standard string functions strspn and strcspn.
Here is a demonstration program.
#include <stdio.h>
#include <string.h>
int main( void )
{
char s[50];
printf( "Introdu propozitia : " );
fgets( s, sizeof( s ), stdin );
size_t count = 0;
const char *delim = " \t\n";
for ( const char *p = s; *p; )
{
p += strspn( p, delim );
size_t n = strcspn( p, delim );
if (n != 0 && p[0] == p[n - 1])
{
++count;
}
p += n;
}
printf( "\nSunt : %zu\n", count );
}
Its output might look like
Introdu propozitia : 123454321 2345432 34543 454 5
Sunt : 5
If you want to output the words that satisfy the condition then add one statement in the if statement of the program
if (n != 0 && p[0] == p[n - 1])
{
++count;
printf( "%.*s\n", ( int )n, p );
}

Keep getting gibberish output when trying to print an array in C

I am trying to write a program that reverses words in a sentence, the code is able to do that but also prints gibberish in between. (see below code for sample)
#include <stdio.h>
#define MAX_VALUE 50
int main(){
char c[MAX_VALUE],
b[MAX_VALUE];
int i = 0, j = 0;
while ((c[i] = getchar()) != '\n'){
i++;
}
for(i = MAX_VALUE; i >= 0; i--){
if (c[i] == ' '){
for(j = i+1; j < MAX_VALUE; j++){
if (c[j] != ' '){
printf("%c", c[j]);
}
else{
break;
}
}
printf(" ");
}
}
while (c[i] != ' '){
printf("%c", c[i]);
i++;
}
}
Loop goes backwards when it detects a space it prints the word until it finds another space then goes backwards again from where it left off last
The input and output expected:
input: test a is this
output: this is a test
What I get:
input: test a is this
output:
this
`����l�,+�D �=� is a test
This for loop
while ((c[i] = getchar()) != '\n'){
i++;
}
can write outside the array c and store the new line character '\n' in the array.
And this output consisting from two lines
this
`����l�,+�D �=� is a test
demonstrates that the new line character was stored in the array.
Also you forgot to append the entered sequence of characters with the zero terminating character '\0' to form a string.
You could write the while loop the following way
int ch;
while ( i < MAX_VALUE - 1 && ( ch = getchar() ) != '\n' && ch != EOF ){
c[i++] = ch;
}
c[i] = '\0';
Or if you want store the entered sequence without the terminating zero character '\0' then the loop can look like
int ch;
while ( i < MAX_VALUE && ( ch = getchar() ) != '\n' && ch != EOF ){
c[i++] = ch;
}
In this case the variable i will contain the number of entered symbols in the array and you should use its value instead of the value MAX_VALUE in the following loops.
This outer for loop
for(i = MAX_VALUE; i >= 0; i--){
is incorrect because the user can enter a sequence of symbols that contains less than MAX_VALUE symbols. You should either use standard string function strlen (if you appended the sequence with the terminating zero character '\0') to determine the length of the string stored in the array or the value of the variable i as mentioned above that denotes the number of entered symbols.
And it is not enough to check this condition
if (c[i] == ' '){
because the leading spaces can be absent in the entered string. So you need to check also whether i is equal to 0. Otherwise the output can be incorrect if the sequence contains for example only one word.
The inner for loop
for(j = i+1; j < MAX_VALUE; j++){
again is incorrect by the same reason of using MAX_VALUE in the condition.
Pay attention to that the array b
char c[MAX_VALUE],
b[MAX_VALUE];
is not used in your program.
Using your approach I can suggest the following solution to output words of a string in the reverse order shown in the demonstrative program below.
#include <stdio.h>
#include <string.h>
#include <ctype.h>
int main( void )
{
const char *s = "test a is this";
for( size_t i = strlen( s ); i != 0; )
{
while ( i != 0 && isblank( ( unsigned char )s[i-1]) )
{
putchar( s[--i] );
}
size_t j = i;
while ( j != 0 && !isblank( ( unsigned char )s[j-1]) )
{
--j;
}
if ( j != i )
{
size_t last = i;
i = j;
while ( j != last )
{
putchar( s[j++] );
}
}
}
putchar( '\n' );
}
The program output is
this is a test
The code uses two arrays and two 'counters', and fiddles around with individual characters one-at-a-time. It's easy to get lost and use an upper bound that is outside the array size.
Simplify! This "reversal" is an excellent example of when recursion should be the go-to method of solving the problem.
#include <stdio.h>
#include <string.h>
void output( char *p ) {
if( (p = strtok( p, " " )) == NULL ) return;
output( NULL );
printf( "%s ", p );
}
int main() {
char str[] = "The quick brown fox jumps over the dogs";
output( str );
return 0;
}
dogs the over jumps fox brown quick The
Some purists may want an entire buffer to be assembled before printing. This resulting string includes an invisible SP at the end that could be lopped off if desired.
#include <stdio.h>
#include <string.h>
char *revWords( char *dst, char *p ) {
if( (p = strtok( p, " " )) == NULL ) return NULL;
revWords( dst, NULL );
return strcat( strcat( dst, p ), " " );
}
int main() {
char str[] = "The quick brown fox jumps over the dogs";
char buf[sizeof str + 1 + 1] = { 0 }; // important to initialise
puts( revWords( buf, str ) );
return 0;
}
For an alternative, here's a version without recursion. It requires, like above, a mutable buffer holding the string.
#include <stdio.h>
#include <ctype.h>
int main() {
char str[] = " The quick brown fox jumps over the dogs ";
int i = 0;
// note: 1 string buffer, 1 index variable
for( i = 0; str[i]; i++ ) ; // loop
while( i >= 0 ) {
while( i >= 0 && !isalnum( str[ i ] ) ) str[i--] = '\0';
while( i >= 0 && isalnum( str[ i ] ) ) i--;
printf( "%s ", str + i + 1 );
}
puts( "" );
return 0;
}

Counting number of words which starts with a given letter

I am a beginner and am making a program for counting how many words start with a given letter, I wrote a program that counts how many words starts with the letter A but can't make it to find using given letter - I tried making another variable ch and asking it from the user and verifying if *p == "ch" but it does not work
#include <stdio.h>
#include <string.h>
int main(void)
{
enum { N = 200 };
char sentence[N];
printf( "Enter sentence: " );
fgets( sentence, N, stdin );
size_t n = 0;
for ( const char *p = sentence; *p; p += strcspn( p, " \t" ) )
{
p += strspn( p, " \t" );
if ( *p == 'A' ) ++n;
}
printf("No. of A in string \"%s\" is %zu\n", sentence, n );
return 0;
}
The code that I tried:
#include <stdio.h>
#include <string.h>
int main(void)
{
enum { N = 200 };
char sentence[N];
char ch;
printf("Enter one char");
scanf("%c", &ch);
printf( "Enter sentence: " );
fgets( sentence, N, stdin );
size_t n = 0;
for ( const char *p = sentence; *p; p += strcspn( p, " \t" ) )
{
p += strspn( p, " \t" );
if ( *p == ch ) ++n;
}
printf("No. of A in string \"%s\" is %zu\n", sentence, n );
return 0;
}
The problem is a classic one: scanf("%c", &ch); reads a single byte and leaves the newline in the stdin buffer, hence fgets( sentence, N, stdin ); reads the rest of the input line without waiting for further user input.
You should read the rest of the input line after the scanf() with:
int c;
while ((c = getchar()) != EOF && c != '\n')
continue;
You're making it much too complicated. I suggest something like this:
#include <stdio.h>
#include <string.h>
int isBlankSpace (char ch) {
return (ch == ' ' || ch == '\t' || ch == '\n');
}
int main(void) {
char sent[200], ch;
printf("Enter a char: ");
ch = getchar();
getchar(); //gets newline character
printf("Enter a sentence: " );
fgets(sent,200,stdin);
int count = 0, i=0;
while (i < strlen(sent)) {
while (isBlankSpace(sent[i])) i++; //successive blank spaces
if ((i==0 || isBlankSpace(sent[i-1])) && sent[i] == ch) count++;
i++;
}
printf("No. of words starting with %c's in the "\
"string \"%s\" is %d\n", ch, sent, count);
return 0;
}

Unable to execute a code that finds first character of a string that matches with a given character

This code is written to identify the position of character in the string from back which matches first with a given character.When i use scanf to get string,the compiler doesn't ask for the character and directly gives the output as 0.I am unable to rectify the problem with scanf.
I ran the function by giving string input directly without scanf and it works fine.
#include<stdio.h>
#include<string.h>
int strrindex(char str[], char t)
{
int n=strlen(str);
while(n>=0)
{
if(str[n]==t)
{
return n;
}
else
{
n=n-1;
}
}
return -1;
}
int main()
{
int k;
char str[100];
printf("enter line\n");
scanf("%s",str);
char t;
printf("enter letter\n");
scanf(" %c",&t);
k=strrindex(str,t);
int p=k+1;
printf("the position is %d",p);
}
The code runs but the output is always 0 mostly because of \n added because of scanf.
You included the return statement
return -1;
in the while loop
while(n>=0)
{
if(str[n]==t)
{
return n;
}
else
{
n=n-1;
}
return -1;
}
Place it outside the loop.
Pay attention to that the function should be declared like
size_t strrindex( const char str[], char t );
and return ( size_t )-1 in the case when the character is not found because the return type of the standard C function strlen is size_t.
Bear in mind that there is a similar standard C function
char *strrchr(const char *s, int c);
Here is a demonstrative program
#include <stdio.h>
#include <string.h>
size_t strrindex( const char *s, char c )
{
size_t n = strlen( s );
while ( s[n] != c && n != 0 ) --n;
return n == 9 ? -1 : n;
}
int main(void)
{
const char *s = "Hello";
size_t n = strlen( s );
do
{
size_t pos = strrindex( s, s[n] );
if ( pos == -1 )
{
printf( "The character %c is not found\n", s[n] );
}
else
{
printf( "The character %c is found at position %zu\n", s[n] == '\0' ? '0' : s[n], pos );
}
} while ( n-- );
return 0;
}
Its output is
The character 0 is found at position 5
The character o is found at position 4
The character l is found at position 3
The character l is found at position 3
The character e is found at position 1
The character H is found at position 0
If you want to exclude the terminating zero from searching then the function can look the following way
#include <stdio.h>
#include <string.h>
size_t strrindex( const char *s, char c )
{
size_t n = strlen( s );
while ( n != 0 && s[n - 1] != c ) --n;
return n == 0 ? -1 : n - 1;
}
int main(void)
{
const char *s = "Hello";
size_t n = strlen( s );
do
{
size_t pos = strrindex( s, s[n] );
if ( pos == -1 )
{
printf( "The character %c is not found\n", s[n] == '\0' ? '0' : s[n] );
}
else
{
printf( "The character %c is found at position %zu\n", s[n] == '\0' ? '0' : s[n], pos );
}
} while ( n-- );
return 0;
}
In this case the program output is
The character 0 is not found
The character o is found at position 4
The character l is found at position 3
The character l is found at position 3
The character e is found at position 1
The character H is found at position 0
Also pay attention to that the function scanf reads a string until a white-space character is encountered.
So instead of scanf use fgets. For example
fgets( str, sizeof( str ), stdin );
str[strcspn( str, "\n" )] = '\0';

I am trying to develop a program that arranges my message(String) in a x*width matrix

For example(if width=5)
This a a C program.
This and " " should be in the 1st line and rest will go to the next line and so on.
#include<stdio.h>
int main(void)
{
int width;
int i;
char message[256];
scanf("%d",&width);
scanf(" %s",&message);
for( i = 1; i <= width; i++ )
{
if( i == width )
{
printf( "\n" );
}
else
{
printf( "%s", message );
i == width;
}
}
printf( "\n" );
return 0;
}
Using scanf for input of a string containing spaces is arcane and over-complex since it normaly uses whitespace as a string delimiter - you will only get the first word of the "message".
You need to iterate the length of the string rather than the width of the "matrix" - otherwise it will just stop after one line. You simply insert a newline every width characters.
The body of your loop makes little sense either since you just print message (several times) regardless of its length.
#include <stdio.h>
int main(void)
{
int width = 0 ;
int i = 0 ;
char message[256] = "" ;
scanf( "%d", &width );
fgets( message, sizeof(message), stdin ) ;
while( message[i] != '\0' )
{
putchar( message[i] ) ;
i++ ;
if( i % width == 0 )
{
putchar( '\n' ) ;
}
}
putchar( '\n' ) ;
}
In most circumstances some validity checking of the user input would be in order.

Resources