Pointers in C for a rookie - c

I am just starting to learn programming for a unit I am doing in my engineering course and I have come across pointers. I just wanted some reassurance that I actually understand the concept correctly in terms of using a pointer as an argument in a function. If I understand it correctly, you pass a pointer to an address of a variable you would like to be altered by a separate function called, even though it is a local variable within the scope of the calling function. Does that make sense? I have an example from my text book which I re-wrote. The only thing is they gave it in two incomplete parts and I put it together, filled in the blanks and added the final printf statement in the main function. I'll paste it here:
#include <stdio.h>
#include <stdlib.h>
#define READ_OK 0
#define READ_ERROR 1
int read_num(int lo, int hi, int *num);
int main(int argc, char *argv[])
{
int lo = 0, hi = 0, *num, val;
printf("Please enter a lower bound and an upper bound for your range,respectively\nLower: ");
scanf("%d", &lo);
printf("Upper: ");
scanf("%d", &hi);
num = &val;
if(read_num(lo,hi, &val) != READ_OK)
{
printf("Read error, program abort\n");
exit(EXIT_FAILURE);
}
else
{
printf("You entered %d, press any key to continue: \n", val);
getchar();
}
return 0;
}
int read_num(int lo, int hi, int *num)
{
int next;
printf("Enter a number between %d and %d: ", lo, hi);
while(scanf("%d", &next)==1)
{
if (lo<=next && next<=hi)
{
*num = next;
return READ_OK;
}
printf("%d is not between %d and %d\nTry again: ", next, lo, hi);
}
return READ_ERROR;
}
So is my understanding correct? "val" gets modified in read_num() by passing it's address in the form of pointer "*num", in which the the value for "next" is then written?
PS: is this syntax correct?
PPS: What would this process specifically be called?
Thanks a bunch for any help :)

The *num is not necessary inside the main() function. As you are passing the address of the val inside the read_num() , so any changes from the read_num() will also affect the value inside main() as you are working with the address.
In your program you have basically use two different pointers- one is inside main which is num, and another inside read_num() which is also num, for more understanding see the scope of a variable in c. As the val is inside main so you don't need to use pointer here, because you have the access of changing the value from the main as it is local to it. You will need pointer when you will be changing the value of val outside from the main, or from outside of the scope of the variable.

Related

Unclear behavior of structs in a function

I am creating a project and I encountered behavior that is not supposed to happen (at least as far as I know). I am trying to change values in a struct array inside of a function addOrder. in main() I give struct's address to a function addOrder (and this is the first warning). Then I try to change its contents in the named function. I should only be able to change using ->, however, I get errors this way and I can only change using data[0].someName
#include<stdlib.h>
#include<stdio.h>
#include<string.h>
#define MENU_TITLE "----Welcome to order manager!---" // menu title
#define MENU_SIZE 4 //change based on menu options
#define INPUT_MSG "Please choose one of the following options" //enter input message (range is added later automatically)
#define SIZE 25 //size of option message array
#define STREET_NAME_SIZE 50 //size of street name array
#define BUILDING_NUMBER_SIZE 10 //size of building number array
#define EMAIL_SIZE 40 //size of email array
#define INPUT_PHONE_MAX 12
typedef struct Data{
char streetName[STREET_NAME_SIZE];
char buildingNumber[BUILDING_NUMBER_SIZE];
unsigned long long phoneNumber;
char email[EMAIL_SIZE];
}Data;
void loadOrderAmount(int *orderAmount);
void showMenu(char *menuTitle, int menuSize, char *inputMsg);
int getChoise();
void addOrder(Data *data, int *orderAmount);
void getEmail(char *email);
unsigned long long getPhoneNumber();
int main(){
int orderAmount = 0;
loadOrderAmount(&orderAmount);
Data data[orderAmount + 1];
int choise = 0;
showMenu(MENU_TITLE, MENU_SIZE, INPUT_MSG);
while(!choise){
choise = getChoise();
}
printf("\n");
switch(choise){
case 1:
addOrder(&data,&orderAmount); // This gives first warning
break;
case 2:
//removeOrder(data);
break;
case 3:
//editOrder(data);
break;
case 4:
printf("Have a nice day\n");
return 0;
}
printf("in main data %d\n",&data);
//printf("%s %s ",data[0].streetName,data[0].buildingNumber);
//printf("+%llu ",data[0].phoneNumber);
printf("in main %s %llu\n",data[0].email,data[0].phoneNumber);
return 0;
}
void addOrder(Data *data,int *orderAmount){
int amount = *orderAmount; //it is equal to 0
char email[41];
char street[51];
char buildingNumber[11];
printf("Adding an order...\n\n");
//++orderAmount;
// getStreetName(data, &orderAmount);
// getBuildingNumber(data,&orderAmount);
data[amount]->phoneNumber = getPhoneNumber(); //why this does not work?
getEmail(email);
strcpy(data[0].email,email); // why this works? its a function....
printf("In function data %d\n", data);
printf("in struct %s %llu\n",data[0].email, data[0].phoneNumber);
}
}
This is only a part of a code that is relevant and most functions are missing. Can anyone help me with this?
The function addOrder is declared like
void addOrder(Data *data, int *orderAmount);
But you are calling it passing the first argument of the type Data ( * )[orderAmount + 1]
addOrder(&data,&orderAmount);
You need to call it like
addOrder( data, &orderAmount );
Instead of this statement
data[amount]->phoneNumber = getPhoneNumber();
you have to write
data[amount].phoneNumber = getPhoneNumber();
And instead of this call
printf("In function data %d\n", data);
you have to write
printf("In function data %p\n", ( void * )data);
Pay attention to that within the function the expressions
data[amount]
and
data[0]
are not the same because amount is not equal to zero. The function is called with the argument orderAmount (passed by reference) that is assigned to amount.
This is how you solve this error:
Compiler points at the line addOrder(&data,&orderAmount); saying something strange "error passing argument 1 blablabla". We don't actually need to understand more than "error argument 1".
Could it be that the compiler is right and something is wrong with argument 1?
Hmm which one is argument 1, it must be &data.
Check the declaration of data, it is Data data[orderAmount + 1];. It's an array!
What did they teach us in beginner class? Ah, arrays decay to a pointer to the first element when passed to a function. So there is no need for &.
Change the call to addOrder(data,&orderAmount);
Compile again.

