C String Passing - c

If I am reading a C string such as:
char myData[100];
and I want to process this data and produce a copy out of it, so my code looks like:
char myData[100], processedData[50];
loop
fill myData from file...
setProcessedData(myData, processedData);
store processedData to file...
where setProcessedData is a function that returns a processed string. let's say for simplicity it returns a substring
void setProcessedData (char *myData, char *processedData) {
memCopy( processedData, myData, 5);
}
Is what I am doing something wrong? Like creating extra objects/strings? is there a better way to do it?
Let's say I read string from file which contains *
I am* A T*est String* But Ho*w to Process*.
I want to get substring which has the first 3 s. So my processedData
I am A t*est String*
and I want to do this for all lines of a file as efficient as possible.
Thanks

Problem is that your function is inherently unsafe, this because you make assumption about the allocated memory by parameters you pass to the function.
If someone is going to call setProcessedData by passing a string which is shorter than 5 bytes then bad things will happen.
In addition you are copying memory with memcpy by using a raw dimension, a safer approach, even if it is quite picky in this situation, is to use sizeof(char)*5.
Best thing you can do, though, is to follow the same approach used by safer functions of standard library like strcpy vs strncpy: you pass a third parameter which is the maximum length that should be copied, eg:
void processData(const char *data, char *processedData, unsigned int length) {
memcpy(processedData,data,length*sizeof(char));
}

I think you can improve your code:
Making the input string pointer const (i.e. const char* myData), to mark that myData is an input string and its content is not modified by the function.
Pass the size of the destination buffer, so in your function you can do proper checks and avoid buffer overruns (a security enemy).

Related

Filling a pre-allocated string of fixed size passed as an argument in C

I need to get a fixed length name from a 3rd party developer in a clean way that (hopefully) doesn't require any allocation on their side, and is checked well by the compiler.
I provide a prototype like this:
void getName(char name[9]);
And they would write a function something like this:
void getName(char name[9]) {
strncat(_name, "Hello World", 8);
}
Then I call it (on my side) sort of like this:
char buf[9];
*buf = '\0';
getName(buf);
doSomethingWith(buf);
It compiles and seems to work, but I'm not sure its the best way to handle this.
Any advice?
Edit: To clarify, the name string is used as an identifier in a packed binary save file. It needs to be exactly 8 ASCII 8-bit chars.
I wonder now if I should just receive any string and truncate it on my side. I was hoping the compiler would help instead of this being a runtime check.
In your example, the name is a static string. In this case the function could look like below, where no additional data copy is required:
const char* getName(void)
{
return "Hello World";
}
...
const char* const pName = getName();
Alternatively:
void getName(FUNCPTR func)
{
func("Hello World");
}
where the void func(const char* const pName) is implemented at your side. Then you also don't need to allocate/copy data.
Your first job is to agree the data type of the returned string.
Although it's tempting to use char*, you ought not to since the type of char is not sufficiently well-defined by the standard (could be unsigned, signed 2's complement or signed 1's complement). If you're not careful the behaviour of your program could be undefiend if you mix up your types.
So you ought to decide on a type and use #DEFINE CharType accordingly.
Then as for the function itself, don't rely on the 3rd party to allocate memory unless you call their library to release that memory. Your C runtime might use a different allocation system to theirs. In order to address this common issue, a sort of convention has grown up: if you pass NULL for the output buffer then the 3rd party function should return the length of the buffer required. Then you allocate the memory yourself with the required length, and call the function a second time with the size of the allocated buffer explicitly sent. In that mode, the function returns the length of the allocated string as well as the result populated into the buffer.
Putting this all together, a good prototype would be
SizeType getName(CharType* buffer, SizeType length);
where SizeType is again agreed upon between you and the 3rd party. Broadly speaking, this is how the Windows API works.

Appending individual characters from string onto a char pointer

