Have an array of chars like char members[255]. How can I empty it completely without using a loop?
char members[255];
By "empty" I mean that if it had some values stored in it then it should not. For example if I do strcat then old value should not remain
members = "old value";
//empty it efficiently
strcat(members,"new"); // should return only new and not "old value new"
using
memset(members, 0, 255);
in general
memset(members, 0, sizeof members);
if the array is in scope, or
memset(members, 0, nMembers * (sizeof members[0]) );
if you only have the pointer value, and nMembers is the number of elements in the array.
EDIT Of course, now the requirement has changed from the generic task of clearing an array to purely resetting a string, memset is overkill and just zeroing the first element suffices (as noted in other answers).
EDIT In order to use memset, you have to include string.h.
Depends on what you mean by 'empty':
members[0] = '\0';
Don't bother trying to zero-out your char array if you are dealing with strings. Below is a simple way to work with the char strings.
Copy (assign new string):
strcpy(members, "hello");
Concatenate (add the string):
strcat(members, " world");
Empty string:
members[0] = 0;
Simple like that.
char members[255] = {0};
EDIT: Given the most recent edit to the question, this will no longer work as there is no null termination - if you tried to print the array, you would get your characters followed by a number of non-human-readable characters. However, I'm leaving this answer here as community wiki for posterity.
char members[255] = { 0 };
That should work. According to the C Programming Language:
If the array has fixed size, the number of initializers may not exceed the number of members of the array; if there are fewer, the remaining members are initialized with 0.
This means that every element of the array will have a value of 0. I'm not sure if that is what you would consider "empty" or not, since 0 is a valid value for a char.
Use bzero(array name, no.of bytes to be cleared);
You cannot empty an array as such, it always contains the same amount of data.
In a bigger context the data in the array may represent an empty list of items, but that has to be defined in addition to the array. The most common ways to do this is to keep a count of valid items (see the answer by pmg) or for strings to terminate them with a zero character (the answer by Felix). There are also more complicated ways, for example a ring buffer uses two indices for the positions where data is added and removed.
members[0] = 0;
is enough, given your requirements.
Notice however this is not "emptying" the buffer. The memory is still allocated, valid character values may still exist in it, and so forth..
I'd go with
members_in_use = 0;
By "empty an array" if you mean reset to 0, then you can use bzero.
#include <strings.h>
void bzero(void *s, size_t n);
If you want to fill the array with some other default character then you may use memset function.
#include <string.h>
void *memset(void *s, int c, size_t n);
In this case just members[0] = 0 works.
Disclaimer: I don't usually program in C so there may be any syntax gotcha in my examples, but I hope the ideas I try to express are clear.
If "emptying" means "containing an empty string", you can just assign the first array item to zero, which will effectively make the array to contain an empry string:
members[0] = 0;
If "emptying" means "freeing the memory it is using", you should not use a fixed char array in the first place. Rather, you should define a pointer to char, and then do malloc / free (or string assignment) as appropriate.
An example using only static strings:
char* emptyString="";
char* members;
//Set string value
members = "old value";
//Empty string value
member = emptyString
//Will return just "new"
strcat(members,"new");
You can use the following instruction:
strcpy_s(members, "");
Related
My question should be rather simple.
I need to give a function a char array of a pre-defined length, but I have a character pointer with variable length, but not longer than the length of my array.
Here the code:
#define SIZE_MAX_PERSON_NAME 50
char person[SIZE_MAX_PERSON_NAME];
char* currentPerson = "John";
now how would I get John into the person array but also setting the rest of the array to 0 (/NUL) ?
so that I would have
BINARY DATA: "John/NUL/NUL/NUL/NUL/NUL/NUL/NUL/NUL/NUL/NUL/NUL/NUL/NUL/NUL....."
in my memory?
sorry if this is overly stupid, but I can't seem to find a solution right now.
First, zero-initialize the fixed-size array :
// Using memset here because I don't know if the whole copy operation can or will be used
// multiple times. We want to be sure that the array is properly zero-initialized if the next
// string to copy is shorter than the previous.
memset(person, '\0', SIZE_MAX_PERSON_NAME);
Then, copy the variable-size string into it :
strcpy(person, currentPerson);
If you are not certain that currentPerson will fit into person :
strncpy(person, currentPerson, SIZE_MAX_PERSON_NAME - 1);
Note that strncpy also zero-initialize the remaining bytes of the array if
strlen(currentPerson) < SIZE_MAX_PERSON_NAME - 1
So you basically have these two options :
memset(person, '\0', SIZE_MAX_PERSON_NAME);
strcpy(person, currentPerson);
Or :
strncpy(person, currentPerson, SIZE_MAX_PERSON_NAME - 1);
person[SIZE_MAX_PERSON_NAME - 1] = '\0';
After this answer was posted the question was retagged from C++ to C.
Use a std::string, like this:
// "using namespace std;" or "using std::string;", then:
string const person = currentPerson;
old_c_function( person.c_str() );
To do things at the C level, which I recommend that you don't, first replace the unnecessary #define with a typed constant:
int const max_person_name_size = 50;
Then zero-initialize your array:
char person[max_person_name_size] = {};
(Note: no silly memset here.)
(Also note: this zeroing is only a preventive measure. You wanted it. But it's not really necessary since strcpy will ensure a trailing zero-byte.)
Then just copy in the string:
assert( strlen( current_person ) < max_person_name_size );
strcpy( person, current_person );
But don't do this. Use std::string instead.
Update: doing other things for some minutes made me realize that this answer, as all the others so far, is completely off the mark. The OP states in a comment elsewhere that
” I've got a function in the library which only takes a character array. Not a character pointer.
Thus, apparently it's all about a misconception.
The only way this can make sense is if the array is modified by the function, and then std::string::c_str() is not a solution. But a std::string can still be used, if its length is set to something sufficient for the C function. Can go like this:
person.resize( max_person_name_size );
foo( &person[0] ); // Assuming foo modifies the array.
person.resize( strlen( person.c_str() ) );
With literal, you may do:
char person[SIZE_MAX_PERSON_NAME] = "John";
if c-string is not a literal, you have to do the copy with strcpy
strcpy(person, currentPerson);
This is the one and only reason for the existence of strncpy:
Putting a string (up to the 0-terminator or buffer end) into a fixed-length array and zeroing out the rest.
This does not ensure 0-termination, thus avoid it for anything else.
7.24.2.4 The strncpy function
#include <string.h>
char *strncpy(char * restrict s1, const char * restrict s2, size_t n);
2 The strncpy function copies not more than n characters (characters that follow a null
character are not copied) from the array pointed to by s2 to the array pointed to by s1.308) If copying takes place between objects that overlap, the behavior is undefined.
3 If the array pointed to by s2 is a string that is shorter than n characters, null characters are appended to the copy in the array pointed to by s1, until n characters in all have been written.
4 The strncpy function returns the value of s1.
I need to initialize an array of structs with the same default values. This is a VERY large array, so setting each element by hand in an initializer is not feasable. Is the following code a correct and sane way to do this, or will I need to fall back on some initializer function and a for loop?
#define SIZE_OF_S1_ARR 10000 //just some arbitrary size for an example
typedef struct { char* id, char* description} S1;
/*
* Array of structs, with each element having an id and a description
* which is an empty c-string
/*/
S1 s1_arr[SIZE_OF_S1_ARR] = {{ "", "" }};
I will add that this array already existed as a char array which only contained the ids as a single character. I am replacing it with the more useful struct.
In standard C there is not array initiaization other than 0, unless you specify each value separately.
However, if you use the GNU C compiler, you can use something like this:
char s1_arr[SIZE_OF_S1_ARR] = {[0 ... SIZE_OF_S1_ARR-1] = '_' };
Please note that this approach is not portable.
In addition, please note that initalizing strings (i.e., pointer to char) to have the same value can be done in two ways:
(possible automatically) allocate a number of stings and assign them or allocate one string and assign it to all elements
It seems you are looking for the memset function.
To initialize your S1 type
#define ARBITER 10000 // just an example number for elements
S1 *s1_arr = (S1*)malloc(sizeof(S1)*ARBITER);
id and description are initialized with NULL.
To set s1_arr->id and s1_arr->description you need also a *char variable
or just a literal string (char* a_string = "I am a String"; // This is a literal).
Hope I help you out.
i have created an two dimensional array like this:
char string_y2m[2][8];
Then I just used memset() for initialize it by 0:
memset(&string_y2m, 0, sizeof(string_y2m));
Now I have to assign it some value but it's not working. I have assigned it like this:
string_y2m[2][8] = {"2011-1","2011-01"};
It's not working, same thing if I do at declaration itself, it works.
You cannot assign strings like that in C, when the target is a character array and you're not also declaring it.
In C, you need to use strcpy() to copy the string into the array, paying a lot of attention to the buffer sizes:
strcpy(string_y2m[0], "2011-1");
strcpy(string_y2m[1], "2011-01");
Or use snprintf() if you have it:
snprintf(string_y2m[0], sizeof string_y2m[0], "%s", "2011-1");
snprintf(string_y2m[1], sizeof string_y2m[1], "%s", "2011-01");
Also, there's no need to clear the space before writing the string there, since writing the string will set the characters to the required values.
Just don't use assignment but initialize the array correctly from the start:
char string_y2m[2][8] = {"2011-1","2011-01"};
This will initialize all characters that are not initialized explicitly to 0.
char in[100], *temp[10],var[10][10];
int i, n = 0,
double val[10];
var[0][]="ANS";
I want to assign a string to var[0][0,1,2] which is 'ANS', but does not work and i cannot figure where i am wrong about this
Perhaps instead using,
strncpy(var[0], "ANS", 3);
You have sort of answered your own question. You want to assign var[0][0,1,2,3] to "ANS" right? Well "ANS" is an array of characters, ans[0,1,2,3] (don't forget the null terminator). So you have to assign each one individually. In C strings aren't a data type, they are just an array of other variables (chars to be exact). What you can do instead is:
strcpy(var[0], "ANS");
Which will do the byte-by-byte copy for you.
There are some pitfalls to strcpy, however. First, the destination char array (var[0] in this case) must be large enough to contain the string. It will not check this for you (it can't, actually) so if you are not careful you can cause a buffer overflow. Also, the source must be NULL terminated.
When you write
var[0][] = "ANS"
Compiler tries to assign "ANS" to var[0][0] which is a place for only one char.
Therefore, you should use strcpy function. strcpy will copy char-by-char.
I have a structure that has an array of pointers. I would like to insert into the array digits in string format, i.e. "1", "2", etc..
However, is there any difference in using either sprintf or strncpy?
Any big mistakes with my code? I know I have to call free, I will do that in another part of my code.
Many thanks for any advice!
struct port_t
{
char *collect_digits[100];
}ports[20];
/** store all the string digits in the array for the port number specified */
static void g_store_digit(char *digit, unsigned int port)
{
static int marker = 0;
/* allocate memory */
ports[port].collect_digits[marker] = (char*) malloc(sizeof(digit)); /* sizeof includes 0 terminator */
// sprintf(ports[port].collect_digits[marker++], "%s", digit);
strncpy(ports[port].collect_digits[marker++], digit, sizeof(ports[port].collect_digits[marker]));
}
Yes, your code has a few issues.
In C, don't cast the return value of malloc(). It's not needed, and can hide errors.
You're allocating space based on the size of a pointer, not the size of what you want to store.
The same for the copying.
It is unclear what the static marker does, and if the logic around it really is correct. Is port the slot that is going to be changed, or is it controlled by a static variable?
Do you want to store only single digits per slot in the array, or multiple-digit numbers?
Here's how that function could look, given the declaration:
/* Initialize the given port position to hold the given number, as a decimal string. */
static void g_store_digit(struct port_t *ports, unsigned int port, unsigned int number)
{
char tmp[32];
snprintf(tmp, sizeof tmp, "%u", number);
ports[port].collect_digits = strdup(tmp);
}
strncpy(ports[port].collect_digits[marker++], digit, sizeof(ports[port].collect_digits[marker]));
This is incorrect.
You have allocated onto collect_digits a certain amount of memory.
You copy char *digits into that memory.
The length you should copy is strlen(digits). What you're actually copying is sizeof(ports[port].collect_digits[marker]), which will give you the length of a single char *.
You cannot use sizeof() to find the length of allocated memory. Furthermore, unless you know a priori that digits is the same length as the memory you've allocated, even if sizeof() did tell you the length of allocated memory, you would be copying the wrong number of bytes (too many; you only need to copy the length of digits).
Also, even if the two lengths are always the same, obtaining the length is this way is not expressive; it misleads the reader.
Note also that strncpy() will pad with trailing NULLs if the specified copy length is greater than the length of the source string. As such, if digits is the length of the memory allocated, you will have a non-terminated string.
The sprintf() line is functionally correct, but for what you're doing, strcpy() (as opposed to strncpy()) is, from what I can see and know of the code, the correct choice.
I have to say, I don't know what you're trying to do, but the code feels very awkward.
The first thing: why have an array of pointers? Do you expect multiple strings for a port object? You probably only need a plain array or a pointer (since you are malloc-ing later on).
struct port_t
{
char *collect_digits;
}ports[20];
You need to pass the address of the string, otherwise, the malloc acts on a local copy and you never get back what you paid for.
static void g_store_digit(char **digit, unsigned int port);
Finally, the sizeof applies in a pointer context and doesn't give you the correct size.
Instead of using malloc() and strncpy(), just use strdup() - it allocates the buffer bin enough to hold the content and copies the content to the new string, all in one shot.
So you don't need g_store_digit() at all - just use strdup(), and maintain marker on the caller's level.
Another problem with the original code: The statement
strncpy(ports[port].collect_digits[marker++], digit, sizeof(ports[port].collect_digits[marker]));
references marker and marker++ in the same expression. The order of evaluation for the ++ is undefined in this case -- the second reference to marker may be evaluated either before or after the increment is performed.