I got the output as unequal can you please explain me why
#include <stdio.h>
int main()
{
char str1[] = "hello";
char str2[] = "hello";
if (str1 == str2)
printf("equal");
else
printf("unequal");
return 0;
}
That's because == is comparing the addresses of str1 and str2 and not the
contents of the string. You have to use strcmp for this:
#include <stdio.h>
#include <string.h>
int main()
{
char str1[]="hello";
char str2[]="hello";
if(strcmp(str1, str2) == 0)
puts("equal");
else
puts("unequal");
return 0;
}
would be the correct version. See https://ideone.com/wJpL2I
Note that in C a string is just a sequence of characters that end with the
'\0'-terminating byte. str1 and str2 are both arrays, but when you do
str1 == str2 they decay into pointers and what you are comparing is the memory
location of where the arrays are stored in memory. They are two different arrays
(although they have the same content), so they memory address will be of course different, that's why you get unequal. That's why you need the
strcmp function in order to compare the contents of the char arrays.
You are comparing the data container’s address which are str1 and str2, if you know java then there is that equals method and contentEquals method, if you use equals method it compares the object references, but if you do contentEquals it compares the content(data) resides in the objects.
In c as you should have already known that that the name of the string has the base address in it. That’s the reason you don’t need to put &(address of operator) while using the scanf this is the soul reason when you do the str1==str2 it compares the address not the data inside the string.
In c str1 and str2 are simply 2 character array which has the \0 at the end. Now when you do
if(str1==str2) //it compares the address of
//variables not the content as
//you are comparing the base address
//of the strings str1 and str2.
The right version should be:
#include <stdio.h>
#include <string.h>
int main()
{
char str1[]="hello";
char str2[]="hello";
if(strcmp(str1, str2) == 0)
puts("equal");
else
puts("unequal");
return 0;
}
If you want to verify that you can use this, printf(“%d”, &str1); printf(“%d”, &str2); they both will not be equal.
When you want to compare two strings, you actually want to see if each character in one string is in the corresponding position of the other string.
The strings variables used here (str1 and str 2) are just pointers to the base addresses of those strings.
Hence, str1 == str2 means you are just comparing if both strings have the same base addresses, which, of course, is incorrect.
Here, you can make use of the string.h file which has the strcmp() or string compare function.
It works like this:
It iterates through the string, and checks the difference in the ascii values of individual characters in corresponding positions(same index value). If all characters are the same, it will return 0.
Otherwise, a positive or negative value is encountered based on the order of passing the strings to strcmp.
But in this case, it is of little importance if you get a positive or a negative value.
usage:
if (!strcmp(str1, str2))
puts("equal");
else
puts("unequal");
Related
I was solving a challenge on CodeSignal in C. Even though the correct libraries where included, I couldn't use the strrev function in the IDE, so I looked up a similar solution and modified it to work. This is good. However, I don't understand the distinction between a literal string and an array. Reading all this online has left me a bit confused. If C stores all strings as an array with each character terminated by \0 (null terminated), how can there be any such thing as a literal string? Also if it is the case that strings are stored as an array, *would inputString store the address of the array or is it an array itself of all the individual characters stored.
Thanks in advance for any clarification provided!
Here is the original challenge, C:
Given the string, check if it is a palindrome.
bool solution(char * inputString) {
// The input will be character array type, storing a single character each terminated by \0 at each index
// * inputString is a pointer that stores the memory address of inputString. The memory address points to the user inputted string
// bonus: inputString is an array object starting at index 0
// The solution function is set up as a Boolean type ("1" is TRUE and the default "0" is FALSE)
int begin;
// The first element of the inputString array is at position 0, so is the 'counter'
int end = strlen(inputString) - 1;
// The last element is the length of the string minus 1 since the counter starts at 0 (not 1) by convention
while (end > begin) {
if (inputString[begin++] != inputString[end--]) {
return 0;
}
} return 1;
}
A string is also an array of symbols. I think that what you don't understand is the difference between a char pointer and a string. Let me explain in an example:
Imagine I have the following:
char str[20]="helloword";
str is the address of the first symbol of the array. In this case str is the address of h. Now try to printf the following:
printf("%c",str[0]);
You can see that it has printed the element of the addres that is 'h'.
If now I declare a char pointer, it will be poining to whatever char adress I want:
char *c_pointer = str+1;
Now print the element of c_pointer:
printf("%c",c_pointer[0]);
You can see that it will print 'e' as it is the element of the second adress of the original string str.
In addition, what printf("%s", string) does is to printf every elemet/symbol/char from the starting adress(string) to the end adress where its element is '\0'.
The linked question/answers in the comments pretty much cover this, but saying the same thing a slightly different way helps sometimes.
A string literal is a quoted string assigned to a char pointer. It is considered read only. That is, any attempts to modify it result in undefined behavior. I believe that most implementations put string literals in read-only memory. IMO, it's a shortcoming of C (fixed in C++) that a const char* type isn't required for assigning a string literal. Consider:
int main(void)
{
char* str = "hello";
}
str is a string literal. If you try to modify this like:
#include <string.h>
...
str[2] = 'f'; // BAD, undefined behavior
strcpy(str, "foo"); // BAD, undefined behavior
you're broken the rules. String literals are read only. In fact, you should get in the habit of assigning them to const char* types so the compiler can warn you if you try to do something stupid:
const char* str = "hello"; // now you should get some compiler help if you
// ever try to write to str
In memory, the string "hello" resides somewhere in memory, and str points to it:
str
|
|
+-------------------> "hello"
If you assign a string to an array, things are different:
int main(void)
{
char str2[] = "hello";
}
str2 is not read only, you are free to modify it as you want. Just take care not to exceed the buffer size:
#include <string.h>
...
str2[2] = 'f'; // this is OK
strcpy(str2, "foo"); // this is OK
strcpy(str2, "longer than hello"); // this is _not_ OK, we've overflowed the buffer
In memory, str2 is an array
str2 = { 'h', 'e', 'l', 'l', '0', '\0' }
and is present right there in automatic storage. It doesn't point to some string elsewhere in memory.
In most cases, str2 can be used as a char* because in C, in most contexts, an array will decay to a pointer to it's first element. So, you can pass str2 to a function with a char* argument. One instance where this is not true is with sizeof:
sizeof(str) // this is the size of pointer (either 4 or 8 depending on your
// architecture). If _does not matter_ how long the string that
// str points to is
sizeof(str2) // this is 6, string length plus the NUL terminator.
Problem Statement
Today is Newton School's first class of this year. Nutan, a student at
Newton School, has received his first assignment. He will be given a
string as input. His task is to print "Gravity'' if the input is
"Apple''; otherwise, he will have to print "Space''.
Can you help Nutan in solving his first assignment? Note that the
quotation marks are just for clarity. They are not part of the input
string, and should not be a part of your output string. Input The
input consists of a single line that contains a string S (1 ≤ length
of S ≤ 10). The string only consists of lowercase and uppercase
letters. Output Print "Gravity'' or "Space'' according to the input.
What I am trying to do:
Basically, I am taking a user-defined string and trying to compare it with the hard input string i.e "Apple". If both the string matches then it will print "Gravity" or else it will print "Space"
#include <stdio.h> // header file for Standard Input Output
#include <stdlib.h> // header file for Standard Library
#include <string.h> // for strcmp() function
int main() {
char str1[10]="Apple";
char str2[20];
int value;
printf("Enter the input ");
scanf("%s", &str2[20]);
value = strcmp(str1, str2);
if(value==0)
printf("Gravity");
else
printf("Space");
return 0;
}
scanf("%s", &str2[20]);
may invoke undefined behavior by out-of-range access. You should:
Pass the pointer to the first element of the array, not one to the next element of the last element. (most) arrays in expressions are automatically converted to pointes to their first elements.
Specify the maximum length to read to avoid buffer overrun.
Check if reading succeeded.
The line should be:
if (scanf("%19s", str2) != 1) {
puts("read error");
return 1;
}
Some improvements:
Don't use "%s", use "%<WIDTH>s", to avoid buffer-overflow
Instead of using bare return 0;, use return EXIT_SUCCESS;, which is defined in the header file stdlib.h.
always check whether scanf() input was successful or not
Use const char * instead of char str1[10]
There's no need for int value;
SYNTAX ERROR: &str2[20]
There's no need for passing the address of str2 READ MORE
Initialize str2 with zeroes
Add 1 more space in your str2 for NULL ('\0') terminating character
Final Code:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(void) {
const char *str1 = "Apple";
char str2[21] = {};
printf("Enter the input ");
if(scanf("%20s", str2) != 1)
{
fprintf(stderr, "bad input\n");
return EXIT_FAILURE;
}
if(strcmp(str1, str2) == 0)
printf("Gravity");
else
printf("Space");
return EXIT_SUCCESS;
}
You are entering a string starting from the memory address after the last element of the array str2
scanf("%s", &str2[20]);
and then trying to compare the character array str1 with the non-initialized array str2
value = strcmp(str1, str2);
Change the call of scanf like
scanf("%19s", str2);
And the program will be safer if at least the array str2 will be initially initialized
char str2[20] = "";
Also as the array str1 is not changed then instead of the array you could declare a pointer to the string literal like
const char *str1 = "Apple";
And instead of the calls of printf
printf("Gravity");
//..
printf("Space");
it is better to use calls of puts
puts("Gravity");
//..
puts("Space");
Pay attention to that neither declaration from the header <stdlib.h> is used in your program. So you may remove this include directive
#include <stdlib.h> // header file for Standard Library
why == operator compares ints but not strings. I know we are passing references(addresses) in case of strings but I think it is the same in case of int as well. Or does it work any different way? I am confused.
Strings are an array of characters.
An array always points to the first element like this:
char myString[] = "Hello";
printf("address of first element: %p\n", (void*)myString);
You can compare strings with str1==str2 but what you are really doing is asking: does str1 point to the same memory location as str2?
In some cases this can work because constant strings for example are generally stored in read-only memory and reused:
const char *myString = "hello";
// may work, but don't rely on it!
if (myString == "hello") {
Bottom line: don't do it and use the functions strcasecmp and strncasecmp to compare strings.
why == operator compares ints but not strings.
In C, objects/constants like int, double, char 123 can be compared with ==.
Arrays cannot be compared with ==.
In many cases though, the usage of an array is converted to the address of the first element as below.
int int_array1[] = { 1,2,3};
int int_array2[] = { 1,2,3};
// This is a pointer compare of address `&int_array1[0]` with address `&int_array2[0]`.
if (int_array1 == int_array2) { ....
But not in this case: sizeof int_array1 is perhaps 3*4 or 12,the size of the array, not the size of "address of the first element".
if (sizeof int_array1 == 42) { ....
To compare the contents of the 2 arrays
// when sizeof int_array1 == sizeof int_array2
if (memcmp(int_array1, int_array2, sizeof int_array1) == 0) { ....
Likewise with a string:
A string is an array (or sequence) of characters up to and including the null character.
char char_array1[] = { '1','2','3',0};
char char_array2[] = { '1','2', 0};
// This is a pointer compare of the address `&char_array1[0]` with `&char_array2[0]`.
if (char_array1 == char_array2) { ....
To compare the contents of the 2 strings, perhaps of different lengths,
if (strcmp(char_array1, char_array2) == 0) { ....
I am confused.
The key difference involves this mantra: "A pointer is not an array - an array is not a pointer". Strings are more like an array with a special content - the terminating null character. == compares non-array objects/constants. Use a function to compare arrays / strings.
int is a single value if you convert it to hexadecimal so it directly compares, however string is an array if characters. so in order to compare strings, you need to compare all the characters one by one, and (==) compares single values(as far as i know).
you need to create a function to do that, or you can use string methods.
[note: I am also a student, not an expert.]
I am using a simple string matching and searching.
Why does *arr is never equal to point though their values(why does I) are same? I am confused what is the cause of this?Is it related to strings or is there any other reason? Any help would be appreciated. I am sorry if the question is not clear.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int search(char ** arr, int size, char *point);
int main()
{
char *array[5]={0};
char original[50];
char toSearch[50];
char *point;
int size=5, searchIndex,i;
/* Copy a string into the original array */
strcpy(original, "why this is not equal");
/* Copy the first 10 characters of the original array into the newcopy array*/
point = memcpy(toSearch, original, 10);
/*string to search*/
array[2]="why this i";
searchIndex = search(array, size, point);
if(searchIndex == -1)
{
printf("%s does not exists in array \n", point);
} else
printf("%s is found at %d position.", toSearch, searchIndex + 1);
return 0;
}
int search(char ** arr, int size, char *point)
{
int index = 0;
// Pointer to last array element arr[size - 1]
char ** arrEnd = (arr + size - 1);
/* Why *arr!=point is never false,
even when both are giving out same values (why this I)?
*/
while(arr <= arrEnd && *arr!=point)
{
printf("%s == %s", *arr,point);
arr++;
index++;
}
if(arr <= arrEnd)
{
printf("%s after found \n",*arr);
return index;
}
return -1;
}
Output:
(null) == why this i
(null) == why this i
why this i == why this i
(null) == why this i
(null) == why this i
why this i does not exists in array
Thank You
I assume that you are asking why the address of the variable of type array-of-char is not identical to the address of the string literal you copy to it.
This is a tricky question, because, excuse me for saying so, it is unclear what could make you expect the address of any variable be different after copying something to it.
Consider the example of not one but two different arrays of char being filled with the same string literal.
char toSearch1[50];
char toSearch2[50];
char *point1;
char *point2;
point1 = memcpy(toSearch1, original, 10);
point2 = memcpy(toSearch2, original, 10);
/* or, depending on what to you is more convincingly copying the same literal */
point2 = memcpy(toSearch2, toSearch1, 10);
Afterwards, the two arrays are still two different variables of type array-of-char and memcpy returns the address of the destination, i.e. of the two different arrays.
Please imagine how those two arrays could have identical address now.
If you follow up with
strcpy(original1, "is this in one or both arrays?");
Would you then expect the two arrays to have different addresses again?
If this does not answer your question, you have a fundamentally different understanding of pointers and addresses of variables than most programmers and I recommend to revise it by finding a tutorial on pointers and addresses.
(Note, for this explanation of what you are asking about I am skipping the discussion of checking lengths in relation to array sizes, using safer versions of string copying, memcpy not correctly null terminating copied strings. All of that is however important for making reliable code, as e.g. Lundin correctly reminds us.)
In C, string are just null terminated char arrays. As ordinary arrays, they decay to pointers when directly used in expression. So when you write str1 == str2 you are just comparing the pointers to their first element.
And two pointers are only equal if they point to the very same object (same address). That is the reason why standard library offers strcmp to compare null terminated strings, and memcmp to compare arbitrary buffers of known size.
when I explicitly state the value of a string, then compare it to itself, system returns FALSE. Does this have something to do with the extra '\0' character added by the system? And how should I refine my code to make it TRUE?
char name[5] = "hello";
if(name == "hello")
{
...
}
You can't (usefully) compare strings using != or ==, you need to use strcmp The reason for this is because != and == will only compare the base addresses of those strings. Not the contents of the strings.
don't use predefined array size like char name[5] = "hello"; instead of you can use char name[] = "hello"; or char name[6] = "hello"; when use
#include <stdio.h>
#include <string.h>
int main()
{
char a[] = "hello";
char b[] = "hello";
if (strcmp(a,b) == 0)
printf("strings are equal.\n");
else
printf("strings are not equal.\n");
return 0;
}
Continuing from my comment, you need char name[6] = "hello"; to hold 'hello (plus the nul-terminating character) Even better, you can use
char name[] = "hello";
That will properly initialize name to contain 6-character (including the nul-byte).
All string.h functions expect a nul-terminated string as a parameter when they take char * or const char * as parameters passed to the functions.
Lastly, as correctly noted in Anuvansh's answer, you cannot use a inequality condition to determine if two strings equal or differ. You either us the normal comparison functions strcmp, strncmp, memcmp or you walk a pointer down each string stopping at the first char the strings differ on, or on the nul-byte if the strings are equivalent.
Look things over and let me know if you have any further questions. Gook luck with your coding.
The strcmp() returns 0 if both argument are equal.
char name[]="hello";
if(strcmp(name,"hello") == 0)
return TRUE;
else
return FALSE;
Actually, name is a pointer that points to the address of the string "hello". You can't compare them. So you can try strcmp function instead. Also include the string.h library.
like:
strcmp(name,"hello");
also as one of the comment points out, take a char array of 6 to include '\0'.
Hope that helps.
In C ,the array name is actually the pointer to the first element of that array.
in your case:
if(name == "hello")
you compare pointer to the string so it will return false
You can see the same concept in this article
why is array name a pointer to the first element of the array?
You can simply include "string.h" library and use strcmp() function
code like this:
char name[]="hello";
if(strcmp(name,"hello")==0){
.....
}
to make it Ture