Printing and Reading Strings in C

Now that we know what strings are and how to define string variables in C Language, let's see how to print and read strings from console.

In this lesson we will see how to use the printf and puts functions to print strings to screen and the scanf and gets functions to read strings from console. We will also see how to read strings in a custom way.

Printing Strings with the printf Function

Let's start studying the first function to print strings to screen in C Language: the printf function. This function is defined in the stdio.h library header.

printf is a very powerful and flexible function, which allows printing formatted strings to screen. It wants, as first parameter, a string that represents the so-called format string. We will see in the next lessons the detail of how format strings are made, also because they recur in many other functions.

To be able to print a string with printf, you need to use the conversion specifier %s, which indicates that the string to print is passed as a subsequent parameter to the format string.

For example, the following code takes a string variable, name, which represents a person's name and prints a greeting to screen:

#include <stdio.h>

int main() {
    char name[] = "Mario";
    printf("Hello, %s!\n", name);
    return 0;
}

The code prints to screen:

Hello, Mario!

When printf encounters the %s specifier, it takes the corresponding string and prints it to screen character by character, until it encounters the terminator character '\0'.

Definition

Printing Strings with printf

The printf function is used to print formatted strings to screen. To print a string, you need to use the %s specifier.

printf("%s", string);

In case the terminator should be missing, printf would continue printing characters to screen until it encounters a terminator, which could be present in another part of memory. In that case the program behavior would be undefined.

Note

Attention to strings passed to printf

You must always make sure that strings passed to the printf function are correctly terminated with the terminator character '\0'.

Otherwise, the program behavior is undefined.

Printing a portion of a string or string in a field

We can also print a portion of a string, rather than the whole string. To do this, we need to use the %.ps specifier, where p is an integer number representing the maximum number of characters to print. For example, the following code prints only the first three characters of the name string:

#include <stdio.h>

int main() {
    char name[] = "Mario";
    printf("Hello, %.3s!\n", name);
    return 0;
}

The code prints to screen:

Hello, Mar!

Similarly, we can enclose the string in a field, that is print the string in an empty field aligning it to the right. To do this, we need to use the %ms specifier, where m is an integer number representing the field width. For example, the following code prints the name string aligned to the right in a field 10 wide:

#include <stdio.h>

int main() {
    char name[] = "Mario";
    printf("Hello, %10s!\n", name);
    return 0;
}

The code prints to screen:

Hello,      Mario!

In this case the string "Mario" is shorter than 10 characters, so it is aligned to the right in the field. In case the string was longer than 10 characters, the string would be printed normally.

We can also align the string to the left, using the minus sign - before the number representing the field width. For example, the following code prints the name string aligned to the left in a field 10 wide:

#include <stdio.h>

int main() {
    char name[] = "Mario";
    printf("Hello, %-10s!\n", name);
    return 0;
}

The code prints to screen:

Hello, Mario     !

The length specifier, field width and alignment can be combined in the syntax %-m.ps. For example, the following code prints the first three characters of the name string aligned to the left in a field 10 wide:

#include <stdio.h>

int main() {
    char name[] = "Mario";
    printf("Hello, %-10.3s!\n", name);
    return 0;
}

The code prints to screen:

Hello, Mar       !

Recapping:

Definition

Details of the %s format specifier

The general syntax of the %s format specifier is:

%-m.ps
  • -: aligns the string to the left in the field and is optional.
  • m: represents the field width. It is optional.
  • .p: represents the maximum number of characters to print. It is optional.

Printing Strings with the puts Function

There is another function to print strings in C Language, the puts function. This function is defined in the stdio.h library header.

It is much simpler to use compared to printf, but less flexible.

It requires a single parameter of type char *, that is a pointer to a string, and prints the string to screen, automatically adding a newline character at the end.

For example, the following code prints to screen exclusively the name string adding a newline character at the end:

#include <stdio.h>

int main() {
    char name[] = "Mario";
    puts(name);
    return 0;
}

The code prints to screen:

Mario
Definition

Printing Strings with puts

The puts function is used to print strings to screen. It automatically adds a newline character at the end.

To use it, you need to include the stdio.h library header and pass the string as parameter.

puts(string);

The puts function is very convenient for printing strings, but does not allow formatting the string as printf does.

Reading Strings with the scanf Function

Let's see, now, how to read a string from console.

The first library function that allows us to read a string is scanf, also defined in the standard library stdio.h.

scanf wants, as first parameter, a format string just like printf. So, to be able to read a string we can write:

char name[32];
scanf("%s", name);

In this case, scanf reads a string from console and stores it in the name variable. Note that we did not have to use the address operator & in front of the name variable, since the latter is already a pointer to characters, being a string.

scanf, moreover, automatically adds a terminator character '\0' at the end of the read string.

For example, we can write a program that reads a person's name from console and prints it to screen:

#include <stdio.h>

int main() {
    char name[32];
    printf("Enter your name: ");
    scanf("%s", name);
    printf("Hello, %s!\n", name);
    return 0;
}

If we try to compile and run the program, we can enter our name and the program will greet us:

Enter your name: Mario
Hello, Mario!

There is, however, a limitation of scanf: it ignores white spaces (spaces and tabs) before the string and stops at the first white space. This means that if we enter a first and last name, scanf will only read the first name.

For example, if we enter the first and last name Mario Rossi, scanf will only read Mario:

