C Compare array elements using pointers - c

I'm trying to make a program to compare array elements using pointers and to give me some result; I make this simple program just to test if it works but I don't know why.. if i enter equals numbers nothing happes. So the first variable of the array is ptr so ptr + 1 means the next element, if i enter directly ch[0] == ch[1] it works. After that I want to make the program to compare characters if are the same.
#include <stdio.h>
#include <stdlib.h>
#include <conio.h>
int main()
{
int ch[2];
int *ptr = &ch;
scanf("%d%d", &ch[0], &ch[1]);
printf("Numbers to compare %d and %d", *ptr, *ptr + 1);
if (*ptr == *ptr + 1){
printf("Equals numbers\n");
}
return 0;
}

Always remember a quick rule.
If the elements are i th and i+1 th index of some array, the the way to access them without using pointer is
a[i] & a[i+1]
Now if you want to get the address of these values without using pointer, then you do &a[i] and &a[i+1]
Now if you want to perform the above two tasks with pointer, then remember array name itself is a pointer to it. So if you want to get the address of i th and i+1 th element, the it will be simply
(a + i) and (a + i + 1)
Now if you want to get the values at these locations, then simply de-reference it like
*(a + i) and *(a + i + 1)
That's why in this case, it will be *ptr == *(ptr + 1)
Note: &a[i] is equivalent to (a+i)
and a[i] is equivalent to *(a+i)
Note 2: If you are not using Turbo C in windows system, then it is not recommended to use conio.h because it is not platform independent. I recommend you to move from Turbo C & conio.h

To explain #kaylum comment which is correct:
You had if (*ptr == *ptr + 1) now the *ptr part is correct but the right hand side of the == is incorrect because the way you have it your dereferencing ptr and then adding one to that value. However you want to increment ptr and then dereference hence why you need the ()

you are making mistake
int *ptr=&ch;
*ptr == *ptr + 1
printf("Numbers to compare %d and %d",*ptr,*ptr+1);
replace it with *ptr=ch becoz ch is an integer array so if you assign it directly to *ptr it will return the first address of ch i.e ch[0] address will be return
difference between using *ptr+1 and *(ptr+1)
*ptr+1 is similar to ch[0]+1 and *(ptr+1) is similar to ch[1]
you are doing *ptr+1 this will increment your first position of array ch so your output will Number to compare 1 and 2 even if your input is 1 and 5 replace it with *(ptr+1)

Related

Can I use scanf with pointers?

