So for some Uni work I need to create an array using a function (my first time with C functions and pointers) but store the array as a pointer because i dont think C can use arrays in functions? And then also use another function to print out each element in the array. The code i use in main is:
int* x = get_lotto_draw();
print_array(x);
And then my functions are:
int* get_lotto_draw() //Returns an array of six random lottery numbers 1-49
{
int min = 1;
int max = 49;
int counter = 0;
srand(time(NULL));
int r = rand()%(max-min)+min;
int *arrayPointer = malloc(6 * sizeof(int));
for(counter = 0; counter <= 5; counter++)
{
arrayPointer[counter] = r;
}
return arrayPointer;
}
void print_array(int * array) //Print out the content of an array
{
int i = 0;
int printerArray[6] = {0, 0, 0, 0, 0, 0};
for(i = 0; i <= 5; i++)
{
printerArray[i] = array[i];
}
printf("array = %d", array);
printf("printerArray = %d", printerArray);
for(i = 0; i <= 5; i++)
{
printf("Array element %d : %d\n", i, printerArray[i]);
}
}
But im doing something wrong, and either the array isnt getting created correctly, or the print isnt working correctly. Thanks for your time.
What you want is:
void print_array(int * array) //Print out the content of an array
{
int i = 0;
for(i = 0; i <= 5; i++)
{
printf("Array element %d : %d\n", i, array[i]);
}
}
Following two lines could provoke undefined behavior
printf("array = %d", array);
printf("printerArray = %d", printerArray);
you can't use %d here, as array and printerArray decays to pointers in this context and in order to print pointer you should use %p and cast your arrays to void * (thanks to #user3447428 for his comment about cast )
Related
For my studies, I have to write a C function GetEvenNumber:
parameters: array with n integers + array size;
returns tr array which contains even integers from td.
I don't know a priori the length of the array tr.
My below code returns errors:
#include <stdio.h> // define the header file
int *GetEvenNumber(int t[], int size)
{
int tr[];
int j = 0;
for (int i = 0; i < size; i++)
{
if (t[i] % 2 == 0)
{
printf("%d is even \n", t[i]);
tr[j] = t[i];
j++;
}
}
return tr;
}
int main() // define the main function
{
int *t; // = {4, 3, 1, 8, 6 };
int *tr = GetEvenNumber(t, 5);
for (int i = 0; i < 5; i++)
printf("%d \n", tr[i]);
}
I get error:
error: array size missing in 'tr'
int tr[];
warning: function returns address of local variable [-Wreturn-local-addr]
return tr;
How do I fix that? Thanks.
You mentioned that you could not use malloc() to dynamically create tr within GetEvenNumber() to address the two issues raised by your copmiler. This leaves making tr a global variable, or as here pass in the result array tr to be filled out:
#include <stdio.h>
#include <stdlib.h>
void GetEvenNumber(size_t size, const int *td, size_t *size2, int *tr) {
*size2 = 0;
for(size_t i=0; i<size; i++)
if(td[i] % 2 == 0)
tr[(*size2)++] = td[i];
}
int main() {
int td[] = {4, 3, 1, 8, 6 };
size_t size = sizeof(td) / sizeof(*td);
int tr[size];
size_t size2;
GetEvenNumber(size, td, &size2, tr);
for (size_t i=0; i < size2; i++)
printf("%d \n", tr[i]);
}
If the input array td contains uneven elements, then the result array tr have fewer valid elements than the input. I used size2 here to tell caller how many elements are valid in tr. Your code did not assign any values to, in this example, last 3 elements. You don't tell us what should happen with those last elements.
In modern C, if you specify the size before the array in the argument, then you can use the size in array specification which help document what is going on.
The error is due to
int tr[];
because you have to specify the size of your array during its creation.
I suggest trying to add a function that returns the number of even numbers in the array:
int getEvenNum(int t[], int lent){
int numEven = 0; // initialize counter to zero
for(int i = 0; i < lent; i++){ // for each element of the array
if ((t[i] % 2) == 0){ // if it's even,
numEven++; // add 1 to counter
}
}
return(numEven); // finaly returns the value of the counter
}
and then you replace the int tr[]; by int tr[getEvenNum(t, size)]; (maybe there's a ; after the getEvenNum(t, size) but I'm not sure)
Since the array tr can have AT MOST the same number of elements as the original integer array, it would be safe to declare the array with the same size as the array 't[]'.
I have made some changes to your code. Try the following:
#include<stdio.h> // define the header file
void GetEvenNumber(int *t, int* tr, int size, int *pCountEven)
{
int i, j=0;
for (i=0; i < size; i++)
{
if(t[i]%2==0)
{
printf("%d is even \n", t[i]);
tr[j++] = t[i];
}
}
*pCountEven = j;
}
int main() // define the main function
{
int t[] = {4, 3, 1, 8, 6 };
int tr[5], countEven = 0, i;
GetEvenNumber(t, tr, 5, &countEven);
for (i=0; i < countEven; i++)
printf("%d\n", tr[i]);
return 0;
}
Edit: As #chqrlie (who is an experienced coder) pointed out, we can simply return the length of the array instead of taking the address of a variable.
So alternatively, you can try this:
#include <stdio.h> // define the header file
int GetEvenNumber(int *t, int *tr, int size) {
int i, j = 0;
for (i = 0; i < size; i++) {
if (t[i] % 2 == 0) {
printf("%d is even \n", t[i]);
tr[j++] = t[i];
}
}
return j;
}
int main() // define the main function
{
int t[] = { 4, 3, 1, 8, 6 };
int tr[5], countEven = 0, i;
countEven = GetEvenNumber(t, tr, 5);
for (i = 0; i < countEven; i++)
printf("%d\n", tr[i]);
return 0;
}
I have to create functions for print array, fill array witn descending numbers.
I created functions for printing array and creating descending array.But I faced with a problem.
If I use my own function printArray() it prints something unclear. Where is the problem, what i do wrong?
Please, help.
Here is the code in C. value - is value of array
Function for printing array:
void printArray (int arr[]){
int i;
printf("\n");
for(i = 0; i < value; i ++)
printf("%3d ", arr[i]);
}
Function for creating descending array:
int createDescendingArray(int a[])
{
int i;
printf("\nDescending array is created.\n");
for (i = value; i > 0; i--) {
a[i] = i;
}
printArray(a); // print of created array
}
Main function:
int main(){
int arr1[value]; //create new array
arr1[value] = createDescendingArray (arr1); //fill array with descending numbers
}
However when I don't use my print function in function createDescendingArray() and print it in Main funktion with standart method like this:
{int i;
for(i = 0; i < value; i++)
{
a[i]=i;
printf("%3d", a[i]);
}
}
It shows descending array as ascending (look at the picture)
How it works?
You have been using a variable named value in your function which prints array, without initializing it, hence the garbage value.
you should initialize it in the function or pass its start value as an argument to the function.
#include <stdio.h>
#include <stdlib.h>
void printArray(int *arr, int length)
{
int i;
printf("\n");
for (i = 0; i < length; i++)
{
printf("%3d ", arr[i]);
}
}
int *createDescendingArray(const int length)
{
if (length == 0)
return NULL;
int *a = malloc(length * sizeof(int));
;
printf("\nDescending array is created.\n");
for (int i = length-1; i >= 0; i--)
{
a[i] = i;
}
printArray(a, length); // print of created array
return a;
}
int main()
{
int *a = createDescendingArray(20);
printArray(a, 20);
return 0;
}
these changes should most probably do the trick but again, there is no initialization of value in the function that creates array as well
EDIT: stop creation of array if length is 0
EDIT2: fixed code to consider 0 as an element
EDIT3: Fixed code with suggestion from #CraigEstey in comments, tested and working
EDIT4: fixed for loop and removed cast on mallock
The function
int createDescendingArray(int a[])
{
int i;
printf("\nDescending array is created.\n");
for (i = value; i > 0; i--) {
a[i] = i;
}
printArray(a); // print of created array
}
is wrong.
According to the output in your question, it seems that you have defined value as 4 (you are not showing us the code with the definition). In that case, your code for the mentioned function is equivalent to the following:
int createDescendingArray(int a[])
{
printf("\nDescending array is created.\n");
a[4] = 4;
a[3] = 3;
a[2] = 2;
a[1] = 1;
printArray(a); // print of created array
}
I did nothing else to the code than unroll the loop.
Since the array a has a size of 4 elements, valid indices are from 0 to 3. Therefore, by writing to a[4], you are writing to the array out of bounds, causing undefined behavior.
If you had written
for (i = value - 1; i >= 0; i--)
instead of
for (i = value; i > 0; i--)
then the unrolled loop would be:
a[3] = 3;
a[2] = 2;
a[1] = 1;
a[0] = 0;
This is better, because now we have fixed the undefined behavior; you are no longer writing to the array out of bounds. However, this is still not what you want. If you want descending output, your unrolled loop must look like this instead:
a[0] = 3;
a[1] = 2;
a[2] = 1;
a[3] = 0;
This can be accomplished by changing your function to the following:
int createDescendingArray(int a[])
{
int i;
printf( "\nDescending array is created.\n" );
for ( i = 0; i < value; i++ ) {
a[i] = value - i - 1;
}
printArray(a); // print of created array
}
Here is a small test program:
#include <stdio.h>
//NOTE: It is customary for constants to be written upper-case,
//not lower-case, so the line below should normally not be used.
#define value 4
void printArray (int arr[]) {
int i;
printf( "\n" );
for( i = 0; i < value; i++ )
printf("%3d ", arr[i]);
}
int createDescendingArray(int a[])
{
int i;
printf( "\nDescending array is created.\n" );
for ( i = 0; i < value; i++ ) {
a[i] = value - i - 1;
}
printArray(a); // print of created array
}
int main( void )
{
int array[value];
createDescendingArray( array );
}
The output is:
Descending array is created.
3 2 1 0
In this test program, I took over most of your other code, but I did not take over the function main, because it was also causing undefined behavior:
int main(){
int arr1[value]; //create new array
arr1[value] = createDescendingArray (arr1); //fill array with descending numbers
}
In the line
arr1[value] = createDescendingArray (arr1);
you are assigning the return value of the function to a variable, although the function did not return a value. This causes undefined behavior. You may want to consider changing the return type to void in the function declaration, if it does not return a value.
Also, even if the function did return a value, arr1[value] would be writing to the array out of bounds, as valid indices are from 0 to value - 1.
I have a problem where I have this structure
typedef struct _COMPLEX {
double real, imag;
}COMPLEX;
and I need to declare an array of this structure and sum the elements of the array. Here is my code.
#include <stdio.h>
#include <stdlib.h>
void* xmalloc(size_t nrOcteti);
int main()
{
COMPLEX* v = 0, *s = 0;
int n, i;
printf("\n n = ");
scanf("%d", &n);
v = (COMPLEX*)xmalloc((n)*sizeof(COMPLEX));
s = (COMPLEX*)xmalloc(sizeof(COMPLEX));
for(i = 0; i < n; i++)
{
printf("\n v[%d].real and imag:", i);
scanf("%lf %lf", &v[i].real, &v[i].imag);
}
for(i = 0; i < n; i++)
printf("V%d after scan=%.2lf + %.2lf * i\n", i, v[i].real, v[i].imag);
s->real = 0; s->imag = 0;
for(i = 0; i < n; i++)
{
s->real = s->real + v[i].real;
s->imag = s->imag + v[i].imag;
}
for(i = 0; i < n; i++)
printf("V%d after sum=%.2lf + %.2lf * i\n", i, v[i].real, v[i].imag);
printf("\nS=%lf + %lf\n", s->real, s->imag);
if(s) free(s);
s = 0;
if(v) free(v);
v = 0;
return 0;
}
void* xmalloc(size_t nrOcteti)
{
void *p = 0;
p = malloc(sizeof(nrOcteti));
if(!p)
{
fprintf(stderr, "Allocation failed!");
exit(EXIT_FAILURE);
}
return p;
}
After I give the elements of the array I print them everything is alright, but just before the sum the elements of the array are changed(and for multiple test, apparently the element with the index 2 is modified) and the sum at the end is incorrect. And sometimes(I think because of different inputs) it gives me at the end Segmentation fault because of the free().
The array and sum needs to be pointers to that struct and need to be dynamically allocated.
I tried many times and I can't manage to make it work properly.
If somebody can help me solve this it will be a blessing =))
The line
p = malloc(sizeof(nrOcteti));
in the function xmalloc() is wrong. This line is ignoring what is passed as the argument and just allocating for one size_t.
It should be
p = malloc(nrOcteti);
to allocate specified size.
I am trying to save strings into the array and then print them but after the first record is saved the whole array is (according to Visual Studio debugger) filled with nonsense. What am I doing wrong?
int saveRecord(int ixA, int ixB, int length, int* ocupied, char**arr)
{
char r[50];
sprintf(r,"%d: %d - %d", length, ixA, ixB);
arr[*ocupied] = r;
(*ocupied)++;
return 0;
}
int printRecords(int ocupied, char** arr)
{
for (int i = 0; i < ocupied; i++)
{
printf("%s\n", arr[i]);
}
printf("Options: %d\n", ocupied);
return 0;
}
int main()
{
int length = 0, ixA = 0, ixB = 0;
int* ocupied;
int a = 0;
ocupied = &a;
char r[50] = "";
char *arr[250000];
for (int i = 0; i < 250000; i++)
{
arr[i] = "";
}
for (int i = 0; i < 10; i++)
{
scanf("%d %d %d", &ixA, &ixB, &length);
saveRecord(ixA, ixB, length, ocupied, arr);
}
printRecords(*ocupied, arr);
}
The problem is in saveRecord:
char r[50];
sprintf(r,"%d: %d - %d", length, ixA, ixB);
arr[*ocupied] = r;
You're setting a value in your array to r, which is a local array. In this context, arr[*ocupied] contains a pointer to the first element of r. When saveRecord reuturns, r goes out of scope, so the pointer you saved off now points to invalid memory. Returning a pointer to a local variable and subsequently dereferencing it invokes undefined behavior.
Since you want this data to persist outside of the function, you need to dynamically allocate memory instead of using a local variable:
// find out exactly how much space is needed
int len = snprintf(NULL, 0, "%d: %d - %d", length, ixA, ixB);
arr[*ocupied] = malloc(len + 1);
snprintf(arr[*ocupied], len + 1, "%d: %d - %d", length, ixA, ixB);
So I'm trying to write a function that'll search a word in a 2D bulk.
The function returns an (int) array of size [3] with values as the answer.
Here is my main() function:
void main() {
char bulk[L][L];
for (int i = 0; i < L; i++) {
for (int j = 0;j < L;j++)
scanf_s(" %c", &bulk[i][j]);
}
int *arr = search(&bulk, L, "bc");
printf("ARR: %d, %d, %d\n", arr[0], arr[1], arr[2]);
}
And here's the search() function:
int *search(char(*bulk)[L], int size, char *word) {
int arr[3] = { 0,0,0 };
int flag = 9;
for (int i = 0; i < size; i++) {
for (int j = 0; j < size; j++) {
if (bulk[i][j] == *word) {
if (checkRight(bulk, i, j, word)) flag=0;
}
if (flag != 9) {
arr[0] = i;
arr[1] = j;
arr[2] = flag;
printf("ARR: %d, %d, %d\n", arr[0], arr[1], arr[2]);
return arr;
}
}
}
return arr;
}
The checkRight() function works well, it returns 0/1 for if the word exists to the right. The problem is that the two printf's are printing different values.
Output for search(): "ARR: 0,1,0".
Output for main(): "ARR: -858993460, -858993460, 0".
I assume it's pointer-related but I'm struggling with finding the problem. Any ideas?
Thanks a bunch!
return arr;
In here you are returning the address of the first value in the array, this address points to a temporary value inside the stack frame of the function search.
try to pass arr as a parameter or using "static int arr[3]" in order to make the array not temporary.