array address do not increment correctly in C - c

I am trying to make a recursive function to print the content of an array.
The main looks like this:
#include <stdio.h>
static int s_index;
int main(void) { int even[] = {2, 4, 6, 8}; s_index = 0; print(even);}
The print function looks like this:
void print(int * array) {
if(s_index > 3) {
printf("\n"); return;
}
printf(" %d ", *array); ++s_index; print(array + s_index);
}
What I notice is:
if &even is 0x7fffffffdbf0 then (array + s_index) increments as follow with s_index:
s_index = 0 : 0x7fffffffdbf0;
s_index = 1 : 0x7fffffffdbf4;
s_index = 2 : 0x7fffffffdbfc;
it should be 0x7fffffffdbf8!!?
It is blowing my mind, could someone help with that?
Thank you for your answers.

You made a logical mistake in your recursive call. See what happens:
Assume &even = 0x7fffffffdbf0
First call:
array = 0x7fffffffdbf0 ; s_index = 0.
You increase s_index and pass into the second call array + s_index, which yields:
Second call:
array = 0x7fffffffdbf4 ; s_index = 1.
Again, you increase s_index and pass into the third call array + s_index, which yields:
array = (0x7fffffffdbf4) + 2 => 0x7fffffffdbfc
You should only increase array by 1 for each recursive call, and remove s_index completely (that's the point of the recursion, to get rid of global variables)

Please get rid of the global value s_index.Change your func signature as shown below
int main(void)
{
int even[] = {2, 4, 6, 8,10,12};
print(even,(sizeof(even)/sizeof(int)));
}
void print(int * array,int len) {
if( len == 0)
{
printf("\n"); return;
}
else
{
printf(" %d ", *(array));
print(array+1,len-1);
}
}

Please don't do really strange and obscure things for no apparent reason, such as using recursion where simple loops are faster, safer and more readable. Because when you are doing really strange things on purpose, other equally strange things tend to happen unexpectedly.
#include <stdio.h>
void print(int* array, size_t size)
{
for(size_t i=0; i<size; i++)
{
printf("value:%d address:%p\n", array[i], (void*)&array[i]);
}
}
int main(void)
{
int even[] = {2, 4, 6, 8};
print(even, 4);
}

Related

last number in a function array

I want to write a function where I have a given array and number N. The last occurrence of this number I want to return address. If said number cannot be found I want to use a NULL-pointer
Start of the code I've made:
int main(void) {
int n = 3;
int ary[6] = { 1,3,7,8,3,9 };
for (int i = 0; i <= 6; i++) {
if (ary[i] == 3) {
printf("%u\n", ary[i]);
}
}
return 0;
}
result in command prompt:
3
3
The biggest trouble I'm having is:
it prints all occurrences, but not the last occurrence as I want
I haven't used pointers much, so I don't understand how to use the NULL-pointer
I see many minor problems in your program:
If you want to make a function, make a function so your parameters and return types are explicit, instead of coding directly in the main.
C arrays, like in most languages, start the indexing at 0 so if there are N element the first has index 0, then the second has 1, etc... So the very last element (the Nth) has index N-1, so in your for loops, always have condition "i < size", not "i <= size" or ( "i <= size-1" if y'r a weirdo)
If you want to act only on the last occurence of something, don't act on every. Just save every new occurence to the same variable and then, when you're sure it was the last, act on it.
A final version of the function you describe would be:
int* lastOccurence(int n, int* arr, int size){
int* pos = NULL;
for(int i = 0; i < size; i++){
if(arr[i] == n){
pos = &arr[i]; //Should be equal to arr + i*sizeof(int)
}
}
return pos;
}
int main(void){
int n = 3;
int ary[6] = { 1,3,7,8,3,9 };
printf("%p\n", lastOccurence(3, ary, 6);
return 0;
}
Then I'll add that the NULL pointer is just 0, I mean there is literally the line "#define NULL 0" inside the runtime headers. It is just a convention that the memory address 0 doesn't exist and we use NULL instead of 0 for clarity, but it's exactly the same.
Bugs:
i <= 6 accesses the array out of bounds, change to i < 6.
printf("%u\n", ary[i]); prints the value, not the index.
You don't actually compare the value against n but against a hard-coded 3.
I think that you are looking for something like this:
#include <stdio.h>
int main(void)
{
int n = 3;
int ary[6] = { 1,3,7,8,3,9 };
int* last_index = NULL;
for (int i = 0; i < 6; i++) {
if (ary[i] == n) {
last_index = &ary[i];
}
}
if(last_index == NULL) {
printf("Number not found\n");
}
else {
printf("Last index: %d\n", (int)(last_index - ary));
}
return 0;
}
The pointer last_index points at the last found item, if any. By subtracting the array's base address last_index - ary we do pointer arithmetic and get the array item.
The cast to int is necessary to avoid a quirk where subtracting pointers in C actually gives the result in a large integer type called ptrdiff_t - beginners need not worry about that one, so just cast.
First of all, you will read from out of array range, since your array last element is 5, and you read up to 6, which can lead in segmentation faults. #Ludin is right saying that you should change
for (int i = 0; i <= 6; i++) // reads from 0 to 6 range! It is roughly equal to for (int i = 0; i == 6; i++)
to:
for (int i = 0; i < 6; i++) // reads from 0 to 5
The last occurrence of this number I want to return as address.
You are printing only value of 3, not address. To do so, you need to use & operator.
If said number cannot be found I want to use a NULL-pointer
I don't understand, where do you want to return nullpointer? Main function can't return nullpointer, it is contradictory to its definition. To do so, you need to place it in separate function, and then return NULL.
If you want to return last occurence, then I would iterate from the end of this array:
for (int i = 5; i > -1; i--) {
if (ary[i] == 3) {
printf("place in array: %u\n", i); // to print iterator
printf("place in memory: %p\n", &(ary[i])); // to print pointer
break; // if you want to print only last occurence in array and don't read ruther
}
else if (i == 0) {
printf("None occurences found");
}
}
If you want to return an address you need yo use a function instead of writing code in main
As you want to return the address of the last occurence, you should iterate the array from last element towards the first element instead of iterating from first towards last elements.
Below are 2 different implementations of such a function.
#include <stdio.h>
#include <assert.h>
int* f(int n, size_t sz, int a[])
{
assert(sz > 0 && a != NULL);
// Iterate the array from last element towards first element
int* p = a + sz;
do
{
--p;
if (*p == n) return p;
} while(p != a);
return NULL;
}
int* g(int n, size_t sz, int a[])
{
assert(sz > 0 && a != NULL);
// Iterate the array from last element towards first element
size_t i = sz;
do
{
--i;
if (a[i] == n) return &a[i];
} while (i > 0);
return NULL;
}
int main(void)
{
int n = 3;
int ary[] = { 1,3,7,8,3,9 };
size_t elements = sizeof ary / sizeof ary[0];
int* p;
p = g(n, elements, ary); // or p = f(n, elements, ary);
if (p != NULL)
{
printf("Found at address %p - value %d\n", (void*)p, *p);
}
else
{
printf("Not found. The function returned %p\n", (void*)p);
}
return 0;
}
Working on the specified requirements in your question (i.e. a function that searches for the number and returns the address of its last occurrence, or NULL), the code below gives one way of fulfilling those. The comments included are intended to be self-explanatory.
#include <stdio.h>
// Note that an array, passed as an argument, is converted to a pointer (to the
// first element). We can change this in our function, because that pointer is
// passed BY VALUE (i.e. it's a copy), so it won't change the original
int* FindLast(int* arr, size_t length, int find)
{
int* answer = NULL; // The result pointer: set to NULL to start off with
for (size_t i = 0; i < length; ++i) { // Note the use of < rather than <=
if (*arr == find) {
answer = arr; // Found, so set our pointer to the ADDRESS of this element
// Note that, if multiple occurrences exist, the LAST one will be the answer
}
++arr; // Move on to the next element's address
}
return answer;
}
int main(void)
{
int num = 3; // Number to find
int ary[6] = { 1,3,7,8,3,9 }; // array to search
size_t arrlen = sizeof(ary) / sizeof(ary[0]); // Classic way to get length of an array
int* result = FindLast(ary, arrlen, num); // Call the function!
if (result == NULL) { // No match was found ...
printf("No match was found in the array!\n");
}
else {
printf("The address of the last match found is %p.\n", (void*)result); // Show the address
printf("The element at that address is: %d\n", *result); // Just for a verification/check!
}
return 0;
}
Lots of answers so far. All very good answers, too, so I won't repeat the same commentary about array bounds, etc.
I will, however, take a different approach and state, "I want to use a NULL-pointer" is a silly prerequisite for this task serving only to muddle and complicate a very simple problem. "I want to use ..." is chopping off your nose to spite your face.
The KISS principle is to "Keep It Simple, St....!!" Those who will read/modify your code will appreciate your efforts far more than admiring you for making wrong decisions that makes their day worse.
Arrays are easy to conceive of in terms of indexing to reach each element. If you want to train in the use of pointers and NULL pointers, I suggest you explore "linked lists" and/or "binary trees". Those data structures are founded on the utility of pointers.
int main( void ) {
const int n = 3, ary[] = { 1, 3, 7, 8, 3, 9 };
size_t sz = sizeof ary/sizeof ary[0];
// search for the LAST match by starting at the end, not the beginning.
while( sz-- )
if( ary[ sz ] == n ) {
printf( "ary[ %sz ] = %d\n", sz, n );
return 0;
}
puts( "not found" );
return 1; // failed to find it.
}
Consider that the array to be searched is many megabytes. To find the LAST match, it makes sense to start at the tail, not the head of the array.
Simple...

equality between lists and conversion of char into int within a list- language c

#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <stdbool.h>
#define BTT 10
void create_pirolito(int list[BTT]);
void create_retardado(int list[BTT]);
void compare_lists(int list1[BTT], int list2[BTT]);
void prints_both(int list1[BTT], int list2[BTT]);
void create_pirolito(int list[BTT])
{
for(int i=0; i<BTT; i++)
{
list[i]=rand()%10;
}
}
void create_retardado(int list[BTT])
{
for(int i=0; i<BTT; i++)
{
list[i]=rand()%20;
}
}
void prints_both(int list1[BTT], int list2[BTT])
{
int i=0;
int j=0;
for(int z=0; z<BTT; z++)
{
printf("(%2d %2d)\n", list1[i], list2[j]);
i++;
j++;
}
}
void compare_lists(int list1[BTT], int list2[BTT])
{
char x='X';
for(int i=0; i<BTT; i++)
{
for(int j=0; j<BTT; j++)
{
if(list1[i]==list2[j])
{
list1[i]==(int)(x);
}
}
printf("\n");
}
}
int main()
{
int pirolito[BTT];
int retardado[BTT];
create_pirolito(pirolito);
create_retardado(retardado);
compare_lists(pirolito, retardado);
prints_both(pirolito, retardado);
return 0;
}
My intention is to compare two different lists and whenever there are equalities, the number saved in that index is exchanged for the letter 'X', this only in the pirolito list, but when I compile there is no error only a large space and then follow the printing of the two lists but without the character 'X' in the respective equalities. how can I print a list with X on repeated numbers like that:
lists:
pirolito[3, 6, 8, 9, 7, 3, 6, 1, 0, 4]
retardado[3, 17, 12, 18, 11, 16, 6, 10, 0, 15]
output:
[X, 6, 8, 9, 7, 3, X, 1, X, 4]
[3, 17, 12, 18, 11, 16, 6, 10, 0, 15]
Removed unused include files.
(Main issue 1 of 2) list1[i]==(int)(x); is a comparison. You want = for assignment here.
Reworked the two create_ functions into one called init() by passing in the modulo value. create usually means the function allocates the variable but in this case caller allocates the arrayand just wants the function to initialize it.
(Not fixed) compare implies a read-only operation but you update the first list. Maybe return a new list instead? I added a comment and made the 2nd list a const to highlight the odd usage. Another good option is to combine compare and print functions which just generate the expected output but leave both lists read-only. The fact that the two functions share the MARKER constant is a strong hint that maybe they should be combined.
(Main issue 2 of 2) prints_both() prints out decimal numbers so it will print 88 and not 'X'. To do that you need to detect if it's 88 and then print it as a char '%c'. It's a bad design, btw, when the value domain overlaps with your special values. See above.
prints_both() uses 3 different index variables with the same values. Just use one.
prints_both() was printing a new line which doesn't seem to serve a purpose.
(Not fixed). Consider passing in the length to the functions that need it instead of relying on the BTT constant.
Here is the resulting program:
#include <stdio.h>
#include <stdlib.h>
#define BTT 10
#define MARKER 'X'
// list1 may be updated
void compare_lists(int list1[BTT], const int list2[BTT]) {
for(int i=0; i<BTT; i++) {
for(int j=0; j<BTT; j++) {
if(list1[i]==list2[j]) {
list1[i]=MARKER;
}
}
}
}
void init(int list[BTT], int modulo) {
for(int i=0; i<BTT; i++) {
list[i]=rand() % modulo;
}
}
void prints_both(const int list1[BTT], const int list2[BTT]) {
const char *normal = "(%2d %2d)\n";
const char *duplicate = "(%2c %2d)\n";
for(int i=0; i<BTT; i++) {
printf(list1[i] != MARKER ? normal : duplicate, list1[i], list2[i]);
}
}
int main(void) {
int pirolito[BTT];
int retardado[BTT];
init(pirolito, 10);
init(retardado, 20);
compare_lists(pirolito, retardado);
prints_both(pirolito, retardado);
}
And here is an example run:
( X 2)
( X 7)
( X 10)
( 5 19)
( X 3)
( 5 6)
( X 0)
( X 6)
( 9 12)
( 1 16)
printf:
%d - converts a signed integer into decimal representation
Your output will never show the character X, because the instruction is to print the decimal representation of the specific value.
Therefore in your print function:
if (list1[i] == (int)'X')
printf("(%c %2d)\n", list1[i], list2[j]); //output X
else
printf("(%2d %2d)\n", list1[i], list2[j]); //output decimal
You can of course omit the %c conversion and use this statement instead (since we know that list1[i] == 'X'):
printf("(X %2d)\n", list2[j]); //output X

A function in C runs for a set of values but gives Segmentation Fault: 11 for another

I am trying to find unique non-zero intersection between two sets. I have written a program which works for some set of arrays but gives segmentation fault for some. I have been trying to figure out why but have failed, any help will be greatly valued. The thing is the functions defined (NoRep and ComEle) are working fine but are unable to return the value to the assigned pointer in the case when Seg Fault is shown. Below is the code:
#include<stdio.h>
#include<stdlib.h>
#include<math.h>
#include<string.h>
int* ComEle(int ar_1[], int size_ar1, int ar_2[], int size_ar2);
int* NoRep(int a[], int l1);
int main ()
{
// Case 1: Gives segmentation fault
int A[10] = {1,1,0,2,2,0,1,1,1,0};
int B[10] = {1,1,1,1,0,1,1,0,4,0};
int *C = ComEle(A,10,B,10); printf("check complete\n");
// //Case 2: Does not give segmentation fault
// int A[4] = {2,3,4,5};
// int B[4] = {1,2,3,4};
// int *C = ComEle(A,4,B,4); printf("check complete\n");
}
//---------------- Local Functions --------------------//
int* ComEle(int ar_1[], int size_ar1, int ar_2[], int size_ar2) {
// sort of intersection of two arrays but only for nonzero elements.
int i=0, j=0, cnt1 = 0;
int temp1 = size_ar1+size_ar2;
int CE1[temp1]; for(i=0;i<temp1;i++) {CE1[i] = 0;}
/* Size of CE1 is knowingly made big enough to accommodate repeating
common elements which can expand the size of resultant array to
values bigger than those for the individual arrays themselves! */
for(i=0;i<size_ar1;i++) {
j = 0;
while(j<size_ar2) {
if(ar_1[i]==ar_2[j] && ar_1[i]!=0) {
CE1[cnt1] = ar_1[i];
cnt1++;
}
j++;
}
}
// Have to remove repeating elements.
int *CE = NoRep(CE1, cnt1);
for(i=0;i<(CE[0]+1);i++) {printf("CE:\t%d\n", CE[i]);}
printf("ComEle: %p\n",CE);
return(CE);
}
int* NoRep(int a[], int l1) {
int cnt = 0, i = 0, j =0;
int *NR; NR = (int*)calloc((l1), sizeof(int));
//int NR[l1]; for(i=0;i<l1;i++) {NR[i] = 0;}
for(i=0;i<l1;i++) {
j = 0;
while(j<i) {
if(a[i]==a[j]) {break;}
j++;
}
if(j == i) {
cnt++;
NR[cnt] = a[i];
}
}
NR[0] = cnt; // First element: # of relevant elements.
printf("NoRep: %p\n",NR);
return(NR);
}
Thanks again for your help!
Take a look at this code:
int temp1 = size_ar1+size_ar2;
int CE1[temp1]; for(i=0;i<temp1;i++) {CE1[i] = 0;}
/* Size of CE1 is knowingly made big enough to accommodate repeating
common elements which can expand the size of resultant array to
values bigger than those for the individual arrays themselves! */
for(i=0;i<size_ar1;i++) {
j = 0;
while(j<size_ar2) {
if(ar_1[i]==ar_2[j] && ar_1[i]!=0) {
CE1[cnt1] = ar_1[i];
cnt1++;
}
j++;
}
}
Here you have nested loops, i.e. a for-loop with a while-loop inside. So - in worst case - how many times can cnt1 be incremented?
The answer is size_ar1 * size_ar2
But your code only reserve size_ar1 + size_ar2 element for CE1. So you may end up writing outside the array.
You can see this very easy by printing cnt1 inside the loop.
In other words - your CE1 is too small. It should be:
int temp1 = size_ar1*size_ar2; // NOTICE: * instead of +
int CE1[temp1]; for(i=0;i<temp1;i++) {CE1[i] = 0;}
But be careful here - if the input arrays are big, the VLA gets huge and you may run in to stack overflow. Consider dynamic memory allocation instead of an array.
Besides the accepted answer: I have been missing a break statement in the while loop in ComEle function. It was not giving me the expected value of cnt1. The following will be the correct way to do it:
for(i=0;i<size_ar1;i++) {
j = 0;
while(j<size_ar2) {
if(ar_1[i]==ar_2[j] && ar_1[i]!=0) {
CE1[cnt1] = ar_1[i];
cnt1++;
break;
}
j++;
}
}
This will also do away with the requirement for a bigger array or dynamic allocation as suggested (and rightly so) by #4386427

C Pointer to an Array example stops working

I'm working on an example and my code is stopped woking when I run it.(Note that I translated the question to English so sorry for grammar mistakes.)
Here is the question:
myShrink() function's prototype is like this:
void myShrink(int *param1, const int param2);
myShrink() function should find the average of the array param1 then should increment the element by 1 if its less than average, or should decrement the element by 1 if it's more than average. param2 is a number of elements in an array.
Here is the content of the main() function:
void myStretch(int *param1, const int param2);
int main () { int myArray[] = {2, 4, 2, 4, 2, 4};
int index;
myStretch(myArray, 6);
printf("UPDATED ARRAY: ");
for(index = 0; index < 6; index++){
printf("%d\t", myArray[index]);
}
return 0;
}
---------The result when we run the program:-----
UPDATED ARRAY: 1 5 1 5 1 5
Now this was the question part what we need to is basically programming the content of myShrink() function and here is my work:
void myShrink(int *param1, const int param2)
{
int array[param2];
param1=array;//Using pointer to point elements of array
int average=0;
int i,j;
for(i=0;i<param2;i++)
{
average+=*(param1 + i);//Adding each element of array
}
average=average/param2;//Then dividing result to param2 to find average
for(j=0;j<param2;j++)
{
if(*(param1+j)<average)//if below average
{
*(param1+j)+=1;//increment
}
else if(*(param1+j)>average)//if above average
{
*(param1+j)-=1;//decrement
}
}
}
But its stops working when I run it. Where I did make mistake and how can I fix it?
Just do this:
#include<stdio.h>
void myStretch(int *param1, const int param2);
int main () { int myArray[] = {2, 4, 2, 4, 2, 4};
int index;
myStretch(myArray, 6);
printf("UPDATED ARRAY: ");
for(index = 0; index < 6; index++){
printf("\n%d\t", myArray[index]);
}
return 0;
}
void myStretch(int *param1, const int param2)
{
int average=0;
int i,j;
for(i=0;i<param2;i++)
{
average+=*(param1 + i);//Adding each element of array
}
average=average/param2;//Then dividing result to param2 to find average
for(j=0;j<param2;j++)
{
if(*(param1+j)<average)//if below average
{
(*(param1+j))+=1;//increment
}
else if(*(param1+j)>average)//if above average
{
printf("%d ",(*(param1+j)));
(*(param1+j))-=1;//decrement
}
}
}
Now first thing: your result is wrong. It should be 3 3 3 3 3 3. As the average in this case is 3 and therefore 2 will become 3 and 4 will also become 3. Secondly you don't have to assign a new array inside the function. Just do it this way. Third mistake:
*(param1+j)>average
should be replaced by
(*(param1+j))>average
and similarly for less than sign.
UPDATE: Also note that many people argue that array[param2] is legal or not. When you declare such an array they are called Variable Length Array(VLA). This is allowed in modern C compilers but older compilers like Turbo C don't allow.
In below myShrink function, after 'param1=array;' statement param1 start pointing to array which has garbage inside.
void myShrink(int *param1, const int param2){
int array[param2];
param1=array;//Using pointer to point elements of array
int average=0;
int i,j;
//debug code to shows param1 points to array which has garage inside
int index =0 ;
for(index = 0; index < 6; index++){
printf("myDebug: %d\n", param1[index]);
}
for(i=0;i<param2;i++)
{
average+=*(param1 + i);//Adding each element of array
}
average=average/param2;//Then dividing result to param2 to find average
for(j=0;j<param2;j++)
{
if(*(param1+j)<average)//if below average
{
*(param1+j)+=1;//increment
}
else if(*(param1+j)>average)//if above average
{
*(param1+j)-=1;//decrement
}
}}

Array shows its pointer instead of its value

I'm stuck in some trouble, unfortunately I'm still learning the details of this language.
I have the following code
#define SIZE 5
typedef struct
{
int start;
int end;
int nElements;
int vetor[SIZE];
} TSTACK;
and I try to inser values in its array using the following function:
void Push(TSTACK *s, int elementInsert)
{
if(IsFull(s))
{
printf("%s\n", "# ERROR: full.");
}
else
{
s->end++;
if(s->end == SIZE)
{
s->end = 0;
}
s->vetor[s->end] = elementInsert;
s->nElements++;
}
}
and I use the following function to show elements:
void Display(TSTACK *s)
{
int i;
if (isEmpty(s))
{
printf("%s\n", "# ERROR: empty");
}
else
{
for (i = 0; i < s->nElements; i++)
{
printf ("value: %d\n", s->vetor[i]);
}
}
}
My question is that I don't get the same result when I add different amount of elements, when I insert 5 elements, the Display function display all the elements correctly, but when I insert less than 5, the first item appears to be its pointer:
The following main results in 4201166, 3, 5, 7
int main(void)
{
TSTACK test;
test.start = 1;
test.end = 0;
test.nElements = 0;
Push(&test, 3);
Push(&test, 5);
Push(&test, 7);
Push(&test, 3);
Display(&test);
}
The following main results in 5, 3, 5, 7, 3
int main(void)
{
TSTACK test;
test.start = 1;
test.end = 0;
test.nElements = 0;
Push(&test, 3);
Push(&test, 5);
Push(&test, 7);
Push(&test, 3);
Push(&test, 5);
Display(&test);
}
Can someone show me where I am wrong?
When you "insert" an element, you do it at
s->vetor[s->end]
But before you do that you increase s->end, so the first element will be at s->vetor[1]. Since the first element (s->vetor[0]) is not initialized, you will have a random value there. That is the reason you have a strange value first in the four-value insert.
When you insert a fifth value, you have the check for s->end == SIZE where you set s->end to zero, so the last value in that case will end up in the first place in the array.
The solution, that will solve both of the above problems, is to increase s->end after you assigned the value to the array.
When you print the stack:
for (i = 0; i < s->nElements; i++)
{
printf ("value: %d\n", s->vetor[i]);
}
You are starting at index 0, but your stack implementation starts at index 1, so when you have less than 5 elements the first item is not initialized. Perhaps you can fix this by changing start value to 0.
First problem: Local variables aren't initialized, they contain garbage unless you initialize them.
Second problem: You start assigning at array index 1 instead of 0. Only when you insert five elements will it work, because you check if end == SIZE and if so set end = 0, making the fift insert set the first element vetor[0].

Resources