munotes®

Practical 6(c): strlen and strcmp

Chapter Twenty-One

Syllabus topic Module 1, Practical 6(c): "Write a program to using strlen(), strcmp() function ."

Pages 72 to 75 of 206

Aim

To use the strlen() and strcmp() functions.

Both come from one header

#include <string.h>

Without it the compiler does not know these functions exist, and in C17 that is an error, not a warning.

strlen: how long is this string

strlen(s) counts the characters in s up to but not including the terminating null.

#include <stdio.h>
#include <string.h>

int main(void)
{
    char a[20] = "Mumbai";
    char b[] = "";
    char c[] = "BSc IT";

    printf("strlen(\"%s\") = %zu\n", a, strlen(a));
    printf("strlen(\"%s\") = %zu  (the empty string)\n", b, strlen(b));
    printf("strlen(\"%s\") = %zu  (the space counts)\n", c, strlen(c));

    printf("sizeof a = %zu, strlen(a) = %zu\n", sizeof a, strlen(a));

    return 0;
}
strlen("Mumbai") = 6
strlen("") = 0  (the empty string)
strlen("BSc IT") = 6  (the space counts)
sizeof a = 20, strlen(a) = 6

The last line is the distinction this function is always asked about.

sizeof astrlen(a)
Answershow big is the boxhow much is in it
Counts the nullyesno
Decidedwhen the program is compiledwhen the function runs
Is it a functionno, an operatoryes
For char a[20] = "Mumbai"206

strlen returns a size_t, an unsigned type, whose format specifier is %zu. Two consequences follow, and the second bites.

Print it with %zu, not %d. With -Wall the compiler says so.

strlen(s) - 1 on an empty string is not minus 1. It is an enormous positive number, because an unsigned type cannot be negative and subtracting one from zero wraps to the largest value. A loop written for (i = strlen(s) - 1; i >= 0; i--) with i unsigned never ends. Cast to int when you need to go backwards, as [Practical 6(b): Is This String a Palindrome?] does.

strcmp: which of these two comes first

strcmp(a, b) compares two strings and returns a number that tells you their order:

Return valueMeaning
0the strings are identical
negativea comes before b
positivea comes after b

The comparison is character by character from the left. At the first pair that differs, the character codes decide, and the rest of both strings is irrelevant.

#include <stdio.h>
#include <string.h>

int main(void)
{
    printf("strcmp(\"apple\", \"apple\")  = %d\n", strcmp("apple", "apple"));
    printf("strcmp(\"apple\", \"banana\") = %d\n", strcmp("apple", "banana"));
    printf("strcmp(\"banana\", \"apple\") = %d\n", strcmp("banana", "apple"));
    printf("strcmp(\"Apple\", \"apple\")  = %d\n", strcmp("Apple", "apple"));
    printf("strcmp(\"app\", \"apple\")    = %d\n", strcmp("app", "apple"));

    return 0;
}
strcmp("apple", "apple")  = 0
strcmp("apple", "banana") = -1
strcmp("banana", "apple") = 1
strcmp("Apple", "apple")  = -1
strcmp("app", "apple")    = -1

Read those five lines carefully, because each one answers a viva question.

Identical strings give 0. Not 1. This is the whole trap and it has its own section below.

munotes.in72

Practical 6(c): strlen and strcmp

apple against banana is negative, because at the first character a is 97 and b is 98.

Apple against apple is negative, because a capital A is 65 and a small a is 97. Every capital letter comes before every small letter in ASCII, which is why an ordinary alphabetical sort puts Zebra before apple.

app against apple is negative. The first three characters match; then app has its terminating null, which is 0, against l, which is 108. A string that is a prefix of another always comes first.

The standard promises only the sign of the value, not its size. This library returns minus 1 and 1; another may return the difference of the character codes, minus 1 and 1 or minus 25 and 25. Test the sign, never the value. A program that says if (strcmp(a, b) == -1) is relying on something no standard guarantees.

The trap: 0 means equal

#include <stdio.h>
#include <string.h>

int main(void)
{
    char a[] = "ravi", b[] = "ravi";

    if (strcmp(a, b))
        printf("WRONG: the program thinks they are different\n");
    else
        printf("RIGHT: they are the same\n");

    if (strcmp(a, b) == 0)
        printf("The correct test: they are the same\n");

    return 0;
}
RIGHT: they are the same
The correct test: they are the same

