I need some clarification about sprintf() and array[] - c

char buff[10]={0};
char buff1[6]="xxxxx";
sprintf(buff,"My name is %s");
is this a correct array initialization for buff (ie.10)? or I need to initialize with 17.

If you're going to write over it with sprintf then it doesn't need to contain anything in particular, it just needs to be large enough to hold the data.
In other words the = {0} is sufficient, and actually optional in this case.
PSA: DO NOT USE functions like sprintf that are missing a length argument. Instead use snprintf and related functions where there is a length argument. Buffer overflow bugs are a huge problem in C if you do not take proper precautions.
The code you should have in C is roughly:
size_t buff_size = 255;
char buff[buff_size];
char* name = "Aadhi";
snprintf(buff, buff_size, "My names is %s", name);
Where that contains not only a placeholder argument but, importantly, the value that should be used.
In C++ you should skip this entirely and instead:
std::string name = "Aadhi";
std::string message = "My name is " + name;
Where std::string avoids almost all of the problems with buffer overflow bugs.
C++ 20 introduces a new std::format feature which works an awful lot like sprint but without all the buffer overflow issues:
std::string name = "Aadhi";
std::string message = std::format("My name is {}", name);

Related

Using a char* or a char array for strings within a struct

If I have the following pseudocode for a struct I would like to implement in C (for a text editor):
STRUCT line
STRING line_contents
INT line_length
END
Is there a best practice for how I write my strings? I see two options:
struct line {
char* line_contents;
size_t line_length;
};
or...
#define MAX_LINE_LENGTH 1024 // Some arbitrary number
struct line {
char line_contents[MAX_LINE_LENGTH];
size_t line_length;
};
The first one has the drawback of leaving the programmer with manual memory management, however, this is likely to be the case anyway with structs if they're part of a linked list/some other advanced data structure.
The second one might use too much or too little memory, it opens itself up to out of bounds errors, etc.
Is the way you deal with strings dependent on your use case or is there a universal best practice?
There is no generic best practice on this one. It is mainly wasted space vs. complexity of the code.
As a rule of thumb, you might consider the typical line lengths you have in your typical documents - In a text editor, 1 vs. maybe 100 bytes, so a maximum "waste" of 99 bytes per line, which, in my opinion is acceptable on modern, non-memory-restricted machines. The point is: Once your user wants a line of 101 characters, you're forced to either tell your users about the limit, or introduce expensive work-arounds for the case of extra long lines (and, revert back to complexity).
You might, however, want to consider that line-oriented editor buffers have been widely out of fashion since at least 30 years. The most-used (and accepted, IMHO) buffer architecture is the one Emacs introduced like 30 years ago - A big chunk of memory with an insertion gap that is moved back and forth to the place the user is editing.
Is the way you deal with strings dependent on your use case or is there a universal best practice?
There is no "universial best" pratice. It always depend on your your specific use case.
But... your use case is a text editor so using a struct with a fixed maximum line length just seems wrong to me.
But I like to show a third way which uses a flexible array member:
struct line {
size_t line_length;
char line_contents[]; <--- Flexible array.
malloc determines the size
};
int main()
{
char* str = "Hello World";
size_t len = strlen(str);
struct line* l = malloc(sizeof *l + len + 1);
\-----/
sizeof the array
l->line_length = len;
strcpy(l->line_contents, str);
printf("Len %zu: %s\n", l->line_length, l->line_contents);
free(l);
return 0;
}
In this way a single malloc can allocate both a new node and memory for the string.
The solution that is being commonly used in C libraries is by using the internal string.h library.
Strings in C are being designed with a null terminator in the end that basically says where the string ends. The null terminator is a '\0' character. The C string scheme is shown here.
Your code can be reformatted to the following bellow.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
const int MAX_STRING_LENGTH = 256;
int main()
{
/*+1 for the additional null terminator*/
char* line = malloc(MAX_STRING_LENGTH + 1);
strcpy(line, "Hello stack overflow!");
/*'line' can hold up to 256 byte long strings, but to get the
length of "Hello stack overflow!" string that was transfered
into 'line' variable, you can use 'strlen()' function as shown
below.*/
printf("Length of 'line' string: %d\n", strlen(line));
return 0;
}

how to load a char[] that's a member of Stuct[i]?