Using function to pass the user input via pointers not working

I'm trying to get the input from the user input, and pass to the program main using pointer. It seems that the value isn't going through even tho I tried some alternatives.
For example, if i input 0.0001, when I return to the main function it outputs 0.0000
#include <stdio.h>
void inputFloat(float *n);
int main() {
float *number;
printf("Insert number: ");
inputFloat(number);
printf("%1.4f", *number);
return 0;
}
void inputFloat(float *n){
float num;
while (scanf("%f", &num) != 1 || num < 0) {
scanf("%*[^\n]%*c");
printf("insert positive: ");
}
printf("%1.4f\n", num);
n = &num;
}
Thanks in advance for any tip or correction.
The main problem here is that you forget that in C arguments are passed by value, and that includes pointers.
The argument variable n in the inputFloat function is local to the inputFloat function, all modifications (like assignments) to it will be lost once the function returns.
What I believe you are trying to to is emulating pass by reference, which indeed is done by using pointers. But then you pass a pointer to a normal variable using the address-of operator &:
float number; // Not a pointer
inputFloat(&number); // Pass a pointer to the variable number
To use this pointer, and to set the value of the original variable it points to, you need to dereference the pointer:
void inputFloat(float *n)
{
// ...
*n = num; // Copy the value of num to the location where n is pointing
}

Simple if statement in C always return true

I dont have time to explain it deeply, its very simple code but the function always return 'y'(=true)
It is expected to write each number from 1 to squareroot of the generated random number and decide whether it is dividable or not but when i run it, somehow the if statement in the function always return true
#include <stdio.h>
#include <stdlib.h>
int a,b,i;
char c;
char abcd(char c);
int main()
{
srand(time(NULL));
int a=rand()%512;
b=sqrt(a);
i=1;
do{
if(abcd(c)=='y')printf("number %d is dividable by %d\n",a,i);
else printf("number %d is not dividable by %d\n",a,i);
i++;
}while(i<=b);
return 0;
}
char abcd(char c)
{
if(a%i==0)return'y';
else return 'n';
}
When you declare int a inside main as
int a=rand()%512;
you are shadowing your global variable a. The a in main is a different variable that has scope only local to the function main. Therefore, when you are using the value a inside char abcd(char c), this value is the global variable a which is default initialized to 0.
Also, why are you passing a char c variable to function abcd. You aren't using it. Please consider renaming your functions to something that more clearly describes their intent.
You have two different variables a:
one declared at file scope
int a,b,i;
and one declared in main():
int a=rand()%512;
Within its scope (almost all of main()), the latter shadows the former. Elsewhere, such as in function abcd(), only the former is visible. The former is default initialized to 0 and no other value is ever assigned to it, so no matter what value i takes, inside abcd(), the expression a%i evaluates to 0.
This is a good lesson in avoiding file-scope variables. Functions should operate on data accessed directly or indirectly through their parameters, or obtained from an external source. It is poor form for functions to exchange data through file-scope variables. Moreover, it was a red flag to me that your function abcd() declares a parameter that it never uses. Suggested variation:
char abcd(int dividend, int divisor) {
return (dividend % divisor) ? 'n' : 'y';
}
Or even better (because better name and more appropriate return type):
_Bool is_divisible(int dividend, int divisor) {
return !(dividend % divisor);
}
The reason yours doesn't work is because the variable a was declared in a separate scope from the abcd function. The a variable you use inside the abcd function is automatically set to 0, which is why it returns true every time (0 % anything is 0).
When you call abcd, you would need to pass a inside the parameters for it to use the correct value.
But really you don't need the abcd function, you can save a lot of code and directly check if it's divisible. This code should work:
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <time.h>
int a, b, i;
char c;
int main()
{
srand(time(NULL));
int a = rand() % 512;
b = sqrt(a);
i = 1;
do {
if (a%i == 0)printf("number %d is dividable by %d\n", a, i);
else printf("number %d is not dividable by %d\n", a, i);
i++;
} while (i <= b);
return 0;
}

