This piece of code works fine. But I'm wondering if it can be done in a more efficient way. More specifically, this part (*(s1 + i)
) if it possible to force it to sequence through entire array character by character via pointer, for example, *s1++
.
My task to do this function compareStrings
without index array []:
int compareStrings(const char *s1, const char *s2)
{
int i = 0, answer;
// i - to sequence through array of characters
// pointer to character string1 and character string2
while (*(s1 + i) == *(s2 + i) && *(s1 + i) != '0円'&& *(s2 + i) != '0円')
{
i++;
}
if ( *(s1 + i) < *(s2 + i) )
answer = -1; /* s1 < s2 */
else if ( *(s1 + i) == *(s2 + i) )
answer = 0; /* s1 == s2 */
else
answer = 1; /* s1 > s2 */
return answer;
But I want to change it to s1++
and s2++
instead of *(s1 + i)
and *(s2 + i)
. I've tried to implement this idea with pining an extra pointer to the beginning but I've failed.
int compareStrings(const char *s1, const char *s2) { int answer; char **i = s1, **j = s2; // i to sequence through array of characters while (*(i++) == *(j++) && *(i++) != '0円'&& *(j++) != '0円'); if (*i < *j) answer = -1; /* s1 < s2 */ else if (*i == *j) answer = 0; /* s1 == s2 */ else answer = 1; /* s1 > s2 */ return answer; }
3 Answers 3
You don't need pointers to character pointers at all:
int str_cmp(const char* s1, const char* s2)
{
while (*s1 != '0円' && *s1 == *s2)
{
++s1;
++s2;
}
if (*s1 == *s2)
{
return 0;
}
return *s1 < *s2 ? -1 : 1;
}
Also, there is a bug in your second implementation: it returns 1 on compareStrings("hello", "helloo")
, when the correct result is -1.
Hope that helps.
-
2\$\begingroup\$ It would be more understandable if you write the test for end-of-string as "*s != '0円'". \$\endgroup\$jamesqf– jamesqf2017年02月04日 06:10:34 +00:00Commented Feb 4, 2017 at 6:10
-
2\$\begingroup\$ You don't need to check that both
*s1
and*s2
are non-null. Since you are checking that they are equal, you only need to check one of them for non-null. Although as written the compiler would probably optimize it to only do 1 check. \$\endgroup\$Buge– Buge2017年02月04日 08:44:42 +00:00Commented Feb 4, 2017 at 8:44
There's another huge bug in your code which stems from a quirk of C (and C++):
Plain char
can be either signed or unsigned.
Next, do you really want to normalize the return-values to one of -1
, 0
and 1
, or is negative, zero, positive enough? The latter is what the standard does... and it's less work.
int compareStrings(const char* s1, const char* s2)
{
while (*s1 && *s1 == *s2) {
++s1;
++s2;
}
return (int)(unsigned char)*s1 - (int)(unsigned char)*s2; // not normalized
return *s1 == *s2 ? 0 : (unsigned char)*s1 < (unsigned char)*s2 ? -1 : 1; // normalized
}
(The code assumes that an int
is bigger than a char
.)
-
\$\begingroup\$ I've tried to implement your version of this function and it doesn't do the job that I need to at all. @Deduplicator \$\endgroup\$Yellowfun– Yellowfun2017年02月03日 16:38:23 +00:00Commented Feb 3, 2017 at 16:38
-
2\$\begingroup\$ This wrong. If string s2 is shorter than s1 you read past the end of s2. \$\endgroup\$Tonny– Tonny2017年02月03日 16:38:33 +00:00Commented Feb 3, 2017 at 16:38
-
3\$\begingroup\$ @Tony: How? That would mean they are different and thus stops the loop! \$\endgroup\$Deduplicator– Deduplicator2017年02月03日 17:58:46 +00:00Commented Feb 3, 2017 at 17:58
-
\$\begingroup\$ @Yellowfun: You mean you have to have your return-value normalized, or what? \$\endgroup\$Deduplicator– Deduplicator2017年02月03日 18:00:03 +00:00Commented Feb 3, 2017 at 18:00
-
\$\begingroup\$ Now it's working fine! @Deduplicator \$\endgroup\$Yellowfun– Yellowfun2017年02月03日 18:08:49 +00:00Commented Feb 3, 2017 at 18:08
Remember when you learned that arrays are nothing but the pointer to the first element of the same array? You can do this the other way around too: *(s1 + 1)
is equivalent to s1[1]
.
In the second example take a look at how you resolve which pointer. **i = s1
so will *(i++)
be equal to *(s1 + 1)
? Your debugger can tell you the details from here :)
-
\$\begingroup\$ It says "+ i 0x0018e25c {0x69726561 <Error reading characters of string.>} char * * " \$\endgroup\$Yellowfun– Yellowfun2017年02月03日 12:26:02 +00:00Commented Feb 3, 2017 at 12:26
-
\$\begingroup\$ About it I know '*(s1 + 1) is equivalent to s1[1]'. :) \$\endgroup\$Yellowfun– Yellowfun2017年02月03日 12:30:21 +00:00Commented Feb 3, 2017 at 12:30
-
5\$\begingroup\$ "Remember when you learned that arrays are nothing but the pointer to the first element of the same array?" If so, then you were taught incorrectly. :-) What you say here is true, but it's because arrays decay implicitly to a pointer to their first element. The two things are not equivalent as far as the language is concerned. \$\endgroup\$Cody Gray– Cody Gray2017年02月03日 13:07:13 +00:00Commented Feb 3, 2017 at 13:07
-
1\$\begingroup\$ Agreed, it is an oversimplification. \$\endgroup\$fer-rum– fer-rum2017年02月03日 13:33:30 +00:00Commented Feb 3, 2017 at 13:33
-
\$\begingroup\$ Thank you. I thought pointer to array is a & address in the memory to that array[]. But we can reach to it from start to end through the first element and than incrementing with something like index. \$\endgroup\$Yellowfun– Yellowfun2017年02月03日 16:57:57 +00:00Commented Feb 3, 2017 at 16:57
*(s1 + i) == *s2 + i
is a typo and you mean*(s1 + i) == *(s2 + i)
\$\endgroup\$