Let's say we have this struct
struct Foo{
int FooLength; //length of Foo
char FooChar[4];
};
and then in the main we have
int sizeFoo = 100; struct Foo myFooList[sizeFoo];
what would be the best way to input data for FooChar? Would strncpy, or memcpy, or snprintf, or sprintf?
what I wish to do is something like
myFooList[0].FooLength = 3;
myFooList[0].FooChar = "dog";
myFooList[1].FooLength = 3;
myFooList[1].FooChar = "cat";
.
.
.
with a correct syntax since in C you can't just = "string"; here, and I'm not sure what would be the best way to go about it? I have look at similar topics, but I just get more confused with how strncpy or sprintf are not good or you have to have a \0 added at the end or some other detail that makes picking what to do more difficult.
Also if all the values of myFooList[] are already know (they are const or static) is there a way to initialize like one would do any other array?
If your input is always 3 characters, you can use strcpy, otherwise use strncpy(myFooList[0].FooChar, "dog", 3). You must add the terminating null character if using strncpy. strcpy will add the termination null character automatically, just like VHS has in his answer. In either case, you should still validate that your input does not exceed the maximum length. To find the length of a string(i.e. the number of char characters up to the first null character), you would use strlen. To determine the capacity of a char a[], you can use _countof(a). Don't forget that one of those has to be a '\0'.
memcpy would also work, but it would be unusual to do that with a string.
You wouldn't use sprintf here. sprintf would normally be used when you need to create a unique string using dynamic data at runtime. This is not what you're doing here. If you have any experience with .NET, it is the C equivalent of string.Format.
To initialize an array of 'Foo', you will just need to write a function that will do that. Even if you figure out the syntax to do it in one line, it'll be very difficult to read and maintain. Here's an example without validation, I will leave that task to you.
myFooList[0].FooLength = 3;
strncpy(myFooList[0].FooChar, "dog", 3);
myFooList[0].FooChar[3] = '\0';
myFooList[1].FooLength = 3;
strncpy(myFooList[1].FooChar, "cat", 3);
myFooList[1].FooChar[3] = '\0';
Your integer assignment is correct, but the string assignment is not. Following is the right way:
myFooList[0].FooLength = 3;
strcpy( myFooList[0].FooChar, "dog");
myFooList[1].FooLength = 3;
strcpy(myFooList[1].FooChar, "cat");
what would be the best way to input data for FooChar? Would strncpy,
or memcpy, or snprintf, or sprintf? ...
but I just get more confused with how strncpy or sprintf are not good
or you have to have a \0 added at the end or some other detail that
makes picking what to do more difficult.
Well, memcpy is a good choice if you don't want terminate nul byte. I don't really understand what is your question here.
Also if all the values of myFooList[] are already know (they are const
or static) is there a way to initialize like one would do any other
array?
In your example, no, because you use VLA who can't be initialize. But you could do the following:
#include <stdio.h>
struct Foo {
int FooLength; // length of Foo
char FooChar[4];
};
int main(void) {
struct Foo myFooList[] = {{3, "dog"}, {3, "cat"}};
size_t size = sizeof myFooList / sizeof *myFooList;
}

Too much code for string concatenation in C