how do you increment a variable using a pointer in C? [duplicate]

This question already has an answer here:
Variable changed in function not seen by caller?
(1 answer)
Closed 6 years ago.
My code is about implementing the function of Stack and Queue. If you're wondering why don't I use struct in my program that's because our instructor only allows us to use pointers and I'm a little bit confused using pointers. It's not yet finish, as much as possible I try to finish one function at a time instead of skipping to the next.
#include <stdio.h>
int container[5];
int len=0;
As I understand this part of my in function insert, "len" is suppose to change since it's incremented every time the function is use
int insert(int container[],int len)
{
int i,j,content,*incre;
incre=&len;
for(i=*incre;i<*incre+1;i++)
{
printf("Enter number:\n");
scanf("%d",&content);
container[i]=content;
}
(*incre)++;
}
int printcontent(int container[])
{
int i;
printf("Content of container:\n");
for(i=0;i<len+1;i++)
{
printf("%d ",container[i]);
}
printf("\n");
}
This part asks the user whether to add a content in the container or simply remove it. They can only add or remove one at a time.
int stack(int container[])
{
while(1)
{
int choice;
printf("What do you wanna do?\n");
printf("1.Insert\n2.Pop\n3.isEmpty\n4.Exit\n");
scanf("%d", &choice);
I checked the value of len it remains 0 instead of 1 when I first use insert.
if (choice==1)
{
insert(container,len);
printf("Value of len:%d\n",len);
printcontent(container);
}
else if(choice==4)
{
break;
}
}
}
main()
{
while(1)
{
int choice;
printf("What do you want to do?\n");
printf("1.Stack\n2.Queue\n3.Exit\n");
scanf("%d",&choice);
if(choice==1)
{.
stack(container);
}
else if(choice==3)
{
break;
}
}
}
Thanks for all of your help.
What your insert(...) function does is that it takes the parameter int len by value. That means if you call insert(...) with the local variable len as an argument in main(...) or whereever - it actually copies the value of the local variable len to the argument variable len inside the insert(...) function. The variable len which is inside the insert(...) function is then local to the insert function. That does not change even if you're declaring a pointer named incre pointing to this insert(...)-local variable len.
Then the argument variable len is incremented - but due to the fact that it is a local variable of the insert(...) function you will not see the original local variable len (which is in main(...) e.g.) being changed.
If you want to pass the original len by reference instead of by value, you have to declare your function like this ...
int insert(int container[], int* len) { ... } // Using raw pointers
... or like this ...
int insert(int container[], int& len) { ... } // Using references
... and use it like that (depending on the decision above):
insert(container, &len); // With pointers
insert(container, len); // With references

Allocating memory for array in struct (in C)

I need to define a type-struct in C that contains an array to be malloc'd as:
#include <stdio.h>
#include <stdlib.h>
typedef struct mine
{
int N;
double *A;
} mine;
int main(int argc, char** argv)
{
int i;
mine *m=malloc(sizeof(mine));
printf("sizeof(mine)=%d\n",sizeof(mine));
scanf("Enter array size: %d",&(m->N));
m->A=malloc((m->N)*sizeof(double));
for(i=0; i < m->N; i++)
m->A[i]=i+0.23;
printf("First array element: %lf",m->A[0]);
return (EXIT_SUCCESS);
}
The program compiles and runs, and the integer assignment seems to work fine. The array is not working as it should, however.
Any suggestions? I would like m to remain a pointer (to pass to functions etc.).
Thanks.
This is your problem:
scanf("Enter array size: %d",&(m->N));
It should be two separate steps:
printf("Enter array size: ");
scanf("%d",&(m->N));
(and for debugging checking:)
printf("The size entered appears to be %d\n", m->N);
That way, you know if you got the value you intended to get!
If #abelenky answered your question fine, but I was always told to cast the results of malloc from the void * it returns into whatever you are actually working with.
mine *m = (mine *)malloc(sizeof(mine));

Resources