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.]
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.
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.
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");
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
How would i get the lengths of the belowed strings, as well as the array size?
char str [] = {};
str[0] = "He";
str[1] = "llo";
str[2] = " Wor";
str[3] ="ld";
And how i could store them in a multidimension array? So this array would look something like this:
char strstr [size of str][string length of str];
The strstr[][] array-dimensions should be
1.number of array-elements of str and
2.number of all chars in str. In the case of strstr[3][1], this would be "d".
Would that be possible without initializing the str-array in the first place?
[edit]
I see, the second dimension of strstr doesn't make sense. It should be the length of every element from *str and not the complete number of chars in *str
[/edit]
This will probably do what you want, but it wasn't exactly what you asked for.
#include <stdio.h>
char *strs[] = {
"foo",
"bar",
"bazy"
};
int main() {
printf("%d - %s\n", strlen(strs[0]), strs[0]);
printf("%d - %s\n", strlen(strs[1]), strs[1]);
printf("%d - %s\n", strlen(strs[2]), strs[2]);
return 0;
}
Output:
3 - foo
3 - bar
4 - bazy
Note that you only have a few possibilities for storing arrays of arrays. You can either do what this solution does (make an array of pointers to arrays), make a "compressed" list of arrays in a large array, or make an overly large 2-D array.
The "compressed" array would take the format:
char strs[] = "foo\0bar\0bazy"; // array is {f,o,o,\0,b,a,r,\0,b,a,z,y,\0}
The problem with this format is that it's somewhat tricky to access anything after the first element, and usually involves searching linearly through the array. (or keeping a seperate table of addresses... rather like the first solution)
The 2-D array requires that you specify all sizes, and looks like this:
char strs[3][5] = {
"foo",
"baz",
"baxy"
};
int main() {
printf("%d - %s\n", strlen(strs[0]), strs[0]);
printf("%d - %s\n", strlen(strs[1]), strs[1]);
printf("%d - %s\n", strlen(strs[2]), strs[2]);
return 0;
}
This is probably laid out in memory like this:
{f,o,o,\0,*,b,a,z,\0,*,b,a,x,y,\0} (the *'s could be anything, most dependent on your compiler)
Since the compiler knows that each string takes exactly 5 bytes, it can easily calculate the location of the later elements.
When declaring an array in C, you must declare its size unless you are simultaneously providing initializing values. This is because arrays are laid out sequentially in memory, and so the computer needs to know how much space to set aside.
Further, char str [] = {....} will declare an array of characters, not an array of strings. A string is an array of characters, so str is just a single string.
To create an array of strings, you need to do something like this:
char strs[num_of_strings][max_length_of_strings+1];
strcpy(strs[0],"string1");
strcpy(strs[1],"string2");
...
There's a more in depth discussion of other options at this question.
If you're specifying max_length_of_strings but then copying from source strings that you can't guarantee are shorter than max_length_of_strings, you want to use strncpy instead of strcpy. In that case you also want to ensure that the resulting strings are null terminated, which you can do by looping
strs[i][max_length_of_strings] = '\0';
To get the length of a null-terminated string, you use the function strlen.
As to the second part of your question, the above should make it clear how to create a higher-dimensional array. I'd provide more detail, but I'm not exactly sure what you want this array to do. When you say "number of all chars in str" do you mean the max length of the strings stored in your strs array?
If so, you don't need to worry about that. Programming your strs array like I explained it above will already give you this functionality: since strings are just arrays of char's, you can index into strings in the same way that you index into char's.
Let me know if any of the above isn't clear, and I'll try to explain it better.
If you want an actual array, something like this:
char str[4][5]; // holds up to 4 characters in each
strcpy(str[0], "He");
strcpy(str[1], "llo");
strcpy(str[2], " Wor");
strcpy(str[3], "ld");
To get the length of a string in C you'd use strlen and pass the string.
int len = strlen(array[0]);