I was trying to write a stack in C, but i had some problems regarding realloc. Finally i managed to write a working program but i don't get why does it work and why i have to give on the input of my functions put_on_fun_stack and get_from_fun_stack a pointer to my table of structures.
When i tried to give it like put_on_fun_stack(stack_t *s, ...) it didin't work. Why do i have to put pointer in realloc and why do i have to write a (*s)[*l], and i can't write *s[*l]. Can somebody please explain the pointers to structures?
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
typedef struct {
int *n;
char *name;
}stack_t;
void init(stack_t **s){
*s=malloc(0);
}
void put_on_fun_stack(stack_t **s, char *name, int *l, int n){
*s = realloc(*s, (*l+1) * sizeof(stack_t));
(*s)[*l].name = name; //why do i need (*s) ?
(*s)[*l].n = n;
*l=*l+1;
}
char* get_from_fun_stack(stack_t **s, int *l){
char *temp = (*s)[*l-1].name;
*s = realloc(*s, (*l - 2) * sizeof(stack_t));
*l=*l-2;
return temp;
}
void rm(stack_t *s){
free(s);
}
int main(int argc, char **argv){
char *name;
stack_t* s;
init(&s);
int i;
int l=0;
srand(time(0));
if (argc>1)
for(i=1;i<argc;i++){
printf("%s\n", argv[i]);
put_on_fun_stack(&s, argv[i], &l, rand()%10);
printf("name=%s, n=%d, l=%d \n", s[l-1].name,s[l-1].n, l-1);
}
rm(s);
return 0;
}
C is pass by value so when you call put_on_fun_stack() and you just pass s you have a copy of main's value of s and not the address of s. You can't change the value of s that's in main. In other words, when you had it coded as s = realloc(s, (*l - 2) * sizeof(stack_t)); you're only changing the value of s in put_on_fun_stack() and it doesn't affect the s from main.
You fixed that by passing the address of s in main to put_on_fun_stack() and so as coded *s = realloc(*s, (*l - 2) * sizeof(stack_t)); the value of s in main gets set as you need it to.
As for (*s)[*l] vs *s[*l], it's a matter of operator precedence. [] binds tighter than * so *s[*l] is the same as *(s[*l]). Not what you want.
If your question is, why does (*s)[*l] work you have to look at what s is. s is a stack_t **, (*s) then is a stack_t * and (*s)[*l] then is the *lth element of the array pointed to by (*s).
Looking at why the other one doesn't work, (s[*l]) is the *lth element of an array of stack_t * and then *s(*l]) is the 0th element of the *lth stack_t *. It will only work when *l is 0.
It would be confusing but you can avoid the () by coding it as s[0][*l]. A cleaner way to clean it up is to dereference s and save it in a local variable, sort of like this:
void put_on_fun_stack(stack_t **ps, char *name, int *pl, int n){
stack_t *s;
int l=*pl;
s = realloc(*ps, (l+1) * sizeof(stack_t));
s[l].name = name;
s[l].n = n;
// return the updated values
*pl=l+1;
*ps=s;
}
Related
So when I pass a data type like a struct to assign some memory to it I find that the pointer doesn't change within the main scope. This further becomes a problem when I try to free the memory but obviously if its using the original pointer it will be pointing at the stack address.
void allocate(int *value){
value = malloc(10 * sizeof(int));
}
int main(){
int val2;
allocate(&val2);
free(&val2);
return 0;
}
I can fix this by using a double pointer to be passed into the allocate function but some course work I'm doing requires to only pass a pointer and I cant get it to update the pointer when it returns to main. I have looked around for a while but cant find a straight forward answer, I feel like my coursework is wrong but that might be my lack of understanding.
The requirement to "only pass a pointer" seems contrived, and you could argue that a pointer to pointer (not a "double pointer") is a pointer, but perhaps you could use void * to punch a hole in the type system. Or use a struct:
#include <stdlib.h>
#include <stdio.h>
struct intbuffer {
int *d;
size_t cap;
};
void *
xmalloc(size_t s)
{
void *r = malloc(s);
if( r == NULL ){
perror("malloc");
exit(1);
}
return r;
}
void
allocate(void *p, size_t s)
{
*(int **)p = xmalloc(s * sizeof(int));
}
void
allocate2(struct intbuffer *p)
{
p->d = xmalloc(p->cap * sizeof *p->d);
}
int
main(void)
{
int *val2;
struct intbuffer v;
allocate(&val2, 10);
free(val2);
v.cap = 10; /* Horrible api!! */
allocate2(&v);
free(v.d);
return 0;
}
Note that setting the capacity in the struct prior to making the call to allocate is a violation of many principles of software design, but this whole thing is absurdly contrived due to the bizarre artificial limitations.
There are not enough *'s in each place, but you will have to figure out what that means.
void allocate(int** value){
*value = malloc(10 * sizeof(int));
}
int main(){
int* val2;
allocate(&val2);
free(val2);
return 0;
}
I am trying to sort city names inputted. The code below seems correct to me, but while it does compile successfully, it does not work as I expected.
Am I failing in understanding pointers? Let me correct if below are true:
names type is a char **
names[0] type is char *
If I want to swap strings after checking if they are bigger with strcmp(), I have to change the values inside names[i] and names[j] because the values inside these values are pointers to actual city names. When these are interchanged, they point to each others' char array and I am done.
If my 3rd idea is true, I have to pass parameters to swap function as char * because swap function will take names[i] and names[j] as parameters and the type of these are char *.
The thinking was like above while writing the code below. But it seems I am failing at my logic because code does not work as intended.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int i,j;
char *temp;
void swap(char *, char *);
int main(void){
char *names[4];
//gets city names
puts("Enter 4 city names:");
for (i = 0; i < 4; i++)
{
names[i]=malloc(100);
fgets(names[i],99,stdin);
}
//bubble sort names array and swap if necessary
for (i = 0; i < 3; i++)
{
for (j = i+1; j<4 ; j++)
{
if (strcmp (names[i],names[j]) >0 )
{
swap(names[i], names[j]);
}
}
}
puts("Printing sorted array");
for (i = 0; i < 4; i++)
{
printf("%s", names[i]);
}
getch();
}
void swap(char *first, char *second){
temp=first;
first=second;
second=temp;
}
You need to pass a pointer to the pointer:
void swap(char **first, char **second)
{
char *temp = *first;
*first = *second;
*second = temp;
}
As it was you are only modifying the copy of the pointer, not the original. We use pointers to look at the original...hence you need a pointer to a pointer; you are modifying a pointer!!
To get your head round it, I'd recommend swapping your pointers to strings for ints and sort those instead. If it was ints you were sorting your swap function would look like this:
void swap(int first, int second) // These ints/parameters have been copied
{
first = second; // This only modifies the local copy
// etc..
}
To modify the original values you would need to use a pointer:
void swap(int *first, int *second)
{
*first = *second;
// etc...
}
Your swap function has no effect at all at the passed pointers, you need to change it like this, so that the passed pointers are modified:
swap(&names[i], &names[j]);
void swap(char **first, char **second)
{
temp=*first;
*first=*second;
*second=temp;
}
Your swap function has no effect. Because I feel it is not obvious for you, let's try with a simpler example.
If you wanted to swap two integers, your function would take int instead of char*. Your function would be (I have just replaced the char* by int):
void swap(int first, int second){
int temp=first;
first=second;
second=temp;
}
When you call swap(a, b) with a and b 2 int variables, their values are copied into first in second. Then you swap the contain of the variables first and second. The important point is that you don't change the original variables a and b.
The correct function would be:
void swap(int *first, int *second){
int temp=*first;
*first=*second;
*second=temp;
}
Because that way, you pass the address of the variables and you modify the original variables this way. If it is not clear, you should document yourself about what is a pointer and how it works.
Now, you can change back the int by a char*:
void swap(char **first, char **second){
char* temp=*first;
*first=*second;
*second=temp;
}
Your swap function is incorrect, you can't assign strings like that. You need something like this (non-optimal)
void swap(char *a, char *b) {
char tmp[256];
strcpy(tmp, a);
strcpy(a, b);
strcpy(b, tmp);
}
Your problem is not with pointers, but with function calls. When you pass a value to a function, and modify that value, the "source" of the value is not necessarily changed.
void swap(char **first, char **second) {
char *temp;
temp=*first;
*first=*second;
*second=temp;
}
swap(&names[i], &names[j]);
Or you could do it like this:
void swap(char **arr, int x, int y) {
char *temp;
temp = arr[x];
arr[x] = arr[y];
arr[y] = temp;
}
swap(names, i, j);
In the first case you pass to the function the two addresses, the contents of which are to be changed. In the second you pass the master array address, and the two locations.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int i,j;
char *temp;
void swap(char **, char **);
int main(void){
char *names[4];
//gets city names
puts("Enter 4 city names:");
for (i = 0; i < 4; i++)
{
names[i]=malloc(100);
fgets(names[i],99,stdin);
}
//bubble sort names array and swap if necessary
for (i = 0; i < 3; i++)
{
for (j = i+1; j<4 ; j++)
{
if (strcmp (names[i],names[j]) >0 )
{
swap(&names[i], &names[j]);
}
}
}
puts("Printing sorted array");
for (i = 0; i < 4; i++)
{
printf("%s", names[i]);
}
}
void swap(char **first, char **second){
temp=*first;
*first=*second;
*second=temp;
}
I know how to modify an array of pointers in main, but don't know how to do it when my function need to modify it.
The code between ** is how I do it in main without using a function. I know how to print the array of pointer of pointer out. My question is, suppose I want to move these lines ** into function(), what do I need to modify?
code:
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
void function(char *array[], int size);
void function_print(char *array[], int size);
int main()
{
char *array[] = {0};
char word[20];
**scanf("%s", word);
int len = strlen(word) + 1;
array[size] = (char *)malloc(sizeof(len));
strlcpy(array[size], word, sizeof(array[size]));**
function(array, 0);
return 0;
}
void function(char *array[], int size)
{
}
void function_print(char *array[], int size)
{
for(int x = 0; x < size; x ++)
{
printf("%s", *array);
(array)++;
}
}
~
~
I made some edit and realized your function will do the same. So go on, and read the EDIT if you don't know how it works.
Besides I think there's something wrong in your main(). First, array[size] = (char *)malloc(sizeof(len)); tends to report an error because no size is defined here. Second, if by size you mean the number of elements in array, then array[size] would cause an overflow. Third, the argument of malloc should be sizeof(char)*len, not sizeof(len), since the latter equals sizeof(int).
Change your function to
void function(char **, int);
And call it by
function(array, 0);
EDIT
I think by "modify it" you mean to change the pointers stored in the array. Since every element is a char*, a char** will do the job.
When you pass array as an argument, actually you're passing the address of the first element. Then in the function you receive it with a char** parray. Since you have also passed the size, you can use it as a char* parray[], and the address of every element is exactly the same with array in main(). Thus, any modification you do with parray will change array. Is that what you want?
You are doing no mistake in calling the function and passing the array of char pointers. This is a right way. Your program did not compile for me, so made some small changes. It works.
#include<stdio.h>
#include<string.h>
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include<iostream>
void function(char *array[], int size);
int main()
{
char *array[] = {0};
char word[20];
scanf("%s", word);
int len = strlen(word) + 1;
array[0] = (char *)malloc(sizeof(len)); //that how I do it in main without using a function.
strcpy(array[0], word);
function(array, 0);
return 0;
}
void function(char *array[], int size)
{
char * temp = new char[strlen(array[0])+1];
strcpy(temp, array[0]);
printf(temp, 's');
}
Writing this :
void function(char *array[], int size)
and this:
void function(char **array, int size)
are same in this context.
If you define a function like this then its not necessary to declare it like the same , you can declare it like :
void function(char **, int );
declaration only describes the return type and arguments' type of a function.Now, some other recommendations:
Do not use scanf like this :
scanf("%s", word);// you need to specify field width in case of strings otherwise it will overwrite buffer in case of large strings therefore, do it like this :
scanf("%19s",word);
size is not defined in your main, instead I would rather prefer to do this way :
size_t len = sizeof(word) + 1;// yes, try to use size_t when returning number of bytes
*array = (char*)malloc(sizeof len);// casting malloc is not recommended though.
strncpy(*array, word,len);
Try doing :
void function(char *array, int size)();
And instead of:
function(array,0);
because array itself it is a memroy address.
Okay so I am trying to pass a char pointer to another function. I can do this with an array of a char but cannot do with a char pointer. Problem is I don't know the size of it so I cannot declare anything about the size within the main() function.
#include <stdio.h>
void ptrch ( char * point) {
point = "asd";
}
int main() {
char * point;
ptrch(point);
printf("%s\n", point);
return 0;
}
This does not work however, these two works:
1)
#include <stdio.h>
int main() {
char * point;
point = "asd";
printf("%s\n", point);
return 0;
}
2)
#include <stdio.h>
#include <string.h>
void ptrch ( char * point) {
strcpy(point, "asd");
}
int main() {
char point[10];
ptrch(point);
printf("%s\n", point);
return 0;
}
So I am trying to understand the reason and a possible solution for my problem
This should work since pointer to the char pointer is passed. Therefore any changes to the pointer will be seen outside thereafter.
void ptrch ( char ** point) {
*point = "asd";
}
int main() {
char * point;
ptrch(&point);
printf("%s\n", point);
return 0;
}
void ptrch ( char * point) {
point = "asd";
}
Your pointer is passed by value, and this code copies, then overwrites the copy. So the original pointer is untouched.
P.S. Point to be noted that when you do point = "blah" you are creating a string literal, and any attempt to modify is Undefined behaviour, so it should really be const char *
To Fix - pass a pointer to a pointer as #Hassan TM does, or return the pointer as below.
const char *ptrch () {
return "asd";
}
...
const char* point = ptrch();
Here:
int main() {
char * point;
ptrch(point);
You're passing point by value. Then, ptrch sets its own local copy of point to point to "asd", leaving the point in main untouched.
A solution would be to pass a pointer to main's point:
void ptrch(char **pp) { *pp = "asd"; return; }
If you change the value of the pointer in a function, it will remain changed only in that one function call.
Don't mess your head with pointers and try:
void func(int i){
i=5;
}
int main(){
int i=0;
func(i);
printf("%d\n",i);
return 0;
}
The same with your pointer. You do not change the address it points to.
If you assign to a variable passed by value, the variable outside the function will remain unchanged.
You could pass it by a pointer (to pointer) and change it by dereferrencing it and it's the same with an int - in this case, it doesn't matter if the type is int or char * .
first declare funtion......like this
#include<stdio.h>
void function_call(char s)
next write main code.....
void main()
{
void (*pnt)(char); // pointer function declaration....
pnt=&function_call; // assign address of function
(*pnt)('b'); // call funtion....
}
I have written code to swap strings, but I am not able to swap. What is the problem and how can I solve it by using a function, swap?
#include <stdio.h>
void swap( char*,char*);
int main()
{
char *ptr[2] = {"hello", "morning"};
swap(ptr[0], ptr[1]);
printf("%s %s", ptr[0], ptr[1]);
return 0;
}
void swap(char *t1, char*t2)
{
char *t;
t = t1;
t1 = t2;
t2 = t;
}
I also tried to pass (&ptr[0], &ptr[1]), but here it shows a segmentation fault. Also I made a char, *p1 = ptr[0], char *p1 = ptr[1], and then passes &p1, and &p2 to swap, but still I get a segmentation fault.
C function arguments are pass-by-value. You're passing the value of addresses to your swap function, and expecting those values, the addresses, to change. But only the copies of the addresses in your swap function change.
To change the actual passed-in addressed, you'll need an aditional level of reference:
void swap(char **t1, char **t2)
{
char *t;
t = *t1;
*t1= *t2;
*t2 = t;
}
And call this swap like so: swap(&ptr[0], &ptr[1]);
You need to pass in pointers to the pointers of the char arrays in order to switch them. By doing that you can swap the values of those pointers instead. (Which are the actual arrays.)
#include<stdio.h>
void swap( char**,char**);
int main()
{
char *ptr[2] = {"hello","mornig"};
swap(&ptr[0], &ptr[1]);
printf("%s %s",ptr[0], ptr[1]);
return 0;
}
void swap( char **t1,char **t2)
{
char *t;
t = *t1;
*t1 = *t2;
*t2 =t;
}
You need to pass pointers to your strings to swap them (char**). Otherwise the changes you do will be local to the swap function.
void swap( char **t1,char **t2)
{
char *t;
t = *t1;
*t1 = *t2;
*t2 =t;
}
int main()
{
char *ptr[2] = {"hello","mornig"};
swap(&ptr[0], &ptr[1]);
printf("%s %s",ptr[0],ptr[1]);
return 0;
}
char *ptr[2] = {"hello","mornig"}; - This statement means you are allocating an array of size 2 which is going to store a address of two strings(ie char *). Now the two strings you are giving will be in text segment which is a read only data. If we tries to modify it, which will leads to crash(sgmentation fault).
So if you call swap(&ptr[0], &ptr[1]) leads to a crash. because you are trying to write the charcter m in the first read only string h. Write is not possible to the string which is in text segment.
If you want to simply swap a string you can call the function as swap(&ptr[0], &ptr[1]), which is equivalent to swap((ptr + 0),(ptr + 1));.
And change the swap function as below
void swap( char **t1,char **t2)
{
char *t;
t = *t1;
*t1 = *t2;
*t2 =t;
}
Here we are just swapping the address of the string stored in the array pointer ptr.