strcmp returning only 0 (palindrom algo bug) - c

Hi I learned in class about the string.h library and specifically about the strcmp function that compares between to strings .
and if the first string appears first in the dictionary it will return a number bigger than 0 , if the second string is bigger than first than it will return a number smaller than 0 , and if they are equil its supposed to return a 0.
ive used it like this :
strcmp(strArr , strrev(strArr));
Feel free to educate me.
The code :
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MAX_LENGTH 100
#define PALINDROM_TRUE 0//because in strcmp if both strings compared are equile the strcmp will return 0.
int main(void)
{
char strArr[MAX_LENGTH];
printf("Enter string (max length 100 chars): ");
fgets(strArr , MAX_LENGTH , stdin);
int pali = strcmp(strArr , strrev(strArr));
if(pali == PALINDROM_TRUE)
{
printf("Palindrom\n");
}
else
{
printf("Not Palindrom\n");
}
system("PAUSE");
return 0;
}
my problem is that the code below when I enter i.e "abc" it prints to the screen Palindrom which it should print Not Palindrom , it never prints Not Palindrom

The reason for this is your call to strrev(). strrev() function works in-place. In other words, strrev works on the same buffer(i.e. strArr array) as the original array, and does not allocate a new space for the reversed string. As a result, once you call strrev() with strArr, the string in strArr is reversed, and all you are doing is comparing the two identical strings: the one in strArr, and again, the one in strArr, both of which are now reversed. (Note that the term both may be misguiding. Actually, there is just a single buffer and both arguments to strcmp point to that one.)
One way to correct this issue is to allocate a second array strArr2 and copy the string into it. Then, reverse the string in strArr2, and call strcmp with strArr and strArr2. Below is how this solution would look like in code.
...
char strArr2[MAX_LENGTH];
...
strcpy(strArr2, strArr);
strrev(strArr2);
int pali = strcmp(strArr , strArr2);
if(pali == PALINDROM_TRUE)
{
printf("Palindrom\n");
}
else
{
printf("Not Palindrom\n");
}
...
Note that you may also have to check the end of strArr for any trailing whitespace characters, due to your specific method of taking input. Any such trailing whitespace character could render your reversing and comparing strategy useless by affecting the result of the comparison.
If you do not have that much space, or if MAX_SPACE is too large a value, another way would be to use a custom comparison function for checking if a string is palindrome without having to use strcmp or strrev.

int pali = strcmp(strArr , strrev(strArr));
This line is obviously the issue.
The call to strrev(strArr) reverses strArr so afterwards when strcmp is called, do you expect strArr to be different? But it's the same variable...
You must create another char array to store the reversed string.
EDIT:
#include <stdio.h>
#include <string.h>
#define MAX_LENGTH 100
int main(void)
{
char str[MAX_LENGTH];
char rev[MAX_LENGTH];
puts("Enter string (max length 100 chars): ");
scanf("%s", str);
strcpy(rev, str);
strrev(rev);
if(strcmp(str, rev) == 0) {
puts("Palindrom");
} else {
puts("Not Palindrom");
}
}

ive added
strArr[strcspn(strArr, "\n")] = 0;
after
fgets(strArr , MAX_LENGTH , stdin);
And it worked , its basicly rewriting the (null) at the end. which was messing up the reverse to include null (0) at the start of the string.
Thanks everyone.
Finsihed Code:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MAX_LENGTH 100
#define PALINDROM_TRUE 0//because in strcmp if both strings compared are equile the strcmp will return 0.
int main(void)
{
char strArr[MAX_LENGTH], strArrRev[MAX_LENGTH];
printf("Enter string (max length 100 chars): ");
fgets(strArr , MAX_LENGTH , stdin);
strArr[strcspn(strArr, "\n")] = 0;
strcpy(strArrRev, strArr);
int pali = strcmp(strArr , strrev(strArrRev));
if(pali == PALINDROM_TRUE)
{
printf("Palindrom\n");
}
else
{
printf("Not Palindrom\n");
}
system("PAUSE");
return 0;
}

