I'm new to structs. I am trying to write a program that has a struct, and the struct is supposed to store a character array and its length. I want to be able change the length's value as I would be creating functions like trimming/concatenating the array. Here is a code I wrote:
#include <stdio.h>
#include <stdlib.h>
struct strstruct{
unsigned int length;
char string[20];
};
typedef struct strstruct stru;
int strleng(stru A){
int i=0;
while(A.string[i]!='\0'){
i++;
}
A.length =i;
return i;
}
int main(){
stru A = {1,
{'a','b','c','d','e','f'}
};
printf("%d %d\n",strleng(A),A.length);
return 0;
}
The value of A.length is not changing inspite of calling strleng.
(i)Why?
(ii) Is there another way to do it?
For starters the order of evaluation of arguments in a function call is unspecified.
So in this call
printf("%d %d\n",strleng(A),A.length);
the evaluation of the argument expression A.length can occur before calling the function strleng or vice versa.
Secondly the function strleng declared like
int strleng(stru A);
deals with a copy of the original object A declared in main and used as an argument. So changing the copy does not influence on the original object.
You need to pass the object by reference through a pointer to it.
unsigned int strleng( stru *A){
unsigned int i=0;
while(A->string[i]!='\0'){
i++;
}
A->length =i;
return i;
}
and in main you should write for example
unsigned int n = strleng( &A );
printf("%u %u\n", n, A.length );
Pay attention to that on one hand, the data member length is declared as having the type unsigned int
unsigned int length;
On the other hand, within your original function strleng you are using an object of the signed type int and the function return type is also int. The function should use at least the same type unsigned int instead of the type int.
Try the code below:
#include <stdio.h>
#include <stdlib.h>
struct strstruct{
unsigned int length;
char string[20];
};
typedef struct strstruct stru;
int strleng(stru* A){
int i=0;
while(A->string[i]!='\0'){
i++;
}
A->length =i;
return i;
}
int main(){
stru A = {1,
{'a','b','c','d','e','f'}
};
printf("%d %d %d\n",A.length, strleng(&A),A.length);
printf("%d \n",A.length);
return 0;
}
You will get output: 6 6 1. I should get the answer now.
At first, you need to use pointer as a parameter if you want to modify struture's value inner a fucntion.
For your question:
To most of the c compiler, the functions inner a printf function is prcessed from right to left. I think the compiler in your case is this one.
For some c compiler, it do process functions in one line from left to right.
I hope it can help you, c online compiler: https://www.onlinegdb.com/online_c_compiler.
printf("%d %d\n",strleng(A),A.length);
Firstly, Here you are passing the argument to the strleng function as a value means strleng function' parameter is a copy of A. In other words, variable A in the main function and structure variable inside the strleng function are two independent variables. So changing A.length in the strleng function will not be visible to your variable A in the main function. (There are many good online resources available about Pass by value vs. Pass by reference. You can check those for better understanding)
Most of the compilers takes each parameter of printf() from right to left. So here A.length execute first then strleng(A). So even you pass the argument by reference, it will still output 6 1.
Updated Code
#include <stdio.h>
#include <stdlib.h>
struct strstruct {
unsigned int length;
char string[20];
};
typedef struct strstruct stru;
int strleng(stru* A) {
int i = 0;
while(A->string[i] != '\0'){
i++;
}
A->length = i;
return i;
}
int main() {
stru A = {1, {'a','b','c','d','e','f'}};
printf("%d %d %d\n", A.length, strleng(&A), A.length);//6 6 1
return 0;
}
Related
This is a program to create a table full of points, but i'm trying to separate in functions.
I am doing this because I will need to add more functions in the future using the variables x and tabuleiro. I'm getting the error in the title and I don't understand why. Can you guys help me?
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
char tabuleiro_init(int dim, char tabuleiro[15][15]);
int main(int x)
{
printf("Put the dimension of the table: ");
scanf("%d", &x);
char tabuleiro[15][15];
tabuleiro_init(x, tabuleiro[15][15]);
}
char tabuleiro_init(dim, char tabuleiro)
{
if (dim >= 7 && dim <= 15 && dim%2 != 0)
{
for (int i = 0; i < dim; i++)
{
for (int j = 0; j < dim; j++)
{
printf(".", tabuleiro[i][j]);
printf(" ");
}
printf("\n");
}
}
}
There is a mismatch between the declaration and the definition of your tabuleiro_init function.
Compare
char tabuleiro_init(int dim, char tabuleiro[15][15])
with
char tabuleiro_init(dim, char tabuleiro)
For the first parameter, you are missing int in the definition.
For the second parameter, you declared it to be char tabuleiro[][15], or a pointer to a char array of 15 elements, but you defined it to be just a char.
For starters this declaration of main
int main(int x)
is incorrect.
Declare the function like
int main( void )
and within the function declare the variable x like
int x;
In this call
tabuleiro_init(x, tabuleiro[15][15]);
the second argument is a non-existent element of the array of the type char
Instead write
tabuleiro_init(x, tabuleiro);
The function declaration in its definition does not correspond to the first function declaration
char tabuleiro_init(dim, char tabuleiro)
And the first parameter does not have a type specifier.
Also the return type char of the function dies not make a sense and moreover the function returns nothing.
So at least use the following function declaration in the both cases
void tabuleiro_init(int dim, char tabuleiro[15][15])
In this call of printf
printf(".", tabuleiro[i][j]);
the second argument is not used. Maybe you just mean
printf("." );
(that does not maje a great sense) or
printf(".%c", tabuleiro[i][j]);
but in the last case the array must be initialized before passing it to the function.
When we wanna return one particular type of data, we need to declare a global variable first right? and assign this variable to the value thats being returned by the funtion?
Also for int primitive data type, we cannot use malloc to reserve memory block?
Sincerely,
headful of doubts.
#include <math.h>
#include <stdio.h>
int *sum();
int main()
{
int *num;
num = sum();
printf("\nSum of two given values = %d", *num);
return 0;
}
int *sum()
{
int a = 50, b = 80;
int *sum = NULL;
printf("%d %d",a,b);
*sum = a+b;
return sum;
}
I wanna using pointers to save the data thats being returned by the function. is it possible? I know it's possible for linked list structures. But I'm not sure about integers and other primitive data types.
Starting with your second question, you can use malloc to allocate memory of any size for any type of variable. Yes, you can use malloc to allocate ints and other primitive types on the heap.
int i_am_a_stack_variable = 1;
int * i_am_a_pointer_to_heap_memory = malloc(sizeof(int));
For your first question, I think you are mis-understanding how return variables work. Typically, the use of global variables should be avoided. They certainly aren't needed to return values from functions. The return value of a function is copied from the function's stack frame back to the calling stack frame wherever it is assigned. Note that it is COPIED back. Whether it is a primitive type or a pointer (which is really just another type of primitive). Your code could be written just not using pointers at all. Also, note that your code was not using a global variable at all even though you mentioned global variables.
#include <math.h>
#include <stdio.h>
int sum();
int main()
{
int num;
num = sum();
printf("\nSum of two given values = %d", num);
return 0;
}
int sum()
{
int a = 50, b = 80;
int sum = 0;
printf("%d %d",a,b);
sum = a+b;
return sum;
}
Does this make sense?
This should work
#include <math.h>
#include <stdio.h>
int *sum();
int main()
{
int *num;
num = sum();
printf("\nSum of two given values = %d", *num);
free(num);
return 0;
}
int *sum()
{
int a = 50, b = 80;
int *sum = malloc(sizeof(int));
printf("%d %d",a,b);
*sum = a+b;
return sum;
}
You need to allocate memory for the pointer. In your case you need memory for one Integer. When you say int* sum =NULL your pointer has no Adress. You can't access a null pointer.
I want to know if there is any real difference; I have written code that as it feel it a passing by copy not reference but it acts as reference.
Here is the code:
#include <stdio.h>
#include <conio.h>
using namespace std;
int pause = 0;
void display(int b[5], int size){
for (int i = 0; i < size; i++){
printf("\n%d",b[i]," at:");
printf(" %d", &b[i]);
}
}
void main(){
int num[] = { 2, 4, 6, 8, 10 };
printf("\nIn main function.");
for (int i = 0; i < 5; i++){
printf("\n%d", num[i], " at:");
printf(" %d", &num[i]);
}
display(num,5);
scanf("%d", pause);
}
You cannot pass an array itself to a function at all, nor can you return one. In particular, despite the appearance of its declaration, your function display() does not receive an array as a parameter. It's declaration is 100% equivalent to this one:
void display(int *b, int size);
and this one:
void display(int b[], int size);
Expressions of array type are automatically converted to pointers in almost every context in which they can appear, so this function call:
display(num,5);
is equivalent to
display(&num[0],5);
Nevertheless, there is a potential difference to call out in this area: the expression &num is not equivalent to &num[0]. They refer to the same address, but the two expressions have different types. Passing the former would be the analog of passing the array by reference, but that expression does not have the correct type for the first argument to your display() function. A function that wants to receive &num needs to be declared differently:
void display2(int (*b)[5]);
or
void display3(int n, int (*b)[n]);
The latter requires C99, or C2011 with VLA support (which is required in C99, but optional in C2011).
I know a bit of C++ but I need to do this in C which seems to be far more complicated. As you can probably see from my code I try to have a function that generates an array and then a different function that will reverse the order of this array. The function to generate the array is just a dummy function that will be replaced by input from a different programming language (which will be done through a function that will map the values to something recognisable in C). The reverse function, even tough I know how to do it I do not know how to pass the values from my generateArray back to main and into the reverseArray (it needs to happen in this orderI cannot call reverseArray from within the generateArray).
Also, I get an error in my code right now which says:
reverse.c: In function ‘main’:
reverse.c:19:5: warning: assignment makes pointer from integer without a cast [-Wint-conversion]
p = generateArray(m);
reverse.c: In function ‘generateArray’:
reverse.c:42:8: warning: return makes integer from pointer without a cast [-Wint-conversion]
return a;
#include <stdio.h>
#include <time.h>
#include <stdlib.h>
//int reverseArray();
int generateArray(int size);
int main()
{
int seed = time(NULL);
int *p;
int m;
printf("please insert the size of the array:");
scanf("%d",&m);
p = generateArray(m);
for (int i=0;i<m;i++)
{
printf("%d \n", *(p+i));
}
return 0;
}
int generateArray(int size)
{
static int *a;
a = (int *)malloc(size*sizeof(int));
for(int i=0;i<size;i++)
{
a[i]=rand()%12+1;
}
return a;
}
//int reverseArray(){}
I am trying understand how pointers works in C. I am trying a simple case where an array, and a pointer to array are the arguments of a function which will copy the elements of the first one in the second one.
I have written this code
#include <stdio.h>
#define TAM 32
typedef int TablaArray[32];
void copyArray(TablaArray, TablaArray*, int);
void main(){
int t1[] = {1,2,3,4};
int t2[4];
copyArray(t1, t2,4);
for(int i = 0; i <= 3; i ++){
printf("%d - %d\n", t1[i], t2[i]);
}
}
void copyArray(TablaArray t1, TablaArray *t2, int tam){
for(int i = 0; i<tam-1; i++){
printf("%d\n", t1[i]);
*t2[i] = t1[i];
}
}
I am expecting to get something like this with the printf expression:
1 - 1
2 - 2
3 - 3
4 - 4
But definitely I don't know the way... I have been looking in stackoverflow and because I am sure this trivial question is already answered... but I didn't find it...
You need to make sure you are passing two int pointers pointing to both arrays. In your code only one of the arguments is a pointer. The code below should make it more clear:
#include <stdio.h>
void copyArray(int * arr1, int * arr2, int size);
int main(void)
{
int t1[] = {1,2,3,4};
int t2[4];
copyArray(t1, t2,4);
for(int i = 0; i <= 3; i ++)
{
printf("%d - %d\n", t1[i], t2[i]);
}
return 0;
}
void copyArray(int * arr1, int * arr2, int size)
{
for(int i = 0; i < size; i++)
{
printf("%d\n", arr1[i]);
arr2[i] = arr1[i];
}
return;
}
Edit: in what you have written, a TablaArray * is a pointer to an array of 32 ints, while you need an int *
typedef int TablaArray[32];
is bad practice
The problem is connected with array to pointer decay and then with pointer arithmetics:
Pointer decay means that if you pass an array-object of type int x[32] as argument to a function, then it "decays" to a pointer like int *, which points to the first element of the integer array. So be aware that if you pass an int x[32]-object, it's actually passed by reference (the array is not copied) and you may alter the contents of the array in the function.
Now pointer arithmetics:
Incrementing a pointer (or accessing an array through array subscripting) implicitly does pointer arithmetics, and the number of bytes added to the initial value depends on the type of the object to which the pointer points:
typedef int Array10[10];
Array10 arr = { 1,2,3,4,5,6,7,8,9,0 };
int *x = arr; // arrayOfInts decays to a pointer; x points to the &arr[0]
x++; // in terms of bytes, x is incremented by sizeof(int) bytes
int i = x[3]; // gets the int-value on the address of x + 3*sizeof(int)
Array10 *arr10ptr = arr;
arr10ptr++; // in terms of bytes, x is incremented by sizeof(Array10) bytes, which is 10*sizeof(int)
arr10ptr[3]; // 3*sizeof(Array10), i.e. 3*10*sizeof(int)
Now it should be clear why a function parameter being declared as a pointer to an array of int[32] behaves different from a function parameter being declared as an int[32].
So you could correct your program as follows, now knowing that TablaArray t2 will be a reference to the underlying array anyway:
void copyArray(TablaArray t1, TablaArray t2, int tam){
for(int i = 0; i<tam; i++){
printf("%d\n", t1[i]);
t2[i] = t1[i];
}
}
Hope it helps.
Compile with warnings enabled. If you used gcc -Wall -Werror, you would get the following errors:
luis.c:10:6: error: return type of ‘main’ is not ‘int’ [-Werror=main]
void main(){
^~~~
luis.c: In function ‘main’:
luis.c:15:19: error: passing argument 2 of ‘copyArray’ from incompatible pointer type [-Werror=incompatible-pointer-types]
copyArray(t1, t2,4);
^~
luis.c:8:6: note: expected ‘int (*)[32]’ but argument is of type ‘int *’
void copyArray(TablaArray, TablaArray*, int);
^~~~~~~~~
cc1: all warnings being treated as errors
The first one is simple, it should be int main.
The second one is a bit harder to see exactly because you used a typedef. So your prototype is now
void copyArray(int *, int (*)[32], int);
With the second value being a pointer-to-array that by itself is a construct that is not used often.
Instead, you'd just need two pointers to int here, and the size of an array should perhaps use size_t instead:
void copyArray(int *, int *, size_t);
void copyArray(int *t1, int *t2, size_t n){
for (int i = 0; i < tam; i++) {
t2[i] = t1[i];
}
}
Finally, if you use a C99, C11 compiler, it could be nice to use the variable-length arrays arrays to tell that one of the parameters tell the sizes of the arrays; for that we need to reorder the parameters:
void copyArray(size_t, int[*], int[*]);
void copyArray(size_t n, int t1[n], int t2[n]) {
...
}
void copyArray(TablaArray, TablaArray, int); // prototype
void copyArray(TablaArray t1, TablaArray t2, int tam){
for(int i = 0; i<tam; i++){
printf("%d\n", t1[i]);
t2[i] = t1[i];
}
}
this will help
// much faster
#include <string.h>
void copyArray(TablaArray t1, TablaArray t2, int tam){
memcpy(t2, t1, sizeof(t1[0]) * tam);
}
In Your Copy function you were copying the same value of T1 to T2 on the Address Of T2. you can do it with out pointers but pointers helps you to refer the Address