I'm trying to build a function that takes 1 param: the number as char[] and returns a char** with the divisors as strings.
I have come up with the following function, which works only for some numbers.
char** calc_div(char nr[100])
{
int nri,i,ct=0;
char **a = (char**)malloc(sizeof(char*));
nri = atoi(nr);
for(i=0;i<sizeof(char*);i++)
a[i] = (char*)malloc(sizeof(char));
for(i=1;i<=nri;i++)
if(nri % i == 0)
{
sprintf(a[ct++],"%d",i);
}
return a;
}
This works for numbers like 22, 33, 77 but not for 66 or 88 (it just gets stuck somewhere). Could anyone help me?
So many problems in such a small space...oh dear!
Let's think about the interface first...how does the calling code know how many values are returned? Presumably, there must be a null pointer at the end of the array of pointers. Also, for each number bigger than 1, we know that 1 and the number itself will be divisors, so we are going to need an array of at least 3 pointers returned. If a number is not prime or one, then there will be more values to push into the array. Therefore, one of the things we'll need to do is keep tabs on how many values are in the array. Also, the memory release code will need to step through the returned array, releasing each string before releasing the array overall.
So, we get some ideas about what the code should do. How does your code fare against this?
char** calc_div(char nr[100])
{
int nri,i,ct=0;
char **a = (char**)malloc(sizeof(char*));
This allocates one entry in the return array. We now know we need at least 3 times as much space, and we also have to keep a record of how much space was allocated.
nri = atoi(nr);
for(i=0;i<sizeof(char*);i++)
a[i] = (char*)malloc(sizeof(char));
This allocates 4 or 8 strings of size 1 byte each, assigning them to successive elements of the array of size 1 previously allocated. This is a guaranteed buffer overflow on the array a. Plus, because the strings are only big enough to hold the null at the end of string, you can't put any answers in there. You should probably be allocating strlen(nr)+1 bytes since nr is one of the numbers you'll need. It is not remotely clear that numbers are limited to either 3 or 7 factors (since you also need to allow for the terminating null pointer).
for(i=1;i<=nri;i++)
if(nri % i == 0)
{
sprintf(a[ct++],"%d",i);
}
The code inside the body of the if statement will have to be ready to do memory allocation for the new factor and for the array as and when necessary.
return a;
}
After
char **a = (char**)malloc(sizeof(char*));
a has space for 1 pointer to char ...
for(i=0;i<sizeof(char*);i++)
a[i] = (char*)malloc(sizeof(char));
but you try to write to more than that single element (unless sizeof(char*) happens to be 1).
Related
So basically I have an array with a size of 5 and I want to count how many elements it has inside it.
int main()
{
int size;
char ola[5];
ola[0] = 'p';
size = sizeof(ola);
printf("%d\n", size);
return 0;
}
This code returns 5, but I expected 1.
What should I change?
The C standard does not provide any usable concept of elements in an array being used or unused. An array is simply a sequence of elements. It is up to you to track how many elements in it are of interest to you; you must write your own code for this.
You can do this by keeping a separate counter, by using a particular element value to denote that an element is “unused,” by using a particular element value to denote that an element ends the elements of interest, by calculating the end from related information, or by other means.
The C library includes many routines that use the third method, where the “null character,” with value zero, is used to mark the end of a string of characters. When you use this method, be sure to include room for the terminating null character in any array. For example, if you want an array to hold strings of length up to n characters, define the array to have at least n+1 elements.
Keep a count as you add elements to the array, rather than using sizeof (which returns the total capacity of the array in bytes), for example
#include <stdio.h>
int main(void)
{
int size = 0; // initialize size
char ola[5] = ""; // also initialize ola (with 5 '\0's)
ola[size++] = 'p'; // use and increment size
// size = sizeof(ola); // size is already updated
printf("%d\n", size);
// one more character
ola[size++] = 'o';
printf("%d\n", size);
printf("The string is [%s]\n", ola);
return 0;
}
It returns 5 because it is the size of your array, you could try:
size = sizeof(ola[0]);
To get the response 1, this mean that you are getteing exatly the size of the element, and not the size of whole array.
i only would know how to store value in the last position of the array, with the code below:
int main(int argc, char *argv[]){
int x[2][2];
int i, j;
x[2][0] = 1;
printf("%d", x[2][2]);
}
Thanks!
The last element in your matrix is in x[1][1]; just put in this position. Your vector has only four positions indexed starting in 0 going to 1 twice (for each dimension); that is, neither x[2][0] nor x[2][2] is valid — they access out of the bounds of the array.
The first element of an array in C is numbered as 0, and when creating an array, the size inputted will represent the number of elements in the said array. Hence, the first element of an array of 2 would be labelled as 0 and the second as 1, the third(2) not being allocated.
So, for example, making an array of 4 variables:
int i[4]
Would allocate four ints int memory,
i[0]
i[1]
i[2]
i[3]
these being the valid spots of the array. Of course this applies to 2D arrays like yours.
If you wish a 3-large array(Like I suppose from your use of the array element zero and two), you simply need to, as you probably understood, declare an array with a size of [3].
Keep in mind accessing invalid spots in an array might not cause a crash of your program if it had allocated some memory at the emplacement it tried to access, sometimes yielding to funny results caused by these unexpected values.
Hope this helps.
Can someone explain what would happen? Is it really necessary to start at index 0 instead of 1 (which would be easier for me)?
You can do whatever you want, as long as your array subscript is strictly less than the size of the array.
Example:
int a[100];
a[1] = 2; // fine, 1 < 100
What happens if I don't use zero-based array in C
Well, you can't. C arrays are zero based, by definition, by standard.
Is it really necessary to start at 0?
Well, this is no rule to prevent you from leaving index 0 unused, but then, you'll almost certainly not get the desired result.
Using non-zero based arrays in C is possible, but not recommended. Here is how you would allocate a 1-based array of 100 integers:
int * a = ((int*)malloc(100*sizeof(int)))-1;
The -1 moves the start of the pointer back one from the start of the array, making the first valid index 1. So this array will have valid indices from 1 to 100 inclusive.
a[1] = 10; /* Fine */
a[100] = 7; /* Also fine */
a[0] = 5; /* Error */
The reason why this isn't recommended is that everything else in C assumes that pointers to blocks of memory point to the first element of interest, not one before that. For example, the array above won't work with memcpy unless you add 1 to the pointer when passing it in every time.
Hello I for an exercise at University i need to malloc an array with this way. The array at stars has 1 slot. If the inputs are more than one then the array is doubled. If the inputs are more than 2 then it is doubled again etc. After this I have to crop the array to fit to the number of inputs. For example if I have 5 inputs then the array will have 8 slots and I must make it to have 5 slots which I cannot figure out how. Here is my code so far:
nameInfoT* ReadNames(int* size){
nameInfoT* names ;
int array_size=1;
int entries=0;
char input[length];
names=(nameInfoT*) malloc(sizeof(nameInfoT)*array_size);
do{
scanf("%s",input);
if(!strcmp(input,"END")) break;
if(entries==array_size){
array_size=array_size*2;
names= (nameInfoT*) realloc(names,sizeof(nameInfoT)*array_size);
}
names[entries].name=(char*)malloc(sizeof(char)*strlen(input));
strcpy(names[entries].name,input);
entries++;
}while(1);
printf("there are %d free spaces \n",array_size-entries);
*size=entries;
printf("there are %d entries \n",*size);
int i;
for(i=array_size;i>entries;i--){
free(names[i]);//here it won't compile
}
return names;
}
You can only free the result of malloc/calloc/realloc. You cannot free individual elements. So in the end you can simply realloc again to the desired final size.
You have a couple of other problems:
1) when you allocate space for the input string, you need to add 1 to keep the trailing '\0'
2) before your realloc, you should have a switch statement which will take the array_size and use that to determine the new size. If I understand your problem, you want to go from 1 -> 2 -> 4 -> n (where n is the next number). Your realloc code just doubles each time. You need to change that.
3) when you free the entries, you need to be careful since you don't seem to be freeing the 'name' member of the class/struct.
4) after freeing the members in the loop, then do one free on the names class/struct.
I could look into it more carefully later.
This question already has answers here:
Is calloc(4, 6) the same as calloc(6, 4)?
(7 answers)
Closed 4 months ago.
What is the difference between calloc(10,4) and calloc(1,40)?
I see this behavior:
Thing** things = (Thing**)calloc(1, 10 * sizeof(Thing*));
// things[0] != 0
Thing** things = (Thing**)calloc(10, sizeof(Thing*));
// things[0] == 0
I would like to understand why. Edit: losing my mind is why, both seem to result in zero now... To at least make the question interesting, why doesn't calloc just take a single argument, like malloc?
In practice it's the same. But there's one important feature this gives you.
Say that you're receiving some data from the network and the protocol has a field that specifies how many elements an array will contain that will be sent to you. You do something like:
uint32_t n = read_number_of_array_elements_from_network(conn);
struct element *el = malloc(n * sizeof(*el));
if (el == NULL)
return -1;
read_array_elements_from_network(conn, el, n);
This looks harmless, doesn't it? Well, not so fast. The other side of the connection was evil and actually sent you a very large number as the number of elements so that the multiplication wrapped. Let's say that sizeof(*el) is 4 and the n is read as 2^30+1. The multiplication 2^30+1 * 4 wraps and the result becomes 4 and that's what you allocate while you've told your function to read 2^30+1 elements. The read_array_elements_from_network function will quickly overflow your allocated array.
Any decent implementation of calloc will have a check for overflow in that multiplication and will protect against this kind of attack (this error is very common).
It is the same. The allocation does number of elements times size of one element to allocate the size.
It does not matter as it will be one block.
It's virtually the same, as the allocation block is contiguous. It allocates number_of_elements * size_of_element, so 10 elements of size 4 or 1 element of size 40 both end up allocating 40 bytes.
calloc(10,4) will allocate 10 no of elements where the size will be 4, whereas calloc(1,40) will allocated one elment with size of 40.
Ref : http://www.tutorialspoint.com/c_standard_library/c_function_calloc.htm
By size i mean for every element allocated.