Tutorial 14 – Working with strings in C

This is the fourteenth tutorial in the series Online C Tutorials for beginners and is about working with strings in C. These tutorials are single page bite size tutorials which can usually be run on either codepad.org or ideone.com.

Strings in C

If you were picking a programming language to work with strings, I wouldn’t start with C. Programming languages like Java, C# and Python and C++ have much more powerful string-handling capabilities. You can do stuff with text using c-Strings; it takes more effort though and can lead to bugs if you aren’t careful.

A c-string is a block of RAM that terminates with a 0 value, denoted as ‘\0’ in C. So if a string has four characters in it, it actually occupies five bytes. Forgetting this can lead to bugs.

char * name="Dave"; // name occupies five bytes Dave + 
char * name="Dave"; // name occupies five bytes Dave + \0

So what can be do with strings?

Here’s a list of things. I’ll give examples for each item in the list.

  1. Assign a string.  (Example above)
  2. Copy one string onto another.
  3. Append one string on to the end of another.
  4. Convert numbers to strings.

Copy one string onto another

So we have our string name which has the value Dave in it. Now lets copy it into another string.

Remember, a string is a block of RAM. It can be allocated statically at compile-time, or dynamically at runtime.

Here’s the static version. I’ve allocated a buffer of 20 chars.

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

char buffer[20];
char* name = "Dave";
int main(){
	strcpy_s(buffer,sizeof(buffer), name);  // Win 32
	//strncpy(buffer, name, sizeof(buffer));  // Linux
	printf("Copied string - %s\n", buffer);
}

This copies all five characters of name into buffer. Note I’ve used the safe versions (strcpy_s on Windows, strncpy on Linux) of strcpy. You might see older code using strcpy but if the string being copied doesn’t have a terminating 0 then strcpy will keep on copying until it finds a \0. If there isn’t a \0 at the end of the string strcpy could copy several hundred or thousand bytes and will clobber data and possibly code.

Here’s the dynamic version.

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

char* destination;
char* name = "Dave";
int len = 50;

int main(){
	destination = (char*)malloc(len);
	if (!destination) {
		printf("Unable to allocate %d bytes",len);
		return 1;
	}
	strcpy_s(destination, len, name);  // Win 32
	//strncpy(destination, name, len); // Linux
	printf("Copied string - %s\n", destination);
	free(destination);
}

This is a bit longer because I’ve checked the malloc() call to ensure it did allocate ram. It’s good practice to always do this and bail out if it fails. Otherwise it’s more or less identical. Most of the string functions that copy, append etc use this destination and source pointer parameters. These are always pointers but can also be the name of an array or the address of an array element.

For instance in the static example, if I wanted to copy name into buffer starting at the fifth byte, it would look like this.

strcpy_s(&buffer[4],sizeof(buffer), name);

You could put replace buffer with &buffer[0] but why would you. Simpler is best!

Windows vs Linux

It was found pretty quickly that the strcpy() and similar functions were not very safe. So safe versions of these were devised. Microsoft went for the _s versions. Linux went for the strn versions. Both added an extra parameter which specifies the maximum length of the destination. Confusingly Windows has the extra parameter as the 3rd while Linux makes it the second.

Append one string on to the end of another

This is very similar to the safe strcpy() examples but instead uses safe versions of strcat(). So first copy one string with strcpy_s then use strcat_s to append to it.

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

char* destination;
char* name = "Dave ";
char* append = "was here";
int len = 50;

int main(){
	destination = (char*)malloc(len);
	if (!destination) {
		printf("Unable to allocate %d bytes",len);
		return 1;
	}
	strcpy_s(destination, len,name );
	strcat_s(destination, len, append); 
	printf("Appended string - %s\n", destination);
	free(destination);
}

I’ve not put the array version in.

Convert numbers to strings

You’ll occasionally see reference to a function itoa. This exists in Visual C++ as _ltoa_s but does not in Linux.  Here’s what it looks like in Windows.

#include <stdio.h>
#include <stdlib.h>

int len = 50;
char buffer[50];

int main(){

	_ltoa_s(1250,buffer,len,10);
	printf("value = %s\n", buffer);
}

This is the Linux version.

#include <stdio.h>
#include <stdlib.h>

int len = 50;
char buffer[50];

int main(){
	int value = 1250;
	snprintf(buffer,len,"%d", value);
	printf("Value=%s\n",buffer);
}

The snprintf (safe version of sprintf) prints the number to the string into buffer. You can then printf buffer out in the last line. I’ve used an int value but float or double with the appropriate format string works as well.

Conclusion

String handling in C is certainly doable but its quite fiddly and it’s very easy to introduce bugs.

(Visited 11 times, 1 visits today)