This week my teacher of C language explained that we can use * (array + i) rather than array [i], he also mentioned the advantages of using this "new method". It's ok so far and then he gave us some exercises to do, in one of them I'm trying to use along with scanf this new method.
I know how to do it like this:
printf("%i", *(array + i));
My doubt is, how can I use *(array + i) in an scanf, or it's not possible?
scanf("%i", *(array + i));
for(i = 0; i < size; i++)
{
printf("Insert number: %i", i+1);
scanf("%i", *(array + i); // it's not working.
}
The argument to scanf must be a pointer to the variable you want to store the result in, so you shouldn't dereference it:
scanf("%i", array+i);
This is simply the opposite of the way you deal with ordinary variables in printf() and scanf():
printf("%i", var);
scanf("%i", &var);
Adding & is analogous to removing *.
*(array + i) == array[i]
array + i == &array[i]
This means:
printf( "%i", array[i] ) == printf( "%i", *(array + i) );
scanf( "%i", &array[i] ) == scanf( "%i", array + i );
he also mentioned the advantages of using this "new method"
What advantages would those be? In my experience, using *(a + i) over a[i] tends to result in code that's less clear, and easier to get wrong.
In C, a[i] actually gets translated to *(a+i); it's called syntactic sugar
Arrays are referenced using their variable names and individual array elements are referenced as the starting address + (element position*size of each element)
As mentioned in the Barmar's Answer - you should be using
a+i instead of *(a+i)
because the scanf function needs an address as argument to store the input, not the dereferenced value
Indeed, you have to use scanf(3) with pointers, as it is not allowed to pass a nonpointer value. But what you cannot do (except if the final pointed value is also a pointer) is to use them with dereferenced pointers (what is indeed done in your example, when you write *(array + i)) If you want to use the pointer you can for example, pass array + i which is a perfectly valid pointer, that points to the i-esim element of array.

Pointer dereferencing in a variable and in an array in C [closed]

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 5 years ago.
Improve this question
I am somewhat confused on pointers. I have two of them in the following code I'm using and they are working but I'm not 100% sure why they are working.
The first is
char *note = "A7";
The second is
char *octFreq[15] =
{"1","55","2","110","3","220","4","440","5","880","6","1760","7","3520"};
They both get to the value of each though I had to use * before the array and not before the single variable. I am able to get the value of note by just using note though cannot do this for octFreq.
Here is the line of code I'm a little confused by and all of the code immediately follows.
if(note[1] == *octFreq[x]){//WHY DO I HAVE TO DEREFERENCE octFreq and not note????
#include <stdio.h>
#include <cs50.h>
#include <stdbool.h>
#include <string.h>
int main(void){ //Notes are in this order C D E F G A B
char *note = "A7";
//char freq;
int semiUpDown = 0;
char *octFreq[15] = {"1","55","2","110","3","220","4","440","5","880","6","1760","7","3520"};
//int noteIndex[7] = {1, 2, 3, 4, 5, 6};
if(note[1] == '#'){
semiUpDown = 1;
//Up one semitone or multipled by 2^1/12
}else if(note[1] == 'b'){
semiUpDown = -1;
//Down one semitone or divide by 2^1/12
}
if(semiUpDown == 0){//This means no flat or sharp
if(note[0] != 'B' || note[0] != 'b'){//Check the first letter is CDEFGA
if(note[0] == 'A' || note[0] == 'a'){//Check to see if it's the baseline
for(int x = 0; x < 13; x++){
//printf("%s\n\n", noteA[x]);
if(note[1] == *octFreq[x]){//WHY DO I HAVE TO DEREFERENCE octFreq and not note????
//freq = *octFreq[x+1];
// printf("Found it: %s\n\n", noteA[x]);
printf("This is the frequency: %s\n\n", octFreq[x+1]);
}
}
}
}
}
}
char *note = "A7" means that you have declared a pointer to a char array. Therefore you can access its elements by note[0] etc. like any other array.
char *octFreq[15] means that you declared a pointer to an array of char pointers.
octFreq[15] would reach to the char pointer at the index 15.
*octFreq[15] would reach to the char pointed by the char pointer at the index 15.
if(note[1] == *octFreq[x]) is only comparing a single character so it works for A7 but won't work for A110. There you need to use strcmp which uses char * to compare entire strings. Something like this;
if (0 == strcmp(&note[1], octFreq[x]))
The index operator ([]) is an automatic dereference of a specific integer amount from the base pointer value.
So, to explain. A pointer is really just a variable that holds a memory location. This memory location is a specific integer value (i.e. 4000, 9320, etc.). You can add, subtract, multiply, divide, etc., this variable to get a new memory location that points to a valid value of the type the pointer points to (in this case, a char).
Your first pointer variable, note, could be defined as such:
char* note = new char[3];
*(note + 0) = 'A';
*(note + 1) = 'F';
*(note + 2) = '\0'; \\all character arrays have an implicit null-terminator
Each character can be then referenced as: note[x], where 0 <= x <= 2. note[x] can also be read as *(note + x).
char* note = "A7"; // here you define note - array of chars ('A', '7', '\0'). When you access note[1], you get the second symbol ('7').
char* octFreq[15] = {"1","55","2","110","3","220","4","440","5","880","6","1760","7","3520"}; // here you define octFreq - array of arrays of char. There are 15 arrays, were every has type char*. So when you access octFreq[3], you getting the fourth element of array of arrays of char and it is array of chars ("110" in this example). Then you apply * to this array of chars and you get the first element of this array (it is bold one here -> "110"), because the pointer to array of chars (char*) actually points to it's first element.

Explain this method of taking input in array [closed]

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 5 years ago.
Improve this question
for(int i = 1 ; i <= n ; ++i)
{
scanf("%d" , arr + i);
}
explain this method of taking input in array.
Generally, I try this method for entering elements in array.
for(int i = 1 ; i <= n ; ++i)
{
scanf("%d" , &arr[i]);
}
what is the difference between these two methods?``
I found the former one used in competitive programming...
Here is the "normal" way of using scanf to read n elements into an array:
for(int i = 0; i < n; i++)
scanf("%d", &arr[i]);
Note well that I am calling
scanf("%d", &arr[i]);
with an &, so that I pass a pointer to array[i], so that scanf can fill in that element. (One of the surprising things to remember about scanf is that you must always pass it pointers to fill in, unlike printf, where you pass values to print.)
But if we know how pointers and arrays and pointer arithmetic work, we can then see that this alternative form is equivalent:
scanf("%d", arr + i);
The reason is that when when we mention the array arr in an expression like this, what we get is a pointer to the array's first element. And then arr + i is a pointer to the array's i'th element, which is exactly what we want to pass to scanf, as before.
(Also, you'll notice that I have quietly changed your loop from i = 1; i <= n to i = 0; i < n. Arrays in C are 0-based, so you always want your subscripts to run from 0 to n-1, not from 1 to n.)
The thing is, the second is wrong while the first one is correct - but even then the first one is not robust in that - it doesn't check the return value of scanf().
scanf()'s %d format specifier expects an address of int variable. In the second case you provided the int variable itself (if you enabled compiler warnings this would generate warning message) and the first case you provided the address which results in correct behavior.
In case there are n elements then both of the scanf() would invoke Undefined Behavior because you are accessing an array index out of bound. (Arrays indexing starts from 0 in C).
scanf("%d" , arr + i); is equivalent to scanf("%d",&arr[i]). And the correct way to use scanf() would be
if( scanf("%d", &arr[i]) != 1){
// error occured. Handle it.
}
Also from standard:
d
Matches an optionally signed decimal integer, whose format is the same as expected for the subject sequence of the strtol function with the value 10 for the base argument. The corresponding argument shall be a pointer to signed integer.
To be clear on why both are same:-
The arr+i arr converted to pointer to the first element and then with that pointer we add i - in pointer arithmetic every addition is being directed by the type of element it points to. Here the array is containing int elements - which is why arr+i will point to the i th element of the array. arr+i is a pointer to the ith element which is what is expected by %d format specifier of scanf.
Also &arr[i] - here & address of operator returns the address of the element arr[i] or *(arr+i) which is nothing but the address of the i-th element that is what is being expected by %d format specifier of scanf.
Remember that the argument corresponding to %d in a scanf call must be an expression of type int * (pointer to int). Normally, you'd read an array element as
scanf( "%d", &arr[i] );
The expression &arr[i] evaluates to the address of the element, and it has type int *.
The array subscript operation arr[i] is equivalent to *(arr + i) - given a starting address arr, offset i elements (not bytes!) from that address and dereference the result.
This works because in C, an array expression that isn't the operand of the sizeof or unary & operators is converted ("decays") from type "N-element array of T" to "pointer to T", and the value of the expression is the address of the first element.
Thus, the expression arr by itself will ultimately have type int *, and will evaluate to the address of the first element in the array:
arr == (arr + 0) == &arr[0]
Thus, if
*(arr + i) == arr[i] // int
then it follows that
arr + i == &arr[i] // int *
And this is why
scanf( "%d", arr + i );
works as well as
scanf( "%d", &arr[i] );
As a matter of style, use array subscript notation rather than pointer arithmetic. It conveys the intent more clearly. And, you're less likely to make a mistake with multi-dimensional arrays -
scanf( "%d", &arr[i][j][k] );
is easier to write and understand than
scanf( "%d", *(*(arr + i) + j) + k );
Also, check the result of scanf - it will return the number of items successfully read and assigned, or EOF if end of file has been signaled or there's some kind of input error.
Short version: It's the difference between referring to a value and replacing it with input from the user, and referring to a point in memory and writing to it directly.
In C arrays referring to the name of the variable returns the address of that variable in memory.
The scanf() statement takes input from the user and writes it to a specific point in memory. Applying your second method (the one you are using) you should write something like this:
//YOUR EXAMPLE
#include <stdio.h>
#define n 3
int main()
{
int arr[n];
int i;
printf("Input 3 numbers:\n");
for(i = 0 ; i < n ; i++)
scanf("%d" , &arr[i]);
for(i = 0 ; i < n ; i++)
printf("%d",arr[i]);
}
Here you tell your program to get the value of the array in position i, symbolized by arr[i], and replace that value with the new value obtained from the user.
The other example:
//OTHER METHOD
#include <stdio.h>
#define n 3
int main()
{
int arr[n];
int i;
printf("Input 3 numbers:\n");
for(i = 0 ; i < n ; i++)
scanf("%d" , arr + i);
for(i = 0 ; i < n ; i++)
printf("%d",arr[i]);
}
Here we reference the array by name, meaning we reference to the address of the starting point of where that array is stored in memory. In which case, we do not need the '&' symbol, as we are referring an address directly. The '+ i' term means that every iteration of the loop we refer to the next address in memory in that array (skipping sizeof(int) bytes), and so we write directly to that address.
I don't know for sure which is faster, perhaps these are even equivalent to the compiler, perhaps someone else here would have insights, but both ways would work.
NOTE:
I replaced your for loop boundaries, as you were looping from i=1 to i<=n, and writing to arr[i], which means you weren't utilizing the first element of the array, arr[0], and were out of bounds on arr[n]. (The last cell in the array is arr[n-1].

Using negative number as array index

I came along a competitive question that asks the output of the following:
#include <stdio.h>
int main()
{
int a[] = {0,1,2,3,4};
int i, *ptr;
for(ptr = a+4, i=0; i <=4; i++)
printf("%d", ptr[-i]);
return 0;
}
I did read this topic: Are negative array indexes allowed in C? However it was unclear to me how the -ve symbol generates the array in the reverse order, ie. 4, 3, 2, 1, 0.
First, recall that in C the expression ptr[index] means the same thing as *(ptr+index).
Now let's look at your expression again: ptr is set to a+4 before the loop; then you apply -i index to it. Therefore, the equivalent pointer arithmetic expression would be as follows:
printf("%d", *(a+4-i));
This expression iterates the array backwards, producing the results that you see.
The reason it works is because the [] operator does pointer addition.
When you reference
a[x]
Whats actually happening is its taking the memory address of a and adding the sizeof(int)*x
So if you set ptr to a+4, you are going to a+sizeof(int)*4
then, when you put in a negative value, you move backwards through the memory address.
ptr[-i] decays into *(ptr + (-i)). At the first iteration, when i = 0, ptr[-i] accesses last element of a array, because initially ptr was set to be equal a + 4, which means - take address of beginning of a and add 4 * sizeof(int) (because ptr was of size int). On every next iteration, when i is incremented, previous element of array is accessed.
In is for statement
for(ptr = a+4, i=0; i <=4; i++)
pointer ptr is set to a+4 It could be done also the following way
ptr = &a[4];
If you tray to output the value pointed to by the pointer as for example
printf( "%d\n", *ptr );
you will get 4. That is the pointer points to the last element of the array.
Inside the loop there is used expression ptr[-i] . for i equal to 0 it is equivalent to ptr[0] or simply to *ptr that is the last element of the array will be outputed.
For i equal to 1 expression ptr[-i] is equivalent to a[4 - 1] or simply a[3]. When iequal to 2 when expression ptr[-i] is equivalent to a[4 - i] that is a[4 - 2] that in turn is a[2] and so on.
SO you will get
4321
a+4 gives a pointer to the fifth element of a. So ptr refers to that location.
Then the loop counts i from 0 up to (and including) 4.
The dereference ptr[-i] is equivalent to *(ptr - i) (by definition). So, since i is 0 and ptr is a+4, it's equivalent to a+4-0, then a+4-1, then a+4-2, and so on until a+4-4, which is (obviously enough) equal to a.
As I mentioned in my comment in C/C++
a[b] == *(a+b) == b[a]
For your case all of these is fine
printf("%d", *(a + 4 - i));
printf("%d", a[4 - i]);
printf("%d", 4[a - i]);
...

Loop control in C using pointers for an array of structures

I am a newbie and am trying to understand the concept of pointers to an array using the example below. Can anyone tell me what the exit condition for the loop should be?
The while loop seems to be running forever but the program terminates with no output.
Thank you.
typedef struct abc{
int a;
char b;
} ABC;
ABC *ptr, arr[10];
int main()
{
ptr = &arr[0];
int i;
for(i = 0; i < 10; i++){
arr[i].a = i;
}
while(ptr!=NULL){
printf("%d \n", ptr->a);
ptr++; //Can I use ptr = ptr + n to skip n elements for some n?
}
}
while(ptr!=NULL){
This will run until ptr becomes NULL. Since it points to the first element of the array, and it's always incremented, and we don't know any other implementation detail, it may or may not become NULL. That's not how you check for walking past the end of the array. You would need
while (ptr < arr + 10)
instead.
Can I use ptr = ptr + n to skip n elements for some n?
Of course. And while we are at it: why not ptr += n?
The loop isn't infinite, it stops when ptr == 0.
Assuming you have a 32bit computer, ptr is 32 bits wide.
SO it can hold numbers from 0 to 4294967296-1 (0 to 2 ^ 32 -1).
Each time through the loop it adds 8 to ptr.
Eventually ptr will get to be 4294967296-8.
Adding 8 to that results in 4294967296 - but that is an overflow so the actual result is 0.
Note: This only works if PTR happens to start at a multiple of 8.
Offset it by 4 and this would be an infinite loop.
CHange the printf from "%d" to "%x" - printing the numbers in hex will make it more clear I think.

Resources