Related

Dynamic memory allocation of string and placement of this string in a char array

I want to have an array of strings and the user to enter a string at a time. The program should either end if the the array is full or when the user skips an input (so the string would be equal to "\n".
Problem is that I have to dynamically allocate memory for each of these strings and I cant find a way to do that efficiently.
Excuse my English on this one but the array should be an array of pointers to char (for example char *pin[MAX])
This is my code:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MAX 5
int main()
{
char *pin[MAX];
char s[] = "";
int n = 0;
while(s != "\n"){
printf("Enter a string: ");
gets(s);
pin[n] = malloc(sizeof(char)*strlen(s));
strcpy(pin[n], s);
n++;
if(n = MAX - 1) break;
}
for(int i = 0; i < MAX; i++){
printf("%s ", *pin[i]);
}
return 0;
}
Take input with fgets and store it in a temporary buffer (128 or 256 bytes large etc).
Call strlen on the read string stored in this buffer to see how much to allocate.
Allocate memory with malloc for pointer pin[n] and strcpy the string there.
NOTE:
char *s; ... while(s != is nonsense since s has not been initialized.
s != "\n" is nonsense since that's not how you compare strings in C.
pin[n] == &s; is nonsense because it's just random stuff typed out without the programmer knowing why. Programming by trial & error doesn't work.
In general you need to study arrays and pointers before strings.

printing strings in array of strings in reverse order

So i did this program and the purpose is to store a string from the stdin and store in a array of strings. After that, i want to print all the strings stored in the array but in reverse order.
Example:
Input:
abc def hij klm nop
Output:
nop
klm
hij
def
abc
Program:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MAXLEN 1001
int main(){
char buffer[MAXLEN];
char** strings;
int i = 0;
int j = MAXLEN;
strings = (char**)malloc(sizeof(char*)*MAXLEN);
while(scanf("%s",buffer) == 3)
{
strings[i]=(char*)malloc(sizeof(char)*(strlen(buffer)+1));
strcpy(strings[i],buffer);
i++;
}
printf("%s",strings[0]);
}
Well, i just put the 1st string only to check if it was printing any strings the problem is that if type that in the example it prints (null) instead of the word and what im wondering is why is it pointing to NULL instead of pointing to the string i gave.
Really any help would be appreciated.
The test for successful conversion from stdin is incorrect: scanf() returns the number of conversions, not the number of characters. You should compare the return value to 1. As coded, the loop test fails immediately so strings[0] is not modified, the code has undefined behavior because the array allocated by malloc is uninitialized. This array happens to contain a null pointer at the beginning (because its first bytes are zero by coincidence), and printf prints (null) for null pointers, which is not guaranteed by the C Standard, but a useful indication sometimes.
Furthermore, you should tell scanf() about the maximum length of a word to store into the destination array: scanf("%1000s", buf).
You should also limit the number of words you tore into the array of pointer and test for memory allocation error.
Finally, you need a loop to output the strings in reverse order of input.
Here is a modified version:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MAXLEN 1001
int main() {
char buffer[MAXLEN];
int i, j;
char **strings = malloc(sizeof(char *) * MAXLEN);
if (strings == NULL)
return 1;
for (i = 0; i < MAXLEN && scanf("%1000s", buffer) == 1; i++) {
strings[i] = strdup(buffer);
if (strings[i] == NULL)
return 1;
}
for (j = i; j-- > 0;) {
printf("%s\n", strings[j]);
free(strings[j]);
}
free(strings);
return 0;
}

Resize specific cells of array in c

#include <stdio.h>
#include <stdlib.h>
#include <stdio.h>
char *readline()
{
char s[256],*ds;
printf("Give string: ");
gets(s);
ds = (char *) calloc(strlen(s)+1,sizeof(char));
strcpy(ds,s);
return ds;
}
main()
{
char *s1,*s2;
int a,b;
s1=readline();
printf("Start:");
scanf("%d",&a);
printf("End:");
s2=(char*)realloc(s1,b-a);
puts(s2);
return 0;
}
I have this code and I want to resize specific cells of the s1 array which are determined from the variables a and b.
E.g. If I give the string "Hello" and the integers a=2 and b=4 then I want the program to print "ell".
Don't use gets use fgets instead.
With fgets you would use if( fgets( s,256, stdin)!= NULL ){ /*Got input in s*/ }.
You have taken \n as input also. s[strcspn(s,"\n")]=0 will overwrite \n with \0.
Casting return value of calloc is not needed since, void* will be implicitly converted to char*. calloc may return NULL - you didn't include check in there.
ds = calloc(strlen(s)+1,sizeof(char));
if( NULL == ds ){
perror("calloc: error");
exit(EXIT_FAILURE);
}
In main() value of b is indeterminate. You didn't take input in b.
if( scanf("%d",&b)!= 1){
fprintf(stderr,"Error in input");
exit(EXIT_FAILURE);
}
Then you realloc-ed. But not clear why. If you thought that shrinking the memory to 4-2 or 2 Bytes will help you get "ell" then you are wrong in many ways. It won't.
what you can do is - allocate memory for that in s2.
if(b<a){
fprintf(stderr,"End must be greater than beginnning\n");
exit(EXIT_FAILURE);
}
s2 = malloc(b-a+1);
if(!s2){
perror("calloc: error");
exit(EXIT_FAILURE);
}
memcpy(s2,s1+a,b-a);
s2[b-a]=0;
puts(s2);
This will print the relevant "ell" just you wanted. There is one thing left for you - put the code snippets in the code.
Since you are open to other solutions:
If there is another way then no problem.
I would point you to a simple solution, where you terminate the original string at b and skip required number of characters a. (Note: in C char array starts from index 0);
This is the idea:
#include <stdio.h>
#include <string.h>
char *splice(char *str, int s, int e)
{
str[e]=0;
return (str+s-1);
}
int main()
{
char *after;
int a=2;
int b=4;
char original[] = { 'H', 'e', 'l' , 'l' , 'o', 0 };
after = splice(original,a,b);
printf("My new string = %s", after);
return 0;
}
Output:
My new string = ell

reversing a string in c without library function

In this program I am trying to take a string as input from the user guessing that the maximum length of the string here is 40 (obviously can exceed).
I'm finding out the length and using the length to create another character array dynamically( only to prevent assigning this array with any random value) and finally, adding the characters from the last to get the reversed string.
It compiles just fine, but upon running, provides no output.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main()
{
char word[40];
char *rev;
int i=0;
int l=0;
printf("Enter any statement \n");
scanf("%[^\n]", word);
while(word[i]!='\0')
{
i++;
}
// i contains the length of the string
rev=(char *)malloc(i*sizeof(char));
while(i>0)
{
rev[l]=word[i];
i--;
l++;
}
printf("\n %s", rev);
return 0;
}
You have two (at least) problems: The first one is that you swap characters twice. The second problem is that you also include the terminator character in your swapping.
I believe you have a 'one-off' type error and are not seeing any output because the teminating \0 character is being copied to the first position of rev.
rev[l]=word[i]; should rev[l]=word[i-1];
Point 1:-
In C a string is always ended with '\0'(NULL Termination),you should always manually insert a '\0' at the end,which i think you forgot.But no worries even i did not remember it as well when i started...:) ,Experiences like these will make you from next time.
Point 2:-
Assume you have a string char str[]="ABCD" ;,In memory this would look like this
------------IN Memory----------------
| 'A' || 'B' || 'C' | | 'D' | | '\0' |
-------------------------------------
0 1 2 3 4
Just by looking we can say that its length would be 4 (we know that we don't include '\0' when calculating length). For copying in reverse we need to start with character 'D' whose index is 3,that means you have to start copying from 2nd last character whose index can be can be found from length of string -1.The mistake you did in your above program is you have used length of string (which is 4), to start copying.which copies '\0' as first character in rev[] ,Hence it provides no output.
Other points:-
Based on the above two points i have corrected the mistakes, see comments in the below program to understand it well.And i have used int j;instead of int l; because i felt so confusing.
and please use width specifier when reading strings using scanf(); In your while loop,you should change the condition from i>0 to i>=0 because when i reaches 0,i>0 condition will break the loop before copying the first character from word[] to rev[].
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main()
{
char word[40];
char *rev;
int i=0;
int j=0;
printf("Enter any statement \n");
scanf("%39[^\n]", word);//using width specifier,(POINT 1)here 39 because sizeof(word)-1, one left to accommodate '\0' at end.
while(word[i]!='\0')//calculating length of string
{
i++;
}
rev=(char *)malloc(i*sizeof(char)+1);// (POINT 1),here making +1 to accommodate '\0' at end.
i=i-1;//(POINT 2)- Last index of the array is always length of string - 1
while(i>=0)//This should be i>=0 because you also want to copy first character of input string.
{
rev[j]=word[i];
i--;
j++;
}
rev[j]='\0';//(POINT 1) You should end with '\0'.
printf("\n %s", rev);
return 0;
}
Your scanf format string looks weird. Perhaps you are using some strange feature of it that I'm unaware of, so I'll pass on that. But you need to make sure that word is a null terminated string after the user input is done.
while(word[i]!='\0')
This loops counts until it finds the null term. So i will contain the string length: you just invented the strlen() function. It will not contain the string length plus the null terminator length (1).
Therefore
rev=(char *)malloc(i*sizeof(char));
is incorrect, you need to allocate i+1 bytes.
Also, you shouldn't cast the result of malloc, because doing so is completely pointless.
And when you copy, you have to ensure that you also copy the null terminator.
Below code with just one modification should return just correct answer. I changed in 2nd while loop from:
rev[l]=word[i];
to
rev[l]=word[i-1];
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main()
{
char word[40];
char *rev;
int i=0;
int l=0;
printf("Enter any statement \n");
scanf("%[^\n]", word);
while(word[i]!='\0')
{
i++;
}
// i contains the length of the string
rev=(char *)malloc(i*sizeof(char));
while(i>0)
{
rev[l]=word[i-1];
i--;
l++;
}
printf("\n %s", rev);
return 0;
}
The code has several memory mistakes and using static memory is also an issue. But for if you are using for practice purpose below are the changes and its explanation.
i--; // you can't place a '\0' to your rev[0] else it would always be NULL string when you print
while(i>=0)
{
rev[l]=word[i];
i--;
l++;
}
rev[l]='\0'; // string should be terminated by '\0'
printf("\n%s\n", rev);
//Reverse of a string without using string functions
#include<stdio.h>
#include<conio.h>
void main()
{
char a[40];
int j=0,len=0;
clrscr();
printf("please enter your name\n");
gets(a); // takes white spaces as characters
printf("the reverse of your name is\n");
while (a[j]!=NULL) // finding the length of the string array
{
len++;
j++;
}
for(int k=len;k>=0;k--)
{
printf("%c",a[k]);
}
getch();
}
Output - please enter your name
dwayne rock johnson
the reverse of your name is
nosnhoj kcor enyawd
As noted, array indices begin at zero and end at length-1. Moreover, if you like, you could rewrite your code in a more cryptic fashion:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main()
{
char word[40];
char *rev;
int i=0;
int l=0;
printf("Enter any statement \n");
scanf("%[^\n]", word);
while(word[++i]);
// i contains the length of the string
rev=(char *)malloc(i*sizeof(char));
while(rev[l++]=word[i---1], i>0);
printf("%s\n", rev);
return 0;
}

Strings in C Language

How can you code this in C language if the output is like this? I need strings format of the code because our topic is strings.
#include <stdio.h>
#include <stdlib.h>
void main()
{
char my_string[50];
printf("Enter a word:");
scanf("%s", my_string);
printf("Enter a word:");
scanf("%s", my_string);
// Some unknown code here...
// this part is my only problem to solve this.
getch();
}
Output:
Hello -> (user input)
World -> (user input)
HWeolrllod -> (result)
Okay, you need to do some investigating. We don't, as a general rule, do people's homework for them since:
it's cheating.
you'll probably get caught out if you copy verbatim.
it won't help you in the long run at all.
The C library call for user input that you should use is fgets, along the line of:
char buffer[100];
fgets (buffer, sizeof(buffer), stdin);
This will input a string into the character array called buffer.
If you do that with two different buffers, you'll have the strings in memory.
Then you need to create pointers to them and walk through the two strings outputting alternating characters. Pointers are not an easy subject but the following pseudo-code may help:
set p1 to address of first character in string s1
set p1 to address of first character in string s1
while contents of p1 are not end of string marker:
output contents of p1
add 1 to p1 (move to next character)
if contents of p2 are not end of string marker:
output contents of p2
add 1 to p2 (move to next character)
while contents of p2 are not end of string marker:
output contents of p2
add 1 to p2 (move to next character)
Translating that into C will take some work but the algorithm is solid. You just need to be aware that a character pointer can be defined with char *p1;, getting the contents of it is done with *p1 and advancing it is p = p + 1; or p1++;.
Short of writing the code for you (which I'm not going to do), there's probably not much else you need.
void main()
{
char my_string1[50],my_string2[50]; int ptr;
ptr=0;
printf("Enter a word : ");
scanf("%s",my_string1);
printf("enter a word");
scanf("%s",my_string2);
while(my_string1[ptr]!='\0' && my_string2[ptr]!='\0')
{
printf("%c%c",my_string1[ptr],my_string2[ptr]);
ptr++;
}
if(my_string1[ptr]!='\0')
{
while(my_string1[ptr]!='\0')
{ printf("%c",my_string1[ptr]);
ptr++;
}
}
else
{
while(my_string2[ptr]!='\0')
{printf("%c",my_string2[ptr]);
ptr++;
}
}
}
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
void main()
{
char my_string1[50],my_string2[50];
int i,l1=1,l2=0;
printf("Enter a word:");
scanf("%s", my_string1);
printf("Enter a word:");
scanf("%s", my_string2);
l1=strlen(my_string1); /* Length of 1st string */
l2=strlen(my_string2); /* Length of 2nd string */
if(l1==l2)
{
for(i=0;i<l1;i++)
{
printf("%c%c",my_string1[i],my_string2[i]);
}
}
else
{
printf("Length of the entered strings do not match");
}
}
This is your required code.
You can see that output needs to be a String containing all chars of User String1 and User String2 one by one...
You can do this like...
//add #include<String.h>
int l1=strlen(s1);
int l2=strlen(s2);
if(l1!=l2)
{
printf("length do not match");
return 0;
}
char ansstr[l1+l2];
int i,j=0,k=0;
for(i=0;i<l1+l2;i=i+2)
{
ansstr[i]=s1[j];
ansstr[i+1]=s2[k];
j++;
k++;``
}
//ansstr is your answer
Ok, here's your code. Come on guys, if he asked here it means he can't solve this.
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
int main(int argc, char *argv[])
{
char str1[] = "abcdefghijklmopq";
char str2[] = "jklm";
int len1 = strlen(str1);
int len2 = strlen(str2);
int c1 = 0, c2 = 0;
int max = (len1 > len2) ? len1 : len2 ;
char *result = malloc(len1 + len2);
for(c1 = 0; c1 <= max; c1++) {
if(c1 < len1)
result[c2++] = str1[c1];
if(c1 < len2)
result[c2++] = str2[c1];
}
result[c2] = 0;
printf("\n%s\n", result);
return 0;
}
Basically the loop picks up a character from str1 and appends it to result. Then it picks a character, which stands in the same position as the first from str2 and appends it to result, just as before. I increment c2 by 2 every time because I'm adding 2 chars to result. I check if c1 is bigger that the length of the strings because I want to copy only the characters in the string without the terminating \0. If you know that your strings have the same length you can omit these ifs.

Resources