Reputation:
I'm studying C programming, I know in C strcmp
is used to compare two strings, but the comparing always contains the new line character, I want to ignore it. I know I can remove the new line character and then compare them, but is there any function that ignores the new line character automatically?
Upvotes: 2
Views: 8460
Reputation: 9375
A function like the following could be used instead of strcmp()
. It does the same thing, but ignores one (possible) trailing newline on the second string. It doesn't modify the strings.
int my_cmp(const char *str1, const char *str2)
{
int r,n;
/* Get length of str1, which is also the index of the 1st additional
* char in str2
*/
n = strlen(str1);
/* Compare the first n chars */
r = strncmp(str1,str2,n);
/* If 1st n chars match, make sure next char in str2 is either the null char
* or a newline followed by the null char. Otherwise, return -1 since str2 is
* longer (making str1 "less than" str2)
*/
if ( !r && str2[n] && (str2[n] != '\n' || str2[n+1]) )
return -1;
return r;
}
Here's another one that ignores all newlines anywhere in either string:
int my_cmp(const char *str1, const char *str2)
{
const unsigned char *a, *b;
/* loop over both strings */
for (a = str1, b = str2; ; a++, b++) {
while (*a == '\n') a++; /* skip newlines in str1 */
while (*b == '\n') b++; /* skip newlines in str2 */
/* If we reach the end of either string (or both), one of
* the if's below will terminate the loop */
/* return if we're at end of both strings */
if (!(*a || *b))
return 0;
/* positive return when str1's char is greater than str2's
* (or at end of str2) */
if (*a > *b)
return 1;
/* negative return when str1's char is less than str2's
* (or at end of str1) */
if (*a < *b)
return -1;
}
return 0;
}
Of course, if you just need to ignore a single trailing newline it's easy to strip it off anyway (just locate it and overwrite it with '\0'
)...
Upvotes: 0
Reputation: 20266
You should first write a function that computes the length of the string, in which both the standard termination character and the endline character terminate the string. In doing so, I suggest you both check Line Feed and Carriage Return character (check here)
Then, you check that both strings have same length according to the previous definition.
If yes, you further check the string with strncmp (and using the found length as third parameter).
Upvotes: 1
Reputation: 25129
This is one of those cases where it's easier to open code the function. I've made it test for equality strictly (i.e. not alphabetise), though that would be a relatively easy change.
Try this, which should actually do what the original questioner asked:
/* Compare two strings s1 and s2, assuming s1 is terminated
* by \n or a NULL, and s2 is terminated by a NULL. A match
* returns 0, a non-match returns 1.
*/
int
strcmpst1nl (const char * s1, const char * s2)
{
char s1c;
do
{
s1c = *s1;
if (s1c == '\n')
s1c = 0;
if (s1c != *s2)
return 1;
s1++;
s2++;
} while (s1c); /* already checked *s2 is equal */
return 0;
}
Interestingly this wasn't particularly elegant to do with a for
loop. More elegant answers appreciated.
A more generalised routine to compare two strings where either can be terminated by a \n
or a NULL
(not quite what you asked) would be:
/* Compare two strings s1 and s2, assuming either is
* terminated by \n or a NULL, A match
* returns 0, a non-match returns 1.
*/
int
strcmpnl (const char *s1, const char *s2)
{
char s1c;
char s2c;
do
{
s1c = *(s1++);
s2c = *(s2++);
if (s1c == '\n')
s1c = 0;
if (s2c == '\n')
s2c = 0;
if (s1c != s2c)
return 1;
}
while (s1c); /* already checked *s2 is equal */
return 0;
}
Another less efficient route (assuming s1 is terminated by \n
) would be:
#include <string.h>
#include <strings.h>
int
strcmpst1nl2 (const char *s1, const char *s2)
{
int s1len, s2len;
s1len = strlen (s1);
s2len = strlen (s2);
/* check strings are equal length without \n */
if (s1len - 1 != s2len)
return 1;
/* we know s1len > 0, as s2len would be -1, so this is safe */
if (s1[s1len - 2] != '\n')
return 1;
return bcmp (s1, s2, s1len - 1);
}
Upvotes: 2