8.3. Safe Additions to Strings¶
As mentioned in Dangers of Buffer overflows, adding textual data to a string is dangerous. It is not very difficult to work with strings safely, but it does require extra effort and needs topics that we covered toward the end of the course. In particular, dynamic memory allocation, data structures, and file input / output need to be used along with the functions from The string library.
A library of functions is helpful. There are actually several open source
string libraries for C. This article compares some popular string
processing libraries.
Many of these libraries are quite large and go well beyond safely adding
data to strings. So to keep things simple, I wrote a modest set of functions
to avoid string buffer overflows and truncations. The code is in the
textstring.h
file, which can be added to your code with an include
statement.
#include "textstring.h"
Declare a pointer to a data structure along with a starting string length as follows:
txtstr *str;
str = tstr_new(LINESIZE);
Then use functions defined below to store data to str in various ways.
To avoid conflicts with your name space, all functions in the library begin
with tstr_
.
To access the string to print it or any other char * string operations,
use either:
char *ptr = tstr_str(str);
- or -
char *ptr = str->string;
The tstr_str
function resets the string to the beginning, which impacts
future string appending functions.
To avoid memory leaks when finished with a string, especially in a function other than main, use:
tstr_free(str);
- tstr_new
Allocate an new txtstr with a given size:
txtstr *tstr_new(int); str = tstr_new(200);
- tstr_ReadLine
Same as String Example - ReadLine, except the lines go to a
txtstr *
data structure. Read atxtstr
line from a file:bool tstr_ReadLine(txtstr *, FILE *); // str is a new line from the file on each loop iteration. // End of file is reached when false is returned. while( tstr_ReadLine(str, fileptr) )
- tstr_sprintf
Safe sprintf() into a txtstr. New string starts at the beginning of the str->string. Formatting is the same as the standard
printf
andsprintf
functions. Multiple data variables may be referenced:int tstr_sprintf(txtstr *, const char *, ...); tstr_sprintf(str, "V = %lf, and a string\n", V, str2);
- tstr_strappend
Formatted append a
char *
string to an existingtxtstr
. Note, the format string may contain text, but only one string is added. Onlytstr_sprintf
has the formatting functionality ofsprintf
:int tstr_strappend(txtstr *str, const char *fmt, char *s2); tstr_strappend(str, "adding a string: %s\n", s2)
- tstr_append
Formatted append
txtstr
to existingtxtstr
. This function is liketstr_strappend
except the string to add is in atxtstr *
data structure, not achar *
string:int tstr_append(txtstr *str1, const char *fmt, txtstr *str2);
- tstr_cat
Safe strcat of
txtstr``s. Contents of ``s2
is added to the end ofs1
:void tstr_cat(txtstr *s1, txtstr *s2);
- tstr_strcat
Safe strcat for a
char *
string:void tstr_strcat(txtstr *str, char *s2);
- tstr_cpy
Safe strcpy of
txtstr
.s2
is copied tos1
:void tstr_cpy(txtstr *s1, txtstr *s2);
- tstr_strcpy::
Safe copy of
char *
string into atxtstr
. Thes2
string is copied to thes1
data structure:void tstr_strcpy(txtstr *s, char *);
- tstr_str::
Return string for printing or other use and reset so string is empty:
char *tstr_str(txtstr *str); printf("%s\n", tstr_str(str));
- tstr_reset::
Reset the
txtstr
so that the string is empty. Future appends go the beginning of the string:void tstr_reset(txtstr *);
- tstr_free
Free the memory held by a
txtstr
. It is important to remember this to avoid memory leaks:void tstr_free(txtstr *str);
Here is the include file that may be downloaded. Testing and example code is also available for download.