Skip to main content

C Strings

Introduction to Strings in C

In C, a string is a sequence of characters stored in memory and terminated by a null character '\0'. Unlike some higher-level languages, C doesn't have a dedicated string data type - instead, strings are represented as arrays of characters.

The null character '\0' (ASCII value 0) marks the end of a string, allowing functions to know where the string terminates.

String Declaration and Initialization

There are several ways to declare and initialize strings in C:

c
// Method 1: Using string literal (recommended)
char greeting[] = "Hello, World!";

// Method 2: Character by character (with explicit null terminator)
char message[] = {'H', 'e', 'l', 'l', 'o', '\0'};

// Method 3: Specifying size explicitly (size must include space for '\0')
char name[20] = "John";

// Method 4: Declaring first, initializing later
char title[50];
strcpy(title, "C Programming");
caution

When declaring a string with a specific size, always ensure there's enough space for all characters plus the null terminator!

String Memory Representation

Let's look at how a string is stored in memory:

c
char greeting[] = "Hello";

This is stored as:

Index012345
Value'H''e''l''l''o''\0'

Notice that the array has 6 elements even though "Hello" has only 5 characters. The extra element holds the null terminator.

Reading and Writing Strings

Reading Strings

There are several ways to read strings in C:

c
#include <stdio.h>

char name[50];

// Using scanf (stops at whitespace)
scanf("%s", name);

// Using gets (dangerous, deprecated - can cause buffer overflow)
// gets(name); // Avoid using this!

// Using fgets (safer alternative)
fgets(name, 50, stdin);
warning

Never use gets() in your code! It doesn't check the buffer size and can lead to serious security vulnerabilities.

Writing Strings

To output strings:

c
#include <stdio.h>

char name[] = "John Doe";

// Using printf
printf("%s\n", name);

// Using puts (automatically adds a newline)
puts(name);

String Input Pitfalls

When using scanf() to read strings:

  • It stops reading at the first whitespace
  • It doesn't check buffer boundaries

Example of a safer approach:

c
#include <stdio.h>

int main() {
char name[50];

printf("Enter your full name: ");

// Limit input to 49 characters to leave room for '\0'
scanf("%49s", name);

printf("Hello, %s!\n", name);

return 0;
}

For reading input with spaces, fgets() is preferred:

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

int main() {
char fullName[50];

printf("Enter your full name: ");
fgets(fullName, 50, stdin);

// Remove the newline character that fgets captures
fullName[strcspn(fullName, "\n")] = '\0';

printf("Hello, %s!\n", fullName);

return 0;
}

String Constants vs Character Arrays

There's an important distinction between these two declarations:

c
// String literal (read-only)
const char *str1 = "Hello";

// Character array (modifiable)
char str2[] = "Hello";
  • str1 is a pointer to a read-only string literal
  • str2 is a modifiable array of characters

Attempting to modify str1 would result in undefined behavior (likely a program crash):

c
str1[0] = 'h'; // ERROR: Trying to modify a string literal
str2[0] = 'h'; // OK: Modifying a character array

Common String Operations

String Length

To find the length of a string (excluding the null terminator):

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

int main() {
char message[] = "Hello, World!";

// Using strlen() function
int length = strlen(message);

printf("Length of string: %d\n", length);

return 0;
}

String Comparison

To compare strings:

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

int main() {
char str1[] = "apple";
char str2[] = "banana";
char str3[] = "apple";

// Returns 0 if equal, <0 if str1 < str2, >0 if str1 > str2
printf("Comparing str1 and str2: %d\n", strcmp(str1, str2));
printf("Comparing str1 and str3: %d\n", strcmp(str1, str3));

return 0;
}

String Copying

To copy one string to another:

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

int main() {
char source[] = "Source string";
char destination[50];

// Copy source to destination
strcpy(destination, source);

// Safer alternative with size limit
strncpy(destination, source, 49);
destination[49] = '\0'; // Ensure null termination

printf("Destination: %s\n", destination);

return 0;
}

String Concatenation

To join strings:

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

int main() {
char first[50] = "Hello, ";
char second[] = "World!";

// Append second to first
strcat(first, second);

// Safer alternative with size limit
strncat(first, " Welcome!", 49 - strlen(first));

printf("Result: %s\n", first);

return 0;
}

String Manipulation Example

Let's see a comprehensive example that demonstrates various string operations:

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

void printReverse(char *str);
void toUppercase(char *str);

int main() {
char input[100];
char copy[100];

// Get input from user
printf("Enter a string: ");
fgets(input, 100, stdin);

// Remove newline character
input[strcspn(input, "\n")] = '\0';

// Create a copy
strcpy(copy, input);

// Get and display string length
printf("Length: %lu\n", strlen(input));

// Convert to uppercase
toUppercase(copy);
printf("Uppercase: %s\n", copy);

// Print in reverse
printf("Reversed: ");
printReverse(input);
printf("\n");

return 0;
}

// Function to print a string in reverse
void printReverse(char *str) {
int length = strlen(str);
for (int i = length - 1; i >= 0; i--) {
printf("%c", str[i]);
}
}

// Function to convert string to uppercase
void toUppercase(char *str) {
for (int i = 0; str[i]; i++) {
str[i] = toupper(str[i]);
}
}
  1. Buffer Overflow

    c
    char name[5];
    strcpy(name, "John Doe"); // Overflows the buffer!
  2. Forgetting Null Terminator

    c
    char str[5];
    str[0] = 'H'; str[1] = 'i';
    // Without str[2] = '\0', this isn't a proper string
  3. Using == for Comparison

    c
    char str1[] = "hello";
    char str2[] = "hello";

    if (str1 == str2) { // WRONG: Compares addresses, not content
    printf("Equal\n");
    }

    if (strcmp(str1, str2) == 0) { // CORRECT
    printf("Equal\n");
    }

Conclusion

Strings in C are arrays of characters terminated by a null character. While C doesn't provide a built-in string type, the standard library offers various functions to manipulate strings effectively.

For safe string handling:

  • Always ensure enough buffer space
  • Use bounded functions like strncpy() instead of strcpy()
  • Always ensure strings are null-terminated
  • Use strcmp() for string comparison, not ==

In the next section, we'll explore the C standard library functions for string manipulation in more detail.

Practice Exercises

  1. Write a program that reads a string and prints the frequency of each character.
  2. Create a function that checks if a string is a palindrome.
  3. Implement a function that removes all spaces from a string.
  4. Write a program that counts the number of words in a string.
  5. Create a function that reverses a string in-place (without using a second array).


If you spot any mistakes on this website, please let me know at [email protected]. I’d greatly appreciate your feedback! :)