I get a lot of strcat lines in my code. Is there a better way to concatenate strings in C?
char material[50]; // it is defined before this code.
char result[10000];
strcpy(result, "// Assign new material to worldGlobe\n");
strcat(result, "shadingNode -asShader lambert -n ");
strcat(result, material);
strcat(result, ";\n");
You could use a format string in conjunction with snprintf() (safe compared to sprintf()):
snprintf(result, 10000,
"// Assign new material to worldGlobe\nshadingNode -asShader lambert -n %s;\n",
material);
strcat is only really suitable for really small strings; it has several problems for anything non-trivial, such as:
Due to the Schlemiel The Painter problem, strcat is O(n) over the length of the input strings, that is, the longer your strings, the longer each concatenation takes. This is because strcat has to walk the entire string to find its end. To solve this, store the length of the string along with the string data, which will allow you to jump directly to the end of the string.
It does not do any bounds checking. If you strcat too much onto the end of a string, it will happily write past the end of the string, producing a segfault in the best case, a severe security vulnerability in the worst, and most likely some bugs that will make you bash your head against the wall. strncat partially solves this problem, as long as you pass it the correct size of the destination buffer.
If your destination buffer is too small, neither strcat nor strncat will increase its size: you'll have to do this yourself.
There are two practical solutions in your situation:
a) The Tower Of Hanoi algorithm: Build a stack of strings. If a new string is shorter than the stack top, push it onto the stack. If it's longer, pop off the top, concatenate, and repeat the process with the result. When you're done pushing, concatenate what's on the stack. This is what std::stringstream in C++ or StringBuilder in .NET do, and if you look around, I'm sure you'll find a suitable implementation in C.
b) Write your strings directly to a stream. What you're outputting looks a lot like code - why not write it to a file directly?
What about
sprintf(result, "// Assign new material to worldGlobe\nshadingNode -asShader lambert -n %s;\n\0", material);
Try stpcpy; see link. Your sample code becomes:
char material[50]; // it is defined before this code.
char result[10000], *p = result;
p = stpcpy(p, "// Assign new material to worldGlobe\n");
p = stpcpy(p, "shadingNode -asShader lambert -n ");
p = stpcpy(p, material);
p = stpcpy(p, ";\n");
This function is available in Linux; the man page for stpcpy on my system states:
This function is not part of the C or POSIX.1 standards, and is not customary on Unix systems, but is not a GNU invention either. Perhaps it comes from MS-DOS.
If you don't have it, it is easy enough to write:
char *stpcpy(char *restrict dst, const char *restrict src) {
return strcpy(dst, src) + strlen(src);
}
This assumes you are aware of the dangers of strcpy.
C is mostly a do-it-yourself language.
Now that you know how to concat strings, you should write your own function to make it easier.
I'd suggest something like:
char* str_multicat(char* result, ...);
And call it something like:
str_mutlicat(result, "// Assign new material to worldGlobe\n",
"shadingNode -asShader lambert -n ",
material,
";\n",
NULL);
(hint, if you don't know the ... syntax, look into va_arg, va_start, va_end)
It would by pretty straight forward to build a string buffer struct that will keep track of the current position in your buffer, and combine that with vsprintf to get a catf(). The function vsnprintf() (assuming it's available) is just like printf, except it takes a va_list instead of ... after the format string.
This approach has the advantage over other answers that it lets you 'cat' from anywhere in your code that has access to the struct without explicitly carrying around the current length or recalculating each time it like strcat does.
Here's a rough sketch free of charge.....
/* Note: the typedef is for the pointer, not the struct. */
typedef struct StrBufStruct {
char * buffer,
size_t size,
size_t pos
} * StrBuf;
/* Create a new StrBuf. NOTE: Could statically allocate too. */
StrBuf newStrBuf(size_t size){
StrBuf sb;
sb = malloc( sizeof(struct StrBufStruct) );
sb->size = size;
sb->pos = 0;
sb->buffer = malloc( size );
/* TODO: ALWAYS CHECK YOUR MALLOC!!! */
}
int sbcatf( StrBuf b, char * fmt, ... )
{
va_list ap;
int res;
if( b->pos < b->size )
{
va_start(ap,fmt);
res = vsnprintf( b->buffer[b->pos], b->size - b->pos, fmt, ap );
b->pos += res;
va_end();
} else {
/* If you want to get really fancy, use realloc so you don't have to worry
about buffer size at all. But be careful, you can run out of memory. */
}
}
/* TODO: Write a free/delete function */
int main(int argc, char **argv){
int i;
/* initialize your structure */
StrBuf sb = newStrBuf(10000);
/* concatenate numbers 0-999 */
for(i=0; i < 1000; i++){
sbcatf(sb, "I=%d\n", i);
}
/* TODO: whatever needs to be done with sb->buffer */
/* free your structure */
deleteStrBuf(sb);
}
Also note that if all you're trying to do is make a really long string but want to be able to have line breaks in your code, this is usually acceptable, although I won't personally guarantee portability. I also use the technique to separate strings at "\n" line breaks to make the code look like the resulting string really would.
const char * someString = "this is one really really really really"
"long stttttttttrrrrrrrrrrrrrrrrrrrriiiiiiiiiiinnnnnnngggggg"
" because the compiler will automatically concatenate string"
" literals until we reach a ';' after a \" character";
You could have a function that returns a pointer to the end of the string, and use that end pointer in future calls. That'd eliminate a bunch of the extra "first, find the end of the string" stuff.
char* faster_cat(char* dest, const char* src)
{
strcpy(dest, src);
return dest + strlen(src);
}
Use like:
char result[10000];
char *end = &result[0];
result[0] = '\0'; // not strictly necessary if you cat a string, but why not
end = faster_cat(end, "// Assign new material to worldGlobe\n");
end = faster_cat(end, "shadingNode -asShader lambert -n ");
end = faster_cat(end, material);
end = faster_cat(end, ";\n");
// result now contains the whole catted string

In C, how can a char* passed to a function be populated with text?

I am trying to create a C function which will return an int, but in the process will populate a char* passed in as a variable. A basic example of what I am trying is:
int myMethod(int input, char* output, int outMaxLen) {
int outValue = input * 5;
if (out < 10) strcat(output, "A small number");
else if (out < 20) strcat(output, "A medium number");
else strcat(output, "A large number");
}
In main.c:
char* myMethodOutput;
int myMethodInt = myMethod(2, myMethodOutput, 15);
printf("%d %s", myMethodInt, myMethodOutput);
When run, the integer displays on the screen, but the text does not.
The outMaxLen variable is intended to check the char* parameter to ensure it is large enough to accommodate the output string.
As well as strcat(), I have tried strcpy() and strncpy(), all to no avail. strcat() does not display any text to the console, and strcpy() and strncpy() invoke the debugger with the message EXC_BAD_ACCESS.
I have successfully managed this in the Windows API by using the strcpy_s function, but I am now trying on a UNIX box. I am probably missing something extremely fundamental!
You need to assign some memory to the pointer first, otherwise you're just writing to some random area in memory. e.g.:
char *myMethodOutput = malloc(256);
/* ... etc ... */
free(myMethodOutput);
char* myMethodOutput;
myMethodOutput = malloc(sizeof(char) * 200); //200 is example
don't forget to free, also myMethod() should be of type void
Naming a parameter as "length of a buffer" does not, indeed, create a buffer long enough.
You don't allocate any memory for a buffer; not in the sample code at least.
You should allocate some memory for myMethodOutput with malloc() or something before you use it. It's not a good idea to write to the location of an uninitialized pointer.

Using strcat in C

Okay so I have the following Code which appends a string to another in C#, note that this is Just an example, so giving alternative string concatination methods in C# is not nessesary, this is just to simplify the example.
string Data = "";
Data +="\n\nHTTP/1.1 " + Status_code;
Data += "\nContent-Type: " + Content_Type;
Data += "\nServer: PT06";
Data += "\nContent-Length: " + Content_Lengt;
Data += "\nDate: " + Date;
Data += "\n" + HTML;
Now I'd like to do the exact same thing in C and I'm trying to do this the following way
time_t rawtime;
time ( &rawtime );
char *message = "\n\nHTTP/1.1 ";
message = strcat(message, Status_code);
message = strcat(message, "\nContent-Type: ");
message = strcat(message, Content_Type);
message = strcat(message, "\nServer: PT06");
message = strcat(message, "\nContent-Length: ");
message = strcat(message, Content_Lengt);
message = strcat(message, "\nDate: ");
message = strcat(message, ctime(&rawtime));
message = strcat(message, "\n");
message = strcat(message, HTML);
Now, this gives me a Segment fault, I know why, I access and read on memory that i shouldn't. But the question is, how do i solve it? Could I use string.h and just do it the same way that I did in C#?
Change
char *message = "\n\nHTTP/1.1 ";
to
char message[1024];
strcpy(message,"\n\nHTTP/1.1 ");
and you should be ok, up to a total message length of 1023.
Edit: (as per mjy's comment). Using strcat in this fashion is a great way of getting buffer overflows. You could readily write a small function that checks the size of the buffer and length of incoming string addition to overcome this, or use realloc on a dynamic buffer. IMO, the onus is on the programmer to check correct buffer sizes where they are used, as with sprintfs and other C strings functions. I assume that C is being used over C++ for performance reasons, and hence STL is not an option.
Edit: As per request from Filip's comment, a simple strcat implementation based on a fixed size char buffer:
char buffer[MAXSIZE] = "";
int mystrcat(char *addition)
{
if (strlen(buffer) + strlen(addition) + sizeof(char) >= MaxSize)
return(FAILED);
strcat(buffer,addition);
return(OK);
}
Using dynamic allocation:
char *buffer = NULL;
int mystrcat(char *addition)
{
buffer = realloc(buffer, strlen(buffer) + strlen(addition) + sizeof(char));
if (!buffer)
return(FAIL);
strcat(buffer, addition);
return(OK);
}
In this case you have to free your buffer manually when you are finished with it. (Handled by destructors in C++ equivalents)
Addendum (Pax):
Okay, since you didn't actually explain why you had to create message[1024], here it is.
With char *x = "hello", the actual bytes ('h','e','l','l','o',0) (null on the end) are stored in an area of memory separate from the variables (and quite possibly read-only) and the variable x is set to point to it. After the null, there's probably something else very important. So you can't append to that at all.
With char x[1024]; strcpy(x,"hello");, you first allocate 1K om memory which is totally dedicated to x. Then you copy "hello" into it, and still leave quite a bit of space at the end for appending more strings. You won't get into trouble until you append more than the 1K-odd allowed.
End addendum (Pax):
I wonder why no one mentioned snprintf() from stdio.h yet. That's the C way to output multiple values and you won't even have to convert your primitives to strings beforehand.
The following example uses a stack allocated fixed-sized buffer. Otherwise, you have to malloc() the buffer (and store its size), which would make it possible to realloc() on overflow...
char buffer[1024];
int len = snprintf(buffer, sizeof(buffer), "%s %i", "a string", 5);
if(len < 0 || len >= sizeof(buffer))
{
// buffer too small or error
}
Edit: You might also consider using the asprintf() function. It's a widely available GNU extension and part of TR 24731-2 (which means it might make it into the next C standard). The example from above would read
char * buffer;
if(asprintf(&buffer, "%s %i", "a string", 5) < 0)
{
// (allocation?) error
}
Remember to free() the buffer when done using it!
Start from using the safer strncat function. In general always use the safer 'n' functions that will not overflow if the size of a string is bigger than a specific size.
In C you need to take care of string sizes yourself. So you need to know how big the resulting string will be and accommodate for it. If you know the sizes of all the strings at the left side, you should create a buffer big enough to hold the resulting string.
message points to a char const[] that you can't write to, yet that's exactly where strcat is writing. You need to malloc() a sufficiently large buffer.
As said previously, you have to write to a sufficiently large buffer. Unfortunately, doing so is a lot of extra work. Most C applications that deal with strings use a dynamically resizable string buffer for doing concatenations.
glib includes an implementation of this, glib strings, which I recommend using for any application that uses strings heavily. It makes managing the memory easier, and prevents buffer overflows.
Have not seen any mention of the strlcpy, strlcat function, which is similar to the 'n' functions except also takes into account the trailing 0. Both take a third argument indicating the maximum length of the output buffer and are found in string.h.
example:
char blah[]="blah";
char buffer[1024];
strlcpy(buffer,"herro!!!",sizeof(buffer));
strlcat(buffer,blah,sizeof(buffer));
printf("%s\n",buffer);
Will output "herro!!!blah"
char blah[]="blah";
char buffer[10];
strlcpy(buffer,"herro!!!",sizeof(buffer));
strlcat(buffer,blah,sizeof(buffer));
printf("%s\n",buffer);
will output "herro!!!b" due to the limited size of buffer[], with no segfaulting. ^^
Only problem is not all platforms seem to include it in their libc (such as linux ._.), most all BSD varients DO seem to have it.
In that case, code for both functions can be found here and easily added: strlcpy, strlcat,
the rest of string.h
The safe way to do this in classic C style is:
char *strconcat(char *s1, char *s2)
{
size_t old_size;
char *t;
old_size = strlen(s1);
/* cannot use realloc() on initial const char* */
t = malloc(old_size + strlen(s2) + 1);
strcpy(t, s1);
strcpy(t + old_size, s2);
return t;
}
...
char *message = "\n\nHTTP/1.1 ";
message = strconcat (message, Status_code);
message = strconcat (message, "\nContent-Type: ");
Now you can say a lot of bad things about it: it's inefficient, it fragments your memory, it's ugly ... but it's more or less what any language with a string concatenation operator and C type (zero-terminated) strings will do (except that most of these languages will have garbage collection built-in).

Resources