C - Some Simple Examples of using strcat

16. February 2013 11:06

 

This post shows some simple example of using strcat to join two strings together in C

 

The msot common example you will find on the internet will work by just making an array that is "big enough" to store both the strings. However this can create problems when the strings you use are too long so it would need these conditions handled correctly in C. So it probably isn't the best example to use.

 

 

void basic(char *s1, char *s2)
{
	char str[200] = "";
	
	strcat(str, s1);
	strcat(str, s2);
	printf("basic: %s\n", str);
}

 

 

A better example of using strcat is to allocate an array dynamically. In this case on the stack. So this will work slightly better however it can cause a significant amount of stack space to be used and can also cause crashes if the strings are too long. However it will execute very quickly because dynamic allocation of memory on the stack will perform well.

 

 

void better1(char *s1, char *s2)
{
	char str[strlen(s1) + strlen(s2) * sizeof(*s1) + 1];
	str[0] = '\0';

	strcat(str, s1);
	strcat(str, s2);
	printf("basic: %s\n", str);
}

 

 

A much better example of this is to use malloc / free for the allocation of string. This will be slightly slower than the previoud example but will be able to handler much larger strings and much safer to use. It can of course still crash but only if the machine run's out of memory. How ever this error can be handled to prevent it crashing by changing the call to abort() to use proper error handling.

 

 

void better2(char *s1, char *s2)
{
	char *str = malloc(strlen(s1) + strlen(s2) + 1 * sizeof(*s1));
	if (str == NULL)
		abort();
	str[0] = '\0';
	
	strcat(str, s1);
	strcat(str, s2);
	printf("basic: %s\n", str);
		
	free(str);
}

 

Finally this is an example about joining multiple strings so we can just keep making our string longer and longer or join it from multiple different sources. Note that the following code really needs a check around the realloc function to see if it returns NULL. If it does then it should fail by returning the previous pointer. Or call abort because the system has run out of memory.

 

 

char *multiple(char *str, char *s2)
{
	int len;
	char *s;
	if (str != NULL)
		len = strlen(str);
	len += strlen(s2) + 1 * sizeof(*s2);
	s = realloc(str, len);
	strcat(s, s2);
	return s;
}

 

With the above code we can call it in the following way

 

 

char *tmp = multiple(NULL, "Hello ");
	tmp = multiple(tmp, " World");
	tmp = multiple(tmp, " We");
	tmp = multiple(tmp, " Can");
	tmp = multiple(tmp, " Join");
	tmp = multiple(tmp, " strings");
	printf("%s\n", tmp);
	free(tmp);

 

E-mail Kick it! DZone it! del.icio.us Permalink


HowTo Override malloc / free in c

3. November 2012 08:56

 

This is a short guide on how to override malloc / free in C/C++ on linux so that custom tracing / logging can be used on the functions to detect double free's

 

It is actually very simple to do. All you require is a short program that is compiled into a shared lib. Then this lib is pre loaded before your program loads and instead of binding to the libc functions it will bind to the ones in the lib.

 

 

#include <stdio.h>
#include <dlfcn.h>

extern void abort();

void *malloc(int size) {
        void * (*ptr)(int);
        void * handle = (void*) -1;
        ptr = (void *) dlsym(handle, "malloc");
        if (ptr == NULL) {
                printf("Opps\n");
                abort();
        }
        void *alloc = (*ptr)(size);
        printf("Alloc = %p Size: %d\n", alloc, size);
        return alloc;
}

void *realloc(void *alloc, int size) {
        void * (*ptr)(void *, int);
        void * handle = (void*) -1;
        ptr = (void *) dlsym(handle, "malloc");
        if (ptr == NULL) {
                printf("Opps\n");
                abort();
        }
        alloc = (*ptr)(alloc, size);
        printf("Realloc = %p Size: %d\n", alloc, size);
        return alloc;
}

void free(void *alloc) {
        if (alloc == NULL)
                return;
        printf("free %p\n", alloc);
        void * (*ptr)(void *);
        void * handle = (void *) -1;
        ptr = (void *) dlsym(handle, "free");
        if (ptr == NULL)
                abort();

        (*ptr)(alloc);
}

 

 

You can compile the above with the following command

 

gcc -Wall sample.c -fPIC -shared -o libsample.so -lc -ldl

 

Then set the LD_LIBRARY_PATH= so that it includes the path to the location that the libsample.so is in.

 

Then set the LD_PRELOAD=libsample.so which will tell the dynamic lib loader to load that library first.

 

Then you can simply run your program.

E-mail Kick it! DZone it! del.icio.us Permalink


Linux Programming - Using inotify for detecting file modifications

22. September 2012 09:21

 

This is a short introduction to using the inofity api in linux to detect file system modifications for specific files. Which can be useful for a number of reasons. The particular reason why I wrote the example program here was to reload parts of apache when python scripts were being modified while doing some web development. the problem being that apache + django caches the python files.

 

The example here is simple. It will take a file list to monitor and will then execute a command when one of thoose files are modified. Though it also shows a simple example of how to use the inofity api in linux.

 

To start with you will need to get a suitable file descriptor by calling inotify_init and then setup the files you would like to monitor you can do this by using the function inotify_add_watch with the correct arguments to be notified when files changes. See below for the first half of the program. Note that the program expects the file list to be passed on the command line.

 