I'm writing a parser in C, and I've got some code that looks like this:
char *consume_while(parser *self, int(*test)(char)) {
char *result;
while (eof(self) && (*test)(next_char(self))) {
// append the return value from the function consumed_char(self)
// onto the "result" string defined above.
}
return result;
}
But I'm kinda new to the whole string manipulation aspect of C, so how would I append the character returned from the function consumed_char(self) to the result char pointer? I've seen people using the strcat function, but that wont work as it takes two constant char pointers, but I'm dealing with a char* and a char. In java it would be something like this:
result += consumed_char(self);
What's the equivalent in C?
Thanks :)
In C, strings do not exist as a type, they are just char arrays with a null-terminating character. This means, assuming your buffers are big enough and filled with zeroes, it can be as simple as:
result[(strlen(result)] = consumed_char(self);
if not, your best bet is to use strcat and change your consumed_self function to return a char *.
That being said, writing a parser without basic understanding of C-style strings, is, to say the least, quite ambitious.

Copying a string with nulls inside

I want to copy a string in C (Windows) that contains nulls in it. I need a function to which I will pass buffer length so that the NULL characters will be meaningless. I found StringCbCopy function but it still stops at the first NULL character.
Since you know the length, use memcpy().
Here is a quick bit of code that may help:
char array1[5] = "test", array2[5];
int length = 5;
memcpy(array2, array1, length*sizeof(char));
//the sizeof() is redundant in this because each char is a byte long
//but it is useful if you are working with other datatypes
memcpy probably will become your best friend for situations like this.
It should be very easy to write your own function to do this. If you know the length of the string, just create a char[] or char* with the specified length, and copy characters one by one.

string manipulation without alloc mem in c

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.
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.
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.
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)!
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.
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.

Make a copy of a char*

I have a function that accepts a char* as one of its parameters. I need to manipulate it, but leave the original char* intact. Essentially, I want to create a working copy of this char*. It seems like this should be easy, but I am really struggling.
My first (naive) attempt was to create another char* and set it equal to the original:
char* linkCopy = link;
This doesn't work, of course, because all I did was cause them to point to the same place.
Should I use strncpy to accomplish this?
I have tried the following, but it causes a crash:
char linkCopy[sizeof(link)] = strncpy(linkCopy, link, sizeof(link));
Am I missing something obvious...?
EDIT: My apologies, I was trying to simplify the examples, but I left some of the longer variable names in the second example. Fixed.
The sizeof will give you the size of the pointer. Which is often 4 or 8 depending on your processor/compiler, but not the size of the string pointed to. You can use strlen and strcpy:
// +1 because of '\0' at the end
char * copy = malloc(strlen(original) + 1);
strcpy(copy, original);
...
free(copy); // at the end, free it again.
I've seen some answers propose use of strdup, but that's a posix function, and not part of C.
You might want to take a look at the strdup (man strdup) function:
char *linkCopy = strdup(link);
/* Do some work here */
free(linkCopy);
Edit: And since you need it to be standard C, do as others have pointed out:
char *linkCopy = malloc(strlen(link) + 1);
/* Note that strncpy is unnecessary here since you know both the size
* of the source and destination buffers
*/
strcpy(linkCopy, link);
/* Do some work */
free(linkCopy);
Since strdup() is not in ANSI/ISO standard C, if it's not available in your compiler's runtime, go ahead and use this:
/*
** Portable, public domain strdup() originally by Bob Stout
*/
#include <stdlib.h>
#include <string.h>
char* strdup(const char* str)
{
char* newstr = (char*) malloc( strlen( str) + 1);
if (newstr) {
strcpy( newstr, str);
}
return newstr;
}
Use strdup, or strndup if you know the size (more secure).
Like:
char* new_char = strdup(original);
... manipulate it ...
free(new_char)
ps.: Not a C standard
Some answers, including the accepted one are a bit off. You do not strcpy a string you have just strlen'd. strcpy should not be used at all in modern programs.
The correct thing to do is a memcpy.
EDIT: memcpy is very likely to be faster in any architecture, strcpy can only possibly perform better for very short strings and should be avoided for security reasons even if they are not relevant in this case.
You are on the right track, you need to use strcpy/strncpy to make copies of strings. Simply assigning them just makes an "alias" of it, a different name that points to the same thing.
Your main problem in your second attempt is that you can't assign to an array that way. The second problem is you seem to have come up with some new names in the function call that I can't tell where they came from.
What you want is:
char linkCopy[sizeof(link)];
strncpy(linkCopy, chLastLink, sizeof(link));
but be careful, sizeof does not always work the way you want it to on strings. Use strlen, or use strdup.
Like sean.bright said strdup() is the easiest way to deal with the copy. But strdup() while widely available is not std C. This method also keeps the copied string in the heap.
char *linkCopy = strdup(link);
/* Do some work here */
free(linkCopy);
If you are committed to using a stack allocated string and strncpy() you need some changes. You wrote:
char linkCopy[sizeof(link)]
That creates a char array (aka string) on the stack that is the size of a pointer (probably 4 bytes). Your third parameter to strncpy() has the same problem. You probably want to write:
char linkCopy[strlen(link)+1];
strncpy(linkCopy,link,strlen(link)+1);
You don't say whether you can use C++ instead of C, but if you can use C++ and the STL it's even easier:
std::string newString( original );
Use newString as you would have used the C-style copy above, its semantics are identical. You don't need to free() it, it is a stack object and will be disposed of automatically.

Resources