tags:

views:

92

answers:

5

I'm wondering if there is another way of getting a sub string without allocating memory. To be more specific, I have a string as:

const char *str = "9|0\" 940 Hello";

Currently I'm getting the 940, which is the sub-string I want as,

char *a = strstr(str,"9|0\" ");
char *b = substr(a+5, 0, 3); // gives me the 940

Where substr is my sub string procedure. The thing is that I don't want to allocate memory for this by calling the sub string procedure.

Is there a much easier way?, perhaps by doing some string manipulation and not alloc mem.

I'll appreciate any feedback.

+1  A: 

Try this:

char *mysubstr(char *dst, const char *src, const char *substr, size_t maxdst) {
    ... do substr logic, but stick result in dst respecting maxdst ...
}

Basically, punt and let the caller allocate space on the stack via:

char s[100];

Or something.

xyld
Defining a variable on the stack is still allocating memory, albeit with automatic storage class.
Tyler McHenry
@tyler personally, I think you're over estimating what mike is asking for... To not allocate **anything** is rather harsh, can't program much with something like that. To not **allocate dynamically** is more likely IMO. A library that does zero **dynamic allocation** can be more faithful when it comes to memory leaks as its far less likely... Again... IMO
xyld
It turns out that I was overestimating based on his comment, but it's not so bizarre a request. It seems logical that if you have data already stored in memory, you should be able to reference a part of what's already in memory instead of having to allocate new memory and make a copy of part of what is already stored. The fact that this is impossible in this case is just a consequence of the C convention for NUL terminated strings, and a new programmer may not realize this.
Tyler McHenry
+2  A: 

No, it can't be done. At least, not without modifying the original string and not without departing from the usual C concept of what a string is.

In C, a string is a sequence of characters terminated by a NUL (a \0 character). In order to obtain from "9|0\" 940 Hello" the substring "940", there would have to be a sequence of characters 9, 4, 0, \0 somewhere in memory. Since that sequence of characters does not exist anywhere in your original string, you would have to modify the original string.

The other option would just be to use a pointer into the original string at the place where your desired substring starts, and then also remember how long your substring is supposed to be in lieu of having the terminating \0 character. However, all C standard library functions that work on strings (and pretty much all third party C libraries that work with strings) expect strings to be NUL-terminated, and so won't accept this pointer-and-count format.

Tyler McHenry
I don't see why he can't allocate room on the stack and write his own substr procedure?
xyld
He said that he did not want to allocate new memory at all, not just that he didn't want to allocate new memory on the heap. Plus, stack-allocation will not be sufficient if the substring requires a lifetime beyond the current scope.
Tyler McHenry
@tyler very true, but I guess I simply thought that he was referring to substr()'s dynamic allocation... maybe I inferred too much...
xyld
@xyld yes I meant dynamic allocation
Mike
A: 

A C string is simply an array of chars in memory. If you want to access the substring without allocating a copy of the characters, you can simply access it directly:

char *b = a[5];

The problem with this approach is that b will not be null-terminated to the appropriate length. It would essentially be a pointer to the string: "940 hello".

If that doesn't matter to the code that uses b, then you are good to go. Keep in mind, however, that this would probably surprise other programmers later on in the product lifetime (including yourself)!

e.James
A: 

As xyld, suggested, you could let the caller allocate the memory and pass your substr function a buffer to fill; though, strictly speaking, that still involves "allocating memory".

Without allocating any memory at all, the only way you'd be able to do this would be by modifying the original string by changing the character after the substring to a '\0', but of course then your function couldn't take a const char * anymore, and you're modifying the original string, which may not be desirable.

Nick Meyer
A: 

If you don't require a \0 terminated string you can make a substring finding function that just tells you where in the full string (haystack) your partial string (needle) is. This would be considered a hot-copy or alias as the data could be changed by changes to the full string (haystack).

I was writing up a long thing on how to allocate memory using alloca and implement a macro (because it wouldn't work as a function) that would do what you want, but just happened to run across strndupa which is like strndup except allocates the memory on the stack rather than from the heap. It's a GNU extension, so it might not be available for you.

Writing your own macro that would look like a function because it needs to return a value but also work on the memory, but it is possible.

nategoose