Enter your name: Mario Rossi
Hello, Mario!
Definition

Reading Strings with scanf

The scanf function can be used to read strings from console. To read a string, you need to use the %s specifier.

scanf("%s", string);

It is not necessary to use the address operator & in front of the string variable.

The scanf function automatically adds a terminator character '\0' at the end of the read string.

When using scanf there are limitations:

  • It ignores white spaces before the string.
  • It stops at the first white space or newline character (enter).

Specifying the maximum number of characters to read with scanf

scanf has a problem, as it does not check the length of the entered string. Reason why, if we enter a string longer than the buffer size, scanf overwrites the adjacent memory, causing undefined behavior.

To overcome this problem we can use the format specifier %Ns, where N is an integer number representing the maximum number of characters to read. For example, the following code reads a string of maximum 31 characters:

#include <stdio.h>

int main() {
    char name[32];
    printf("Enter your name: ");
    scanf("%31s", name);
    printf("Hello, %s!\n", name);
    return 0;
}

In this case we used the %31s specifier, which reads at most 31 characters, while the name string can contain at most 32. This is because we must also take into account the terminator character '\0'.

Definition

scanf and maximum number of characters

To specify the maximum number of characters to read with scanf, we can use the %Ns specifier, where N is an integer number.

scanf("%Ns", string);

Reading Strings with the gets Function

To overcome the limitations of scanf, we can use the gets function. This function is defined in the stdio.h library header.

The gets function reads an entire line of text, including white spaces, until it encounters a newline character, that is when the user does not press the enter key. Having done this, it replaces the newline character with the terminator '\0'.

For example, the following program reads a sentence from console and prints it to screen:

#include <stdio.h>

int main() {
    char sentence[128];

    printf("Enter a sentence: ");
    gets(sentence);

    printf("You entered: %s\n", sentence);
    return 0;
}

If we try to compile and run the program, we can enter a sentence and the program will print it to screen:

Enter a sentence: This is a sample sentence.
You entered: This is a sample sentence.
Definition

Reading Strings with gets

The gets function can be used to read an entire line of text from console, including white spaces.

gets(string);

The gets function replaces the newline character with the terminator '\0'.

The gets function is very convenient for reading entire lines of text from console, but has a security problem: it does not check the length of the string it reads. This means that if the user enters a string longer than the buffer size, the function overwrites the adjacent memory, causing undefined behavior.

There are, as we will see, more secure functions for reading strings from console, such as fgets.

Note

Attention to the gets function

The gets function does not check the length of the string it reads.

Reading Strings in a Custom Way

The scanf and gets functions we saw above are not very flexible and have intrinsic security problems. Reason why, many programmers prefer to write their own functions to read strings from console.

In this section we will try, also for educational purposes, to write a custom function to read strings from console.

In designing a function of this type we must consider some aspects:

  1. Whether the function should discard or not the initial white spaces;
  2. Whether the function should read an entire line or just a word;
  3. Whether the function should check the string length;
  4. When the function should terminate reading. For example, whether it should terminate reading at the first white space or at the first newline character.

That said, suppose we want to implement a read_line function that reads an entire line from console and stops at the first newline character.

Moreover, the function checks the maximum string length and returns the number of characters read.

The prototype of this function could be:

int read_line(char *string, int length);

Where string is the pointer to the string in which to store the read characters and length is the maximum string length. The function returns the number of characters read. If the line of text is longer than the maximum length, the function discards the excess characters.

To implement this function we can read character by character from console and store them in the string until we encounter a newline character or reach the maximum length. To do this, we use the getchar function which reads a single character from console.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
int read_line(char *string, int length) {
    int c;
    int i = 0;

    while ((c = getchar()) != '\n' &&
           (c != EOF) &&
           (i < length - 1)) {
        string[i++] = c;
    }

    string[i] = '\0';

    return i;
}

The code works in the following way:

  1. Line 3: We initialize a counter i to zero;
  2. Lines 5-7: We read a character from console until we encounter a newline character, an EOF (End of File) character or do not reach the maximum length minus 1;
  3. Line 8: We store the read character in the string and increment the counter i;
  4. Line 11: We terminate the string with the terminator character '\0';
  5. Line 13: We return the number of characters read.

Note that the type of the read character, ch, is of type int and not char. This is because the getchar function returns an integer. If it were a char the comparison with EOF would not be possible.

In the function we also added the check of the number of characters read, also taking into account the terminator character '\0'.

We can use the read_line function in the following program:

#include <stdio.h>

int read_line(char *string, int length);

int main() {
    char sentence[128];

    printf("Enter a sentence: ");
    read_line(sentence, 128);

    printf("You entered: %s\n", sentence);
    return 0;
}

int read_line(char *string, int length) {
    int c;
    int i = 0;

    while ((c = getchar()) != '\n' &&
           (c != EOF) &&
           (i < length - 1)) {
        string[i++] = c;
    }

    string[i] = '\0';

    return i;
}

In Conclusion

In this lesson we saw how to print and read strings in C Language:

  • We learned to print strings with the printf function using the %s specifier;
  • We saw how to print a portion of a string or align it in a field;
  • We learned to print strings with the puts function;
  • We learned to read strings with the scanf and gets functions;
  • We saw how to read strings in a custom way.

In the next lesson we will see how to access individual characters of a string in C Language.