int main(int argc, char **argv) {
	int fdnotify = -1;
	int i;

	fdnotify = inotify_init();
	if (fdnotify < 0) {
		fprintf(stderr, "inotify_init failed: %s\n", strerror(errno));
		exit(-1);
	}

	for(i = 2;i<argc;i++) {
		int wd = inotify_add_watch(fdnotify, argv[i], IN_MODIFY);
		if (wd < 0) {
			fprintf(stderr, "inotify_add_watch failed: %s\n", strerror(errno));
		}
	}

 

Once the initial list has been completed you just need to wait for a notification which is done by reading from the file decriptor with the inotify_event data structure and just keep reading from that file descriptor in a loop.

 

while(1) {
		char buffer[4096];
		struct inotify_event *event = NULL;
		int exec = 0;

		int len = read(fdnotify, buffer, sizeof(buffer));
		if (len < 0) {
			fprintf(stderr, "read: %s\n", strerror(errno));
			exit(-1);
		}

		event = (struct inotify_event *) buffer;
		while(event != NULL) {
			if ( (event->mask & IN_MODIFY) && event->len > 0) {
				printf("File Modified: %s\n", event->name);
				exec = 1;
			} else {
				printf("Unknown Mask 0x%.8x\n", event->mask);
			}
				
			/* Move to next struct */	
			len -= sizeof(*event) + event->len;
			if (len > 0)
				event = ((void *) event) + sizeof(event) + event->len;
			else
				event = NULL;
		}
	
		if (exec)	
			system(argv[1]);
	}

And that is really it. Note that I wanted to "eat" most of the file notification events before running the external script so that it would only execute the script once. It can also serve other nice purposes eg it can be used to auto rebuild a c project on the file by using it like this "./inotify make `find . -type f -name '*.[ch]'" which will run make any time any of the .c, .h files change. the program has 100's of useful ways to be used for being able to trigger shell scripts from filesystem events.

 

Here is a copy of the full program

 

 

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

#include <sys/inotify.h>

void printhelp(FILE *out, char *app) {
	fprintf(out, "Usage: %s <command> <dirs to watch>\n", app);
}

int main(int argc, char **argv) {
	int fdnotify = -1;
	int i;

	fdnotify = inotify_init();
	if (fdnotify < 0) {
		fprintf(stderr, "inotify_init failed: %s\n", strerror(errno));
		exit(-1);
	}

	if (argc < 3) {
		fprintf(stderr, argv[0]);
		exit(-1);
	}

	for(i = 2;i<argc;i++) {
		int wd = inotify_add_watch(fdnotify, argv[i], IN_MODIFY);
		if (wd < 0) {
			fprintf(stderr, "inotify_add_watch failed: %s\n", strerror(errno));
		}
	}

	while(1) {
		char buffer[4096];
		struct inotify_event *event = NULL;
		int exec = 0;

		int len = read(fdnotify, buffer, sizeof(buffer));
		if (len < 0) {
			fprintf(stderr, "read: %s\n", strerror(errno));
			exit(-1);
		}

		event = (struct inotify_event *) buffer;
		while(event != NULL) {
			if ( (event->mask & IN_MODIFY) && event->len > 0) {
				printf("File Modified: %s\n", event->name);
				exec = 1;
			} else {
				printf("Unknown Mask 0x%.8x\n", event->mask);
			}
				
			/* Move to next struct */	
			len -= sizeof(*event) + event->len;
			if (len > 0)
				event = ((void *) event) + sizeof(event) + event->len;
			else
				event = NULL;
		}
	
		if (exec)	
			system(argv[1]);
	}

	return 0;
}

E-mail Kick it! DZone it! del.icio.us Permalink


Doing for loops in bash

9. May 2012 23:21

 

It can be commonly known that you can do for loops in bash by doing something like for i in * ; do echo $i ; done or some such. This will loop for every file in the current directory. Though typical for loops for a specific number range can be a little more difficult since you need to form the data to be able to execute the loop.

 

To get a simple for loop to work we can copy python's for i in range(x, y): type of loop since the bash for loop is exactly the same as this. Both bash / python perform a for each loop around a list of data items rather than the traditional for loop with a counter. This can be used to our advantage since all you need to do is create a small program that generates this data lists.

 

The following c program does this.

 

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

void print_usage(FILE *fp, char *app) {
    fprintf(fp, "Usage: %s <start number> <end number>\n", app);
    fprintf(fp, "\n");
}

int main(int argc, char **argv) {
    int a = 0, b = 0;
    int i;

    if (argc < 3) {
        print_usage(stderr, argv[0]);
        exit(EXIT_FAILURE);
    }

    a = atoi(argv[1]);
    b = atoi(argv[2]);
    
    if (a >= b) {
		int tmp = a;
		b = a;
		a = tmp;
    }

    for(i=a;i<=b;i++) {
        printf("%d\n", i);
    }

    return 0;
}

All you need to do is put the program above into a c file and compile it with gcc (gcc -Wall range.c -o range) and place the executable on the path (eg in $HOME/bin). Then you can do for loops in the bash shell the following way.

 

for i in `range 0 20` ; do echo $i ; done

The above will of course produce the output of 0 to 20 on the terminal when run.

 

E-mail Kick it! DZone it! del.icio.us Permalink


C/C++ - Generate a random number

19. April 2012 21:57

 

This is a short example for generating a random number in C/C++. It is actually easy to do. In this case we can produce a random number between 0 and 10 and print it out.

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


int main(int argc, char **argv) {

	srand(time(NULL));

	for(int i =0;i<10;i++) {
		int r = rand() % 10;
		printf("%d\n", r);
	}

	return 0;
}

 

The solution above will only work for generating a number from 0 to RAND_MAX which is typically 32768.

E-mail Kick it! DZone it! del.icio.us Permalink