STLplus C++ Library Collection - strings/string_utilities.hpp - String Handling and Formatting Functions
Author: Andy Rushton

# STLplus C++ Library Collection

Website Collection

# strings/string_utilities.hpp
String Handling and Formatting Functions

- Browse Header string_utilities.hpp
- Padding Function
- Trimming Functions
- Character Translating Function
- Case Changing Functions
- Split and Join Functions
- Special Displays for Bytes and Seconds

## Introduction

This header contains a small collection of general-purpose string processing utility functions which provide simple interfaces to common transformations.

## Padding Function

    std::string stlplus::pad(const std::string& str, stlplus::alignment_t alignment, unsigned width, char padch);

The pad function allows a string to be aligned in a fixed-width field. This is controlled by an enumeration of type stlplus::alignment_t which specifies how the string is to be aligned within the field. It has the following values:

stlplus::align_left
  aligns the string to the left hand side of the field
stlplus::align_right
  aligns the string to the right hand side of the field
stlplus::align_centre
  aligns the string to the centre of the field

If the field is not wide enough, the string is not truncated, it will be simply printed in full but with no padding.

## Trimming Functions

    std::string stlplus::trim_left(const std::string& val);
    std::string stlplus::trim_right(const std::string& val);
    std::string stlplus::trim(const std::string& val);

The trim functions trim whitespace from the argument. The names are fairly self-explanatory - trim_left trims whitespace from the left of the string, trim_right from the right of the string and trim trims whitespace from both ends of the string. Whitespace is defined by the isspace function from <ctype.h>.

## Case Changing Functions

    std::string stlplus::lowercase(const std::string& val);
    std::string stlplus::uppercase(const std::string& val);

The lowercase and uppercase functions are pretty self evident. Note that they do not modify their arguments, but return a new string which has been case-converted.

## Character Translation Function

    std::string stlplus::translate(const std::string& input, const std::string& from_set, const std::string& to_set);

This function was inspired by the 'tr' function from Unix. It processes the input string to generate the return string by replacing any character in the from_set with the character in the same position in the to_set. In other words, if a character in the input string is found at index 17 of the from_set, the returned string will contain the character in index 17 of the to_set. If the to_set is smaller than the from_set, then the extra characters represent characters to delete - in other words they map onto nothing. If a character is not present in the from_set, it will be copied to the output unchanged.

For example:

    std::string result = stlplus::translate("fred123.txt", "abcdefghijklmnopqrstuvwxyz01234567890", "ABCDEFGHIJKLMNOPQRSTUVWXYZ");

This example will convert lowercase letters to uppercase letters. It will delete digits (the from_set is longer than the to_set) and copy anything else unchanged to the output. The result string will therefore be "FRED.TXT".

## Split and Join Functions

There are two functions in the Perl language which are incredibly useful for string manipulation, and which I therefore wanted in C++. These are the split and join functions. Basically the split function converts a string into a vector of strings by splitting the string at every occurrence of a splitter string. For example, a PATH can be split into its elements by splitting with ":" on Unix or ";" on Windows (see the file_system subsystem for a platform-independent interface for this, but yes it does use split internally). The reverse function is join, which converts a vector of strings into a single string by interleaving with a joiner string.

The function interfaces are:

    std::vector<std::string> stlplus::split (const std::string& str, const std::string& splitter = "\n");
    std::string stlplus::join (const std::vector<std::string>&, const std::string& joiner = "\n", const std::string& prefix = "", const std::string& suffix = "");

Note that the split function considers the start and the end of the string to be split points. It searches from the current split point to the next split point and adds the intervening text to the vector. It follows that if the splitter appears at the beginning or end of the string, an empty string will be added to the vector. Similarly, if two instances of the splitter appear consecutively in the string, an empty string will be added to the vector. This is correct behaviour, not a bug!

Note also that the join function allows you to add a prefix and a suffix to the resulting string, so for example a vector of values could be turned into a parenthesised, comma-separated string by a single call which sets the joiner=",", prefix="(" and suffix=")".

Another neat use of these functions is in converting one separator into another by nesting the calls. For example, to convert a colon-separated string into a comma-separated string, simply split and then join:

    std::string value = "a:b:c:d:e";
    std::string result = stlplus::join(stlplus::split(value,":"),",");

## Special Displays for Bytes and Seconds

There are two functions for displaying either a byte-count or an elapsed time in seconds in a human-readable form.

    std::string stlplus::display_bytes(unsigned bytes);

This creates a string representation of the number of bytes, represented as a number in B, kB, MB or GB depending on the value. It is approximate in that the result is rounded to a sensible number of digits.

    std::string stlplus::display_time(unsigned seconds);

This function displays the parameter in seconds as a string representation in weeks, days, hours, minutes, seconds. For example, "4d 3:02:01" means 4 days, 3 hours, 2 minutes and 1 second.