char * capitalize(char *dest, const char *src)
{ int i;
for( i = 0 ; src[i] != '\0' ; ++i )
dest[i] = LOWER(src[i]);
dest[i] = '\0';
dest[0] = UPPER(dest[0]);
return dest;
}
char *name[MSL];
capitalize(name, ch->name); //name will now be capitalized.
sprintf("%s", capitalize(tmp, ch->name) )
$ cat memtest.c
#include <stdio.h>
#include <malloc.h>
#define HUNK 1024*1024*1024
main(){
void* ptr;
printf("No memory allocated yet. Check procps now.\n");
printf("Hit any key to continue\n");
getchar();
ptr = malloc(HUNK);
printf("%d memory allocated. Check procps now.\n",HUNK);
printf("Hit any key to continue\n");
getchar();
free(ptr);
printf("All memory freed. Check procps now.\n");
printf("Hit any key to continue\n");
getchar();
}
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
// method 1
// return pointer to static string
//
// non-reentrant, fixed length limits, no housekeeping
char * capitalize_1(char const* src) {
static char dst[32768];
int i = 0;
0[dst] = '\0';
while (i[src]) {
if (i == 0)
i[dst] = toupper(i[src]);
else
i[dst] = i[src];
i++;
}
i[dst] = '\0';
return dst;
}
// method 2
// modify string in place
//
// reentrant, caller must preserve string if desired
char * capitalize_2(char * src) {
if (strlen(src) > 0)
*src = toupper(*src);
return src;
}
// method 3
// return new string
//
// reentrant, caller must free string
char * capitalize_3(char const* src) {
int i = 0;
size_t len = strlen(src);
char * dst = (char *) malloc(len + 1);
0[dst] = '\0';
while (i[src]) {
if (i == 0)
i[dst] = toupper(i[src]);
else
i[dst] = i[src];
i++;
}
i[dst] = '\0';
return dst;
}
// method 4
// copy string
//
// reentrant, caller must provide allocated string
char * capitalize_4(char * dst, char const* src) {
int i = 0;
0[dst] = '\0';
while (i[src]) {
if (i == 0)
i[dst] = toupper(i[src]);
else
i[dst] = i[src];
i++;
}
i[dst] = '\0';
return dst;
}
int main() {
char a[6] = "hello";
char b[6] = "hello";
char * sptr;
printf("1: %s %s\n",a, capitalize_1(a));
printf("2: %s ",a);
printf("%s\n", capitalize_2(a));
sptr = capitalize_3(b);
printf("3: %s %s\n",b, sptr);
free(sptr);
sptr = (char *) malloc(strlen(b) + 1);
printf("4: %s %s\n",b, capitalize_4(sptr, b));
free(sptr);
return 0;
}
#include <stdio.h>
#include <ctype.h>
// method 5
// safer than method 4
//
char * capitalize_5(char * dst, size_t dst_sz, const char * src, size_t src_sz) {
size_t i = 0;
while (i < src_sz && i < dst_sz) {
if (i == 0)
i[dst] = toupper(i[src]);
else
i[dst] = i[src];
i++;
}
dst[dst_sz-1] = '\0';
return dst;
}
// method 6
// safer than method 4 - uses iterator concept
//
char * capitalize_6(char * dst, char * dst_end, const char * src, const char * src_end) {
char * dptr = dst;
const char * sptr = src;
while (dptr < dst_end && sptr < src_end) {
if (sptr == src)
*dptr = toupper(*sptr);
else
*dptr = *sptr;
sptr++;
dptr++;
}
*(dst_end-1) = '\0';
return dst;
}
#define MSL 256
int main() {
char src[MSL] = "hello";
char dst[MSL];
printf("5: %s %s\n",src, capitalize_5(dst, MSL, src, MSL));
printf("6: %s %s\n",src, capitalize_6(dst, dst+MSL, src, src+MSL));
return 0;
}
I'm having some difficulty deciding on the sort of method to use for storing the results of string utility functions for returning to their callers, so I'd like to solicit some input on the matter. What I'm speaking of are functions used to perform some operation on an input string, then put the result into an allocated buffer of some sort and return it.
For instance, suppose you have a function "capitalize" which takes a string, capitalizes the first character, puts the result into a buffer and then returns a pointer to the buffer. The problem lies in what sort of storage to use for the buffer. Traditionally, the way I've seen it done is to use a static char buffer of a defined size within the function. The problem I have with that method is that I'm looking to have my string infrastructure become mostly/fully limitless; where in terms of string utility functions means that they need to handle strings of any size. The other shortcoming of that method is that you also can't perform repeat calls of that function within a single function call elsewhere; doing so causes the output to get screwy. I.e, if you tried to do "example_printf( thing, "%s %s", capitalize( ex1 ), capitalize( ex2 ) );" it would break. To fix the problem you're forced to break the format into multiple lines, calling the function in question only once per call.
What I'm looking for is a good, hopefully quick, method of getting both things I'm looking for accomplished. I.e, the function can store strings of any size, and can be called in succession without corrupting the output. There are a number of ways I've thought of for handling this, with varying results (potential or otherwise).
One method I've thought of, which is currently set in the code awaiting a better replacement, is to use a static pointer to an allocated buffer that is expanded as needed, with the input placed into the buffer and the pointer returned. This fulfills the requirement of being able to handle strings of any size, but not of allowing the function to be called in direct succession. As a side note, for efficiency sake the buffers are allocated to a somewhat large default size in an effort to cut down on the number of times they would need to be expanded. In theory, most uses of the function would be under the limit so it would not need to be expanded very often, but when the need arises for such the function would be able to handle it.
A second method I've thought of, which I'm only just thinking about for the time being, would be to create a system of disposable strings which are allocated every time the function in question is called, and then disposed of at some later point; likely at the end of the main game loop to try and ensure that the functions are out of scope and nothing will break from freeing the strings. This would likely solve both problems, but the thing that gives me pause in implementing such a system is the potential overhead that could be incurred from having allocations performed so many times (assuming conditions where the functions are being called often).
One of the impressions I've gotten so far from the use of static buffers within string utility functions is that it is designed to cut down on allocations and thus speed things up considerably. What I'm trying to decide is whether or not that desire is particularly relevant these days considering the speed and capabilities of today's computers. I've brought up similar points a number of times, and I can't help but wonder if this is another instance of where the benefit to the form and function of the code outweighs the potential additional CPU/RAM usage. If it is, I find that I'm leaning towards the idea of using something along the lines of the second method described.
Anyhow, some ideas, advice, etc on the matter would be appreciated. :thinking: