I basically want to store a array of student names, based on a given number. For example, if the user wants to insert 5 names, then the array size will be 5. If the user wants to insert 10 names, then the array size will be 10.
I have a method like this to set a name to a specific element in an array.
void setNames(char *names){
strcpy(name[i], names);
}
Thing is, how do I do array bound checks? I heard that you can only add when the index is -1.
Arrays don't maintain their own size, you have to do that for them. This is part of the reason why vectors are so much easier to deal with, and why everyone will say "wtf, raw arrays? use a vector". An array is just a contiguous chunk of memory, thats it. a vector contains an array, and lets you use it like an array to some extent, but it handles a lot of the housekeeping details for you.
Anyway, if you really want to use a raw array, then you'll need to pass around size information along with it. C strings are a null-terminated array -- just a plain old array, but the last element is \0. This way you can read from it without knowing it's size ahead of time, just don't read past the null character at the end (dragons be there).
EDIT (as the OP indicated he actually wants C):
C answer
What you can do is either create a char array:
char [N][name_length]
where N - number "user wants" (I assume the user will somehow input it into your program), name_length - maximum length the name can have (a C-string, i.e. null-terminated string).
or create an array of your own structs (each holding a separate name and maybe some other information).
C++ answer
A typical way to do this in C++ is by using std::vector<std::string> (assuming you only want to store names, as std::string).
You then add new elements using using push_back() function. And, as vector is implemented as a dynamic array in C++, you won't have to do bound checking.
C code needs to keep track of the array size in another variable.
typedef struct {
char **name;
size_t n;
} Names_T;
void Names_Set(Names_T *names, size_t index, const char *name) {
// See if it is a special value and then append to the array
if (index == (size_t) -1) {
index = names->n;
}
if (index >= names->n) {
size_t newsize = index + 1;
// OOM error handling omitted
names->name = realloc(names->name, newsize * sizeof *names->name);
while (names->n < newsize) {
names->name[names->n++] = NULL;
}
}
char *oldname = names->name[index];
names->name[index] = strdup(name);
free(oldname);
}
void Names_Delete(Names_T *names) {
while (names->n > 0) {
names->n--;
free(&names->name[names->n]);
names->name[names->n] = NULL;
}
free(names->name);
names->name = NULL;
}
int main(void) {
Names_T names = { NULL, 0 };
Names_Set(&names, 3, "Sam"); // set array element 3
Names_Set(&names, (size_t) -1, "Thers"); // Append to array
Names_Delete(&names);
return 0;
}
When programming in C/C++ (unless using C++11 or newer), you will manipulate arrays as pointers. That means you won't know the size of an array unless you save it. What char str[10] really means is str's address + 10 * sizeof(char). You are directly dealing with memory here.
If you want a high level approach for that, take a look at C++11. std::array and std::vector are there for you. From the documentation, look how std::array is defined:
template <
class T,
std::size_t N
> struct array;
It means it stores its own size and has useful functions as well, such as size(), at(), back() etc.
Related
I've taking many attempts at solving this problem but failed every time.
I have an array
char *array[1024] = {};
Now I would like to add an item to the array and would also access the items by numbers
For example:
array[0] would be the first item
array[1] would be the second
array[2] would be the third item
But also I would like to know how many items are in the array so I could use something like
for(int i = 0; i <= totalitemsinarray; i++) {
print(array[i]);
}
You cannot change the size of an array in C. You can however allocate a sufficiently large array and then fill it up with entries. First, declare an array with a sufficient size, say, 1024.
char *array[1024];
Then declare a variable fill that counts the number of used slots in array. Initialize it to 0 as 0 slots are used in the beginning. Then, each time you insert an item, increment fill:
array[fill++] = ...;
...
array[fill++] = ...;
Make sure that you never attempt to insert more than 1024 items into the array, C doesn't check that for you.
For a more flexible approach, use malloc() to allocate memory for the array and then periodically enlarge it with realloc() when it's full. If you increase the array size in exponential steps (say, multiply with Φ = 0.5 + 0.5 √2 ≈ 1.61), this runs in O(1) amortised time per entry inserted.
There is no way to do what you're asking directly with C. One option could be if you knew that only certain values were valid. For example, you have an array of char *s so often people use NULL as a flag/invalid value. In that case you could initialize your array to have all NULLs and use that to know the size of the array:
char *array[1024];
memset(array, 0, sizeof(array));
/* .... */
for (int i = 0; i < sizeof(array)/sizeof(char*); i++) {
if (array[i]) {
printf("%s\n", array[i]);
}
}
char *array[1024] = {};
First, that is an array with 1024 char pointers/strings. Those elements can be 0s or plain garbage. If you don't plan to set them all you may want to nullify the array.
For the matter of storing the values and the count you might want to have a look at structs. For example:
typedef struct elem {
int count;
char *value;
} elem;
Then elem.count would be the number and elem.value would be the value accordingly.
And then initialize them in a for loop.
The only really valid way to approach this, is to dynamically grow the array. Allocate the array on the heap, and manage two counts: 1. the count of currently used elements, and 2. the count of elements for which you currently have memory allocated. Something like this:
//the setup
size_t arrayLength = 0, allocatedSize = 8;
int* array = malloc(sizeof(*array) * allocatedSize);
//grow the array -> first check that we have space to add an element
if(arrayLength == allocatedSize) {
array = realloc(array, allocatedSize *= 2);
assert(array);
}
assert(arrayLength < allocatedSize);
//grow the array -> add an element
array[arrayLength++] = ...;
You see, the realloc() call is not too much hassle, but it will protect you from bugs when the requirements change. My experience is that any fixed limit in the code, as insanely large as it may seem to be, will eventually be exceeded, and miserable failure will result. The only safeguard is to use as much memory as needed everywhere.
I am learning C language. I want to know the size of an array inside a function. This function receive a pointer pointing to the first element to the array. I don't want to send the size value like a function parameter.
My code is:
#include <stdio.h>
void ShowArray(short* a);
int main (int argc, char* argv[])
{
short vec[] = { 0, 1, 2, 3, 4 };
short* p = &vec[0];
ShowArray(p);
return 0;
}
void ShowArray(short* a)
{
short i = 0;
while( *(a + i) != NULL )
{
printf("%hd ", *(a + i) );
++i;
}
printf("\n");
}
My code doesn't show any number. How can I fix it?
Thanks.
Arrays in C are simply ways to allocate contiguous memory locations and are not "objects" as you might find in other languages. Therefore, when you allocate an array (e.g. int numbers[5];) you're specifying how much physical memory you want to reserve for your array.
However, that doesn't tell you how many valid entries you have in the (conceptual) list for which the physical array is being used at any specific point in time.
Therefore, you're required to keep the actual length of the "list" as a separate variable (e.g. size_t numbers_cnt = 0;).
I don't want to send the size value like a function parameter.
Since you don't want to do this, one alternative is to use a struct and build an array type yourself. For example:
struct int_array_t {
int *data;
size_t length;
};
This way, you could use it in a way similar to:
struct int_array_t array;
array.data = // malloc for array data here...
array.length = 0;
// ...
some_function_call(array); // send the "object", not multiple arguments
Now you don't have to write: some_other_function(data, length);, which is what you originally wanted to avoid.
To work with it, you could simply do something like this:
void display_array(struct int_array_t array)
{
size_t i;
printf("[");
for(i = 0; i < array.length; ++i)
printf("%d, ", array.data[i]);
printf("]\n");
}
I think this is a better and more reliable alternative than another suggestion of trying to fill the array with sentinel values (e.g. -1), which would be more difficult to work with in non-trivial programs (e.g. understand, maintain, debug, etc) and, AFAIK, is not considered good practice either.
For example, your current array is an array of shorts, which would mean that the proposed sentinel value of -1 can no longer be considered a valid entry within this array. You'd also need to zero out everything in the memory block, just in case some of those sentinels were already present in the allocated memory.
Lastly, as you use it, it still wouldn't tell you what the actual length of your array is. If you don't track this in a separate variable, then you'll have to calculate the length at runtime by looping over all the data in your array until you come across a sentinel value (e.g. -1), which is going to impact performance.
In other words, to find the length, you'd have to do something like:
size_t len = 0;
while(arr[len++] != -1); // this is O(N)
printf("Length is %u\n", len);
The strlen function already suffers from this performance problem, having a time-complexity of O(N), because it has to process the entire string until it finds the NULL char to return the length.
Relying on sentinel values is also unsafe and has produced countless bugs and security vulnerabilities in C and C++ programs, to the point where even Microsoft recommends banning their use as a way to help prevent more security holes.
I think there's no need to create this kind of problem. Compare the above, with simply writing:
// this is O(1), does not rely on sentinels, and makes a program safer
printf("Length is %u\n", array.length);
As you add/remove elements into array.data you can simply write array.length++ or array.length-- to keep track of the actual amount of valid entries. All of these are constant-time operations.
You should also keep the maximum size of the array (what you used in malloc) around so that you can make sure that array.length never goes beyond said limit. Otherwise you'd get a segfault.
One way, is to use a terminator that is unique from any value in the array. For example, you want to pass an array of ints. You know that you never use the value -1. So you can use that as your terminator:
#define TERM (-1)
void print(int *arr)
{
for (; *arr != TERM; ++arr)
printf("%d\n", *arr);
}
But this approach is usually not used, because the sentinel could be a valid number. So normally, you will have to pass the length.
You can't use sizeof inside of the function, because as soon as you pass the array, it decays into a pointer to the first element. Thus, sizeof arr will be the size of a pointer on your machine.
#include <stdio.h>
void ShowArray(short* a);
int main (int argc, char* argv[])
{
short vec[] = { 0, 1, 2, 3, 4 };
short* p = &vec[0];
ShowArray(p);
return 0;
}
void ShowArray(short* a)
{
short i = 0;
short j;
j = sizeof(*a) / sizeof(short);
while( i < j )
{
printf("%hd ", *(a + i) );
++i;
}
printf("\n");
}
Not sure if this will work tho give it a try (I don't have a pc at the moment)
Let's consider following piece of code:
int len = 100;
char *buf = (char*)malloc(sizeof(char)*len);
printf("Appended: %s\n",struct_to_string(some_struct,buf,len));
Someone allocated amount of memory in order to get it filled with string data. The problem is that string data taken from some_struct could be ANY length. So what i want to achieve is to make struct_to_string function do the following:
Do not allocate any memory that goes outside (so, buf has to be allocated outside of the function, and passed)
Inside the struct_to_string I want to do something like:
char* struct_to_string(const struct type* some_struct, char* buf, int len) {
//it will be more like pseudo code to show the idea :)
char var1_name[] = "int l1";
buf += var1_name + " = " + some_struct->l1;
//when l1 is a int or some non char, I need to cast it
char var2_name[] = "bool t1";
buf += var2_name + " = " + some_struct->t1;
// buf+= (I mean appending function) should check if there is a place in a buf,
//if there is not it should fill buf with
//as many characters as possible (without writting to memory) and stop
//etc.
return buf;
}
Output should be like:
Appended: int l1 = 10 bool t1 = 20 //if there was good amount of memory allocated or
ex: Appended: int l1 = 10 bo //if there was not enough memory allocated
To sum up:
I need a function (or couple of functions) that adds given strings to the base string without overwritting base string;
do nothing when base string memory is full
I can not use C++ libraries
Another things that I could ask but are not so important right now:
Is there a way (in C) iterate through structure variable list to get their names, or at least to get their values without their names? (for example iterate through structure like through array ;d)
I do not normally use C, but for now I'm obligated to do, so I have very basic knowledge.
(sorry for my English)
Edit:
Good way to solve that problem is shown in post below: stackoverflow.com/a/2674354/2630520
I'd say all you need is the standard strncat function defined in the string.h header.
About the 'iterate through structure variable list' part, I'm not exactly sure what you mean. If your talking about iterating over the structure's members, a short answer would be : you can't introspect C structs for free.
You need to know beforehand what structure type you're using so that the compiler know at what offset in the memory it can find each member of your struct. Otherwise it's just an array of bytes like any other.
Don't mind asking if I wasn't clear enough or if you want more details.
Good luck.
So basically I did it like here: stackoverflow.com/a/2674354/2630520
int struct_to_string(const struct struct_type* struct_var, char* buf, const int len)
{
unsigned int length = 0;
unsigned int i;
length += snprintf(buf+length, len-length, "v0[%d]", struct_var->v0);
length += other_struct_to_string(struct_var->sub, buf+length, len-length);
length += snprintf(buf+length, len-length, "v2[%d]", struct_var->v2);
length += snprintf(buf+length, len-length, "v3[%d]", struct_var->v3);
....
return length;
}
snprintf writes as much as possible and discards everything left, so it was exactly what I was looking for.
This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
How to find the sizeof(a pointer pointing to an array)
I know this to find the size of array = sizeof(arr)/sizeof(arr[0])
But I have to implement the following (It's just a demo):
demo.h
#ifndef __DEMO_H
#define __DEMO_H
void heap_sort(int *);
#endif
demo.c
void heap_sort(int *ptrA)
{
//implementing heap sort
But here it requires length of array
}
main.c
#include "demo.h"
int main(void)
{
int A[10];
heap_sort(A)
return 0;
}
FYI .. It's just a demo.. but here I have to implement it in some other scenarios in which there is restriction that "DON'T CHANGE ANYTHING IN HEADER FILE" which means i can't change the function signature . Then how to get the array length in demo.c For char it's easy to get by help of strlen() Isn't there anything similar to get the length of int,float double types
The only alternatives I see are:
use a special value as terminator (as strlen does).
use the Pascal trick, and place array length in the first element.
store the array size in a global external variable.
use a separate function.
E.g.:
int arraySize(int newSize)
{
static int arraySize = 0;
int oldSize;
oldSize = arraySize;
if (newSize)
arraySize = newSize;
return oldSize;
}
in main.c:
arraySize(10);
in demo.c:
arraylen = arraySize(0);
if you can't change the function signature, then maybe you could pass the size of the array in the first element.
A[0] = 10;
heap_sort(A);
Or mark the end of the array with some special value, but I don't like this one because you'd have to iterate the whole array to find the length and you need to make sure this value is not used in the array:
A[LENGTH-1] = END//some value;
void array_length(A) {
while (*A++ != END) {
length++;
}
}
This is just a solution for the restrictions you imposed, what I would normally do, is either pass the size of the array as a second argument, or use a struct for the array:
struct array_t {
int *data; //allocate this
int size;
};
Note: other horrible solutions include global variables.
Thinking of strlen() is going into the right direction.
Strings are character arrays with a '\0' as array termination, as last element.
You could take the same approach for any other type of array.
Just define one value as the value which indicates the last element in an array. Searching for this value then helps you to find the size of the array.
Update:
I like mux's idea of using the first element in an array.
Anyhow, using it to store the numbers of element in there might lead to problems in case the number of elements in the array is larger as what can be store in an array's element (a char array, for example, whould then be limited to 255 elements).
My approach on the other hand has the draw back that the value used as terminator to the array is not usable as real value in the arra itself.
The combining the former and the latter approaches, I propose to use the first element of the array to store the value which is used as terminator of the array.
The constraint seems a bit odd, but whatever.
Why not use a global variable to store the size.
I have to write a function in c which will return a dynamic array of strings. Here are my requirements:
I have 10 different examine functions which will return either true or false and associated error text. (error text string is also dynamic).
My function must collect the result(true or false) + the error string and it will be called n examine functions. So my function must collect n results and finally return a dynamic array of strings to other functions.
You can allocate an array of arbitrary length with malloc() (it's like "new" in Java), and make it grow or shrink with realloc().
You have to remember to free the memory with free() as in C there is not garbarage collector.
Check: http://www.gnu.org/software/libc/manual/html_node/Memory-Allocation.html#Memory-Allocation
Edit:
#include <stdlib.h>
#include <string.h>
int main(){
char * string;
// Lets say we have a initial string of 8 chars
string = malloc(sizeof(char) * 9); // Nine because we need 8 chars plus one \0 to terminate the string
strcpy(string, "12345678");
// Now we need to expand the string to 10 chars (plus one for \0)
string = realloc(string, sizeof(char) * 11);
// you can check if string is different of NULL...
// Now we append some chars
strcat(string, "90");
// ...
// at some point you need to free the memory if you don't want a memory leak
free(string);
// ...
return 0;
}
Edit 2:
This is the sample for allocate and expand an array of pointers to chars (an array of strings)
#include <stdlib.h>
int main(){
// Array of strings
char ** messages;
char * pointer_to_string_0 = "Hello";
char * pointer_to_string_1 = "World";
unsigned size = 0;
// Initial size one
messages = malloc(sizeof(char *)); // Note I allocate space for 1 pointer to char
size = 1;
// ...
messages[0] = pointer_to_string_0;
// We expand to contain 2 strings (2 pointers really)
size++;
messages = realloc(messages, sizeof(char *) * size);
messages[1] = pointer_to_string_1;
// ...
free(messages);
// ...
return 0;
}
Consider creating apropriate types suitable for you problem. For example, you can create a struct holding a pointer and sn integer length to represent the dynamic arrays.
Do you have some constraints over
the prototyping of the examine()
function and the function you have
to write ? (let's call it
validate())
You say you have 10 examine() functions, does it mean you will have a maximum of 10 messages/results in the array return by validate() ?
I'm a Java programmer with a C background, so maybe I can highlight a few things for you :
there is no equivalent of Array.length in C : you'll have to supply a side integer value to store the effective size of your array
C arrays can't "grow" : you'll have to use pointers and allocate/reallocate the memory pointed by your array begin pointer as this array grows or shrinks
you should already know that there is no notion of class or method in C, however you can use struct, typedef and function pointers to add some kind of object oriented / genericity behavior to your C programs...
Depending on your needs and obligations, arrays might be a good way to go, or not : perhaps you should try to figure out a way of building/finding an equivalent of the java List interface in C, so that you can add, remove/destroy or sort examine result elements without having to duplicate memory allocation / reallocation / freeing code each time you manipulate your result set (and you should perhaps send a header file with your structs/examine functions to describe what you did for now anyway, and express your needs a bit more precisely, so that we can guide you to the good direction)
Don't hesitate to provide more information or ask for specifics about the above bullets points ;)