Tuesday, November 1, 2011

Working with Strings in ANSI C

Compared to other languages, C doesn't have a built-in string structure. Instead, character arrays are used:
char str[20] = "The bird is the word";
The string above is represented into memory like in the table below:
0
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
T
h
e

b
i
r
d

i
s

t
h
e

w
o
r
d
/0
where '/0' represents the string's terminator (this is how C knows where your string ends).

ANSI C also provides a library, string.h which can be used for all sort of string operations such as:
-Getting the length of string : strlen
-Concatenating two strings: strcat, strncat
-Copying data to a string: strcpy, strncpy
-Comparing two strings: strcmp, strncmp

Getting the length of a string
strlen can be used for computing the length of a string. The length of the string is dictated by the position of its null terminator. Here's an example:
#include<stdio.h>
#include<string.h>

int main(void)
{
   char str[20] = "The bird is the word";
   size_t length = strlen(str);
   printf("Length of the string: %u\n", length);
   return 0;
}
/*Output:
Length of the string: 20
*/
TIP: The length is returned as a size_t datatype. The size of size_t is platform dependent (it can be an int, unsigned int, long, etc), but in most cases you can consider it as unsigned int.
PITFALL: The length of a string is determined by the position of the '\0' character.  If you pass a string who doesn't have a null terminator, the result is unpredictable.

Concatenating two strings
strcat and strncat the functions that can be used for concatenating 2 strings. The main difference between them is that strncat allows you to specify how many characters from the second string will be appended to the first string.
Here's an example on how to use strcat:
#include<stdio.h>
#include<string.h>

int main(void)
{
   char dest[25]      = "The bird is";
   char source[10]    =" the word";
   strcat(dest,source);
   printf("Destination string: %s\n"
          "Source string     : %s",
           dest,source);
   return 0;
}
/*Output:
Destination string: The bird is the word
Source string     :  the word
 */
TIP: strcat also returns a pointer to the destination string. Here's an example:
#include<stdio.h>
#include<string.h>

int main(void)
{
   char dest[25]      = "The bird is";
   char source[10]    =" the word";
   char *dest2 = NULL;
   /*dest2 will point now to the dest string*/
   dest2 = strcat(dest,source);
   printf("Destination string  : %s\n"
          "Source string       : %s\n"
          "Destination pointer : %s\n",
          dest,source,dest2);
   return 0;
}
/*Output:
Destination string  : The bird is the word
Source string       :  the word
Destination pointer : The bird is the word
 */
strncat allows you to specify how many characters will be appended through its third parameter:
#include<stdio.h>
#include<string.h>

int main(void)
{
   char dest[25]      = "The bird is";
   char source[10]    =" the word";
   /*Only the first 4 characters from source will be appended to dest*/
   strncat(dest,source,4);
   printf("Destination string  : %s\n"
          "Source string       : %s\n",
          dest,source);
   return 0;
}
/*Output:
Destination string  : The bird is the
Source string       :  the word
 */
TIP:Both string must be null-terminated, otherwise the result is unpredictable and may even trigger memory errors.
TIP:Be sure that the character array that holds your destination string is large enough to support the operation. Otherwise, a buffer overflow error might occur.

Copying data to a string
strcpy and strncpy the functions that can be used for concatenating 2 strings.  The main difference between them is that strncpy allows you to specify how many characters from the second string will be copied to the first string (just like strcat and strncat).

Here's an example on how to use strcpy:
#include<stdio.h>
#include<string.h>

int main(void)
{
   char dest[25]      = "The bird is";
   char source[10]    =" the word";
   strcpy(dest,source);
   printf("Destination string  : %s\n"
          "Source string       : %s\n",
          dest,source);
   return 0;
}
/*Output:
Destination string  :  the word
Source string       :  the word
 */
And here's an example on how to use strncpy:
#include<stdio.h>
#include<string.h>

int main(void)
{
   char dest[25]      = "The bird is";
   char source[10]    =" the word";
   /*Only the first 9 characters from source will be overwritten in dest*/
   strncpy(dest,source,8);
   printf("Destination string  : %s\n"
          "Source string       : %s\n",
          dest,source);
   return 0;
}
/*Output:
Destination string  :  the wor is
Source string       :  the word
 */
TIP:The source string must be null-terminated, otherwise the result is unpredictable and may even trigger memory errors.
TIP:Be sure that the character array that holds your destination string is large enough to support the operation. Otherwise, a buffer overflow error might occur.
TIP: strcpy destroys the destination string, while strncpy overwrites only the first n characters with the first n characters from the source string.
PITFALL: If you use dynamically allocated character arrays, a common mistake is to use the assignment operator instead of strcpy/strncpy. Using = will create a shallow copy of your first string. This means that when your first string will be modified, your second string will be modified as well (since both pointers point to the same memory zone). Here's an example:
#include<stdio.h>
#include<stdlib.h>
#include<string.h>

int main(void)
{
    const int LENGTH = 20;

    char* myString = NULL;
    char* shallowCopy = NULL;
    char* deepCopy = NULL;

    //Allocates memory for the strings
    myString = malloc(sizeof(char)*LENGTH);
    shallowCopy = malloc(sizeof(char)*LENGTH);
    deepCopy = malloc(sizeof(char)*LENGTH);
    //Copies into the first string its value
    strcpy(myString, "String text");
    //Creates a SHALLOW copy of the first string
    shallowCopy = myString;
    //Creates a DEEP copy of the first string
    strcpy(deepCopy, myString);

    //Making a modification in the first string that will
    //propagate through shallow copy.
    myString[0]='Z';

    puts(myString);
    puts(shallowCopy);
    puts(deepCopy);

    return 0;
}
/*Output
Ztring text
Ztring text
String text
 */
Comparing two strings
Strings are compared lexicographically, character by character using the functions strcmp and strncmp.

The difference between them is that strmcp compares the two strings character by character until the a string terminator is encountered in one of the strings, while strncmp compares only the first n characters.

The return value of the functions is calculated in the following way:
-if the strings are equal from a lexicographic point of view, it returns 0
-if the strings are not equal from a lexicographic point of view and the functions find a character in the first string who has has a bigger ASCII value than the character in the second string at the same position it will return a positive value
-if the are not equal from a lexicographic point of view and a the functions finds a character in second string who has has a bigger ASCII value than the character in first string at the same position it will return a negative value.

Here's an example on how to use these functions:
#include<stdio.h>
#include<string.h>

int main(void)
{
   char string1[10]    ="the ward";
   char string2[10]    ="the word";
   int cmp1 = strcmp(string1,string2);
   int cmp2 = strncmp(string1,string2,3);
   printf("Cmp1 = %d\nCmp2 = %d",cmp1,cmp2);
   /*
     cmp1 = -1 "the ward" < "the word" because 'a'<'o'
     cmp2 =  0  "the" = "the"
   */
   return 0;
}
/*Output:
Cmp1 = -1
Cmp2 = 0
 */
TIP:Both string must be null-terminated, otherwise the result is unpredictable and may even trigger memory errors.
TIP: If strncmp encounters a string terminator before the n-th character, strncmp will act like strcmp.
TIP: If you want to check if two strings are equal, use the clause (strcmp(str1,str2)==0)

Question: What tips & tricks do you know related to string operations?

References:
http://www.cplusplus.com/reference/cstring/

No comments:

Post a Comment

Got a question regarding something in the article? Leave me a comment and I will get back at you as soon as I can!

Related Posts Plugin for WordPress, Blogger...
Recommended Post Slide Out For Blogger