The first if gives the right answer here for the wrong reason, and that is why it is dangerous. In C, a condition is true when it is not zero. strcmp returns 0 for equal strings, so if (strcmp(a, b)) is true exactly when the strings are different. Writing it that way and reading it as "if a equals b" gets the answer backwards on every pair that differs, and right on every pair that matches, which is the worst possible failure pattern for testing.

Always write it out: if (strcmp(a, b) == 0) for equal, != 0 for different.

And the other half of the same lesson:

if (a == b)              /* WRONG for strings */

That compares two addresses. Two separate arrays are at two different addresses, so it is false even when the contents match. == works on numbers and characters; strings need strcmp.

Both functions, in one program that does something

#include <stdio.h>
#include <string.h>

int main(void)
{
    char first[50], second[50];
    int result;

    printf("Enter the first string: ");
    scanf("%49[^\n]", first);
    printf("Enter the second string: ");
    scanf(" %49[^\n]", second);

    printf("\"%s\" has %zu characters\n", first, strlen(first));
    printf("\"%s\" has %zu characters\n", second, strlen(second));

    result = strcmp(first, second);

    if (result == 0)
        printf("The two strings are equal\n");
    else if (result < 0)
        printf("\"%s\" comes before \"%s\"\n", first, second);
    else
        printf("\"%s\" comes after \"%s\"\n", first, second);

    return 0;
}
banana
apple
Enter the first string: Enter the second string: "banana" has 6 characters
"apple" has 5 characters
"banana" comes after "apple"
munotes.in73

Practical 6(c): strlen and strcmp

The space at the start of the second format string, " %49[^\n]", skips the newline left behind by the first read. Without it the second read sees that newline immediately, matches nothing, and leaves second untouched. This is the commonest reason a program that reads two lines appears to skip the second one.

The other comparison functions

FunctionWhat it does
strcmp(a, b)compares the whole strings
strncmp(a, b, n)compares only the first n characters
strcasecmp(a, b)compares ignoring case, on most systems

strncmp is genuinely useful: strncmp(word, "com", 3) == 0 asks whether a word begins with those three letters. strcasecmp is not in the C standard, though nearly every system has it; if a program must be portable, lower both strings yourself with tolower from ctype.h.

What beginners get wrong

if (strcmp(a, b)) read as "if equal". It is true when they differ.

Testing strcmp(a, b) == -1. Only the sign is guaranteed.

Using == on two strings. That compares addresses.

Printing strlen with %d. It returns a size_t; use %zu.

Believing strlen counts the null. It does not; the array needs one more byte than strlen reports.

Calling strlen inside a loop condition. for (i = 0; i < strlen(s); i++) recounts the whole string on every single iteration. Count once into a variable before the loop.

Forgetting #include <string.h>.

Quick revision

  • Both are in string.h.
  • strlen(s) counts characters before the null and returns a size_t, printed with %zu.
  • sizeof is the size of the array; strlen is the length of the string in it.
  • strcmp(a, b) returns 0 if equal, negative if a comes first, positive if b does.
  • Only the sign is guaranteed, never the value.
  • Equal is strcmp(a, b) == 0. A bare if (strcmp(a, b)) means different.
  • == on strings compares addresses and is always the wrong test.
  • A leading space in a scanf format skips the leftover newline.

What goes in your journal

Aim, the algorithm, the program using both functions, and the output for two pairs: two equal strings and two that differ. Write the three return values of strcmp into the conclusion as a small table. If there is room, add the sizeof against strlen line with its two numbers; both are asked in vivas and both fit on one line.

Test yourself

1. What does strcmp return when the strings are identical? 0.

2. char a[20] = "Mumbai"; What are sizeof a and strlen(a)? 20 and 6. sizeof is the size of the array, strlen the length of the string in it.

munotes.in74

Practical 6(c): strlen and strcmp

3. Why is if (strcmp(a, b)) the wrong way to test for equality? Because a non-zero value is true in C, and strcmp returns non-zero exactly when the strings are different. The test means "if they differ".

4. Is strcmp("Apple", "apple") negative or positive, and why? Negative. A capital A is 65 and a small a is 97, so the capital comes first.

5. Why should you not test strcmp(a, b) == -1? Because the standard guarantees only the sign of the result. A different library may return minus 25 for the same pair.

6. Why is for (i = 0; i < strlen(s); i++) a poor loop? Because strlen is called on every iteration and walks the whole string each time. Store the length in a variable before the loop.

munotes.in75

The rest of this subject

These notes are cut from the University's printed syllabus. Open the syllabus itself for the same subject.

Report or request
Done!