trouble trying to use a struct variable - c

I’m learning C programming and I’m trying to make a simple program to store points in the XY plane.
At first I did it like this:
#include<stdio.h>
#include<stdlib.h>
typedef struct point { float x, y; } PNT;
typedef struct plane
{
int n_points;
PNT pt[50];
} plane;
void points_input(plane planexy);
void points_distance(plane planexy);
int main()
{
plane planexy;
printf("How many points do you want to enter? : ");
scanf("%d", &planexy.n_points);
points_input(planexy);
points_distance(planexy);
}
void points_input(plane planexy)
{
int i;
for (i = 0; i < planexy.n_points; i++)
{
printf("\nEnter a coordinate for x%d ", i);
scanf("%f", &planexy.pt[i].x);
printf("\nEnter a coordinate for y%d ", i);
scanf("%f", &planexy.pt[i].y);
system("cls");
}
}
void points_distance(plane planexy)
{
int i;
printf("Select first point :\n");
for (i = 0; i < planexy.n_points; i++)
{
printf("\n %d.(%.1f ,%.1f)", i, planexy.pt[i].x, planexy.pt[i].y);
}
}
And it doesn’t work, when I try to access one of the variables of a point it always returns a 0.
After messing with the variable name “planexy” and using it as a vector of size 1, and then using all mentions of it as planexy[0], it suddenly started to work :
#include<stdio.h>
#include<stdlib.h>
typedef struct point { float x, y; } PNT;
typedef struct plane
{
int n_points;
PNT pt[50];
} plane;
void points_input(plane planexy[]);
void points_distance(plane planexy[]);
int main()
{
plane planexy[1];
printf("How many points do you want to enter? : ");
scanf("%d", &planexy[0].n_points);
points_input(planexy);
points_distance(planexy);
}
void points_input(plane planexy[])
{
int i;
for (i = 0; i < planexy[0].n_points; i++)
{
printf("\nEnter a coordinate for x%d ", i);
scanf("%f", &planexy[0].pt[i].x);
printf("\nEnter a coordinate for y%d ", i);
scanf("%f", &planexy[0].pt[i].y);
system("cls");
}
}
void points_distance(plane planexy[])
{
int i;
printf("Select first point :\n");
for (i = 0; i < planexy[0].n_points; i++)
{
printf("\n %d.(%.1f ,%.1f)", i, planexy[0].pt[i].x, planexy[0].pt[i].y);
}
}
Now, this code works, but I don’t know why I had to put it this way for it to function, and it doesn't seem like it's good code.
I get that if I want to use multiple planes "XY" I should store the variable as a vector, but I just want to use one, I don't understand why it works when I use a vector of size 1 but it doesn't when I just want to use one variable to store a single plane.
What's wrong with the first approach?
Sorry for bad English.

I've edited your question to English so other people can understand it in SO.
I hope you accept it as I'll answer in English.
You're passing a copy of the object planexy in the function points_input() so the actual planexy that's defined in main() doesn't change. Instead, you should pass a pointer that points to it then modify the object pointed by that pointer.
The modified code:
Forward declartion
void points_input(plane* planexy); // ingreso_puntos function
Code
void points_input(plane* planexy)
{
int i;
for (i = 0; i < planexy->n_points; i++)
{
printf("\nEnter a coordinate for x%d ", i);
scanf("%f", &planexy->pt[i].x);
printf("\nEnter a coordinate for y%d ", i);
scanf("%f", &planexy->pt[i].y);
system("cls");
}
}
When using pointers, you use -> instead of the dot . which is only for objects.
Why did it work with an array as your second code?
Simply, arrays/vectors are actual pointers by themselves.
Proof:
scanf("%f", &planexy[0].pt[i].x); is the same as scanf("%f", &planexy->pt[i].x);.
In main(). You should pass the address of the planexy which creates the pointer.
points_input(&planexy);
Tip: When you want to modify an object through a function, you pass a pointer to it exactly as you do with scanf. Otherwise, when you want to just read an object, you pass it normally.

The errors you get from the compiler when you compile this tell you what is wrong:
program.c: In function ‘main’:
program.c:23:20: error: incompatible type for argument 1 of ‘ingreso_puntos’
ingreso_puntos(planexy);
^
program.c:15:6: note: expected ‘plane * {aka struct plane *}’ but argument is of type ‘plane {aka struct plane}’
void ingreso_puntos(plane planexy[]);
^
You've declared your functions as taking a pointer to a plane (plane *), but you're calling them with a plane. Use the & operator to get the address of planexy to pass to the function.
program.c: In function ‘ingreso_puntos’:
program.c:31:28: error: request for member ‘n_puntos’ in something not a structure or union
for (i = 0; i < planexy.n_puntos; i++)
^
Here in the function, planexy is a pointer to a plane, so you need -> instead of . to access fields from it.

Related

Reading and Printing a matrix

I tried to read and print a matrix using an external function (from another c file), the thing is that I want to read the matrix dimensions in the function and store them in the main function, how can I do this?
Do I need to return an array with the m and n dimensions of the matrix or can I access the variables that I created in main and change their value within the external function? (I prefer if someone would explain the second) I don't actually know how to use pointers and stuff.
Sorry for my English, I'm not a native speaker, also thanks for your response
The second and the third functions are in an external function.c file
int main(){
int num_of_rows, num_of_columns;
int matrix[10][10];
read_matrix(num_of_rows, num_of_columns, matrix);
print_matrix(num_of_rows, num_of_columns, matrix);
printf("\n Press any key to exit the program: ");
_getch();
return 0;
}
void read_matrix(int num_of_rows, int num_of_columns, int matrix[10][10]){
int i,j;
printf("\nPlease specify the number of rows:");
scanf("%d", &num_of_rows);
printf("\nPlease specify the number of columns: ");
scanf("%d", &num_of_columns);
printf("\nPlease introduce the matrix elements below:\n");
for(i=0; i<num_of_rows; i++){
for(j=0; j<num_of_columns; j++){
printf("matrix[%d][%d]= ", i, j);
scanf("%d", &matrix[i][j]);
}
}
}
void print_matrix(int num_of_rows, int num_of_columns, int matrix[10][10]){
int i,j;
for(i=0; i<num_of_rows; i++){
for(j=0; j<num_of_columns; j++){
printf("matrix[%d][%d]= %d", i, j, matrix[i][j]);
}
}
}
Parameters are passed by value in C.
In read_matrix, the num_of_rows parameter is a local variable. Even if you modify it, the caller won't see anything change. Same for num_of_columns.
You want this:
void read_matrix(int *num_of_rows, int *num_of_columns, int matrix[10][10]) {
// ^ add * ^ add *
...
scanf("%d", num_of_rows); // << remove the &
printf("\nPlease specify the number of columns: ");
scanf("%d", num_of_columns); // << remove the &
...
for (i = 0; i < *num_of_rows; i++) {
// ^add *
for (j = 0; j < *num_of_columns; j++) {
// ^add *
and in main:
read_matrix(&num_of_rows, &num_of_columns, matrix);
// ^ ^ add the &s
This is basic knowledge that is covered in your C learning material. Most likely in the chapter dealing with pointers and the one dealing with function calls.
Here's the catch. I tested your code and it works nicely. The problem is, what you want to achieve is only possible by using dynamic memory allocation. Take a look at the malloc and free functions.
You can read more about it on:
https://www.tutorialspoint.com/what-is-malloc-in-c-language
https://www.tutorialspoint.com/how-do-malloc-and-free-work-in-c-cplusplus
In C language you are responsible for allocation a space in memory for variable length data structures. Pointers just store an address to a specific memory space allocated to the desired data type.
e.g.:
int n, *p;
p = (int*) malloc(n * sizeof(int));
In this example, you are just giving p an address to the first integer from n integers you just allocated.
p will work just like a vector when using for loops because behind the scenes, it's exactly what happens when you traverse your fixed length vectors and matrices, but this time you were in control of it's length in runtime.
#include<stdio.h>
void main()
{
int x[3][3], p, q, max;
printf("Enter the elements of matrix: \n");
for(p=0;p<3;p++)
{
for(q=0;q<3;q++)
scanf("%d", &x[p][q]);
}
max=x[0][0];
printf("The matrix is as follows: \n");
for(p=0;p<3;p++)
{
for(q=0;q<=3;q++)
scanf(" %d", &x[p][q]);
}
for(p=0;p<3;p++)
{
for(q=0;q<3;q++)
{
if(x[p][q]>max)
max=x[p][q];
}
printf("\n");
}
printf("Maximum number in the matrix is: %d", max);
}
Output:
Enter the elements of matrix:
23 65 12
12 23 56
12 10 32
The matrix is as follows:
23 65 12
12 23 56
12 10 32
Maximum number in the matrix is: 65
Matrix Programs
Explore more matrix programs.

How do you pass 2-dimensional array of character into a function?

So i'm trying to pass
char parent[n][50];
into a function initialize();
And then copy the char x, into the parent [ i ] inside the initialize(); function. Example
x = "Cityname"
and when passed into the initialize();
it would do
strcpy(parent[i], x);
to make the
parent[i] = "Cityname"
void initialize(char *parent, int *ranks, char x, int i){
strcpy(parent[i], x);
ranks[i] = '0';
}
int main(){
int n, i = 1;
char x[20];
printf("Enter how many city are there : "); scanf("%d", &n); fflush(stdin);
char parent[n][20];
int ranks[n];
while(1){
printf("enter city name: "); scanf("%[^\n]", x);
if(i <= n){
initialize(parent[][20], ranks, x, i);
i++;
} else {
printf("The city is at maximum\n");
}
}
}
It tells a warning:
passing argument 1 of 'strcpy' makes pointer from integer without a cast
note: expected 'char *' but argument is of type 'char'
and also in function main
error: expected expression before ']' token
Can anyone explain how to strcpy(parent[i], x) correctly? I can't seem to figure this problem out.
I see several problems with your code. Arrays vs pointers in C can be confusing, so there are a few rules to keep in mind:
char x[n] can be automatically converted by the C compiler to char *x.
char x[10][20] is represented under the hood as a 1D array, and the compiler computes the offsets behind the scenes. For example, if x were a 10 x 20 array, the expression x[1][2] could be compiled as *(x + 22). For this reason, it can cause surprising results to cast a 2D array to a char*, and it is invalid to cast a 2D array to a char**.
With these rules in mind, here is how I would change your code
void initialize(char (*parent)[20], int *ranks, char *x, int i){
strcpy(parent[i], x);
ranks[i] = '0'; // Did you want an automatic conversion from char to int here? Maybe you meant ranks[i] = 0?
}
int main(){
int n, i = 0; // As Craig mentions, i should start at 0.
char x[20];
printf("Enter how many city are there : "); scanf("%d", &n); fflush(stdin);
char parent[n][20];
int ranks[n];
while(1){
printf("enter city name: "); scanf("%19s", x); // scanf will automatically stop at whitespace, and you must include the max length to avoid a buffer overrun.
if(i < n){
initialize(parent, ranks, x, i);
i++;
} else {
printf("The city is at maximum\n");
// Maybe break here, unless you want an infinite loop
}
}
}

Creating a function for a random number 2D array

So, I have this code which I need to turn into a function:
int main(void) {
int i=0,seed;
printf("\n\nEnter seed integer value: ");
scanf("%d", &seed);
printf("\nSeed value is:%d\n\n",seed);
srand(seed);
int a[5][5];
int x,y;
printf("Matrix A:\n");
for(x=0;x<5;x++) {
for(y=0;y<5;y++) {
a[x][y] = rand() %51 + (-25);
printf("%d ",a[x][y]); }
printf("\n"); }
printf("\n\n");
So basically, it produces a 2D 5x5 array of random numbers. This works fine, however my next task is applying a function to this code, with the function name of:
void generate_matrices(int a[5][5])
I have tried multiple times, the closest I got to a successful code was:
#include <stdio.h>
#include <stdlib.h>
void generate_matrices(int a[5][5]);
int main(void) {
int a, seed;
printf("\n\nEnter seed integer value: ");
scanf("%d", &seed);
srand(seed);
printf("\nSeed value is:%d\n\n",seed);
generate_matrices(a);
return 0;
}
void generate_matrices(int a[5][5]) {
int y,z;
printf("Matrix A:\n");
for(y=0;y<5;y++) {
for(z=0;z<5;z++) {
a[y][z] = rand() %51 + (-25); }
printf("%d ",a[y][z]); }
printf("\n");
}
But this returns the error, "expected 'int(*)[5]' but arguement is of type 'int'.
All/any help is muchly appreciated. To be fair on my part, I have done 90% of the code. This is the only bit I need help with so that I can apply this to the rest of my code.
Cheers!
You have declared a as a single integer on this line int a, seed;
When you call the function with generate_matrices(a); you are passing a single integer instead of a pointer to an array.
Change your declaration line to int a[5][5], seed;
generate_matrices(a); will pass a pointer to the first element in your 5 * 5 array, to the function.
You should really print the results in main and not in the function, then you will know that the array has been modified and is available for use in the body of your program.
You have used unconventional placement of braces '}' and this makes it harder to see what belongs in each part of your for loops.
You have the print statements in the wrong places - as a result only part of the matrix is printed.
This is what it should be (just the results - in main):
printf("Matrix\n ");
for (y = 0; y < 5; y++) {
for (z = 0; z < 5; z++) {
printf("%d\t ", a[y][z]);
}
printf("\n");
}
If you use int a[5][5] and call the function with generate_matrices(a);
a function void generate_matrices(int a[5][5]) {...} compiles without error
#include<stdio.h>
#include<stdlib.h>
void modify(int b[5][5]);
int main()
{
srand(4562);
int i,j,arr[5][5];
modify(arr);
for(i=0;i<5;i++){
for(j=0;j<5;j++){
printf("%d ",arr[i][j]=rand() %51 + (-26)); }
}
return 0;
}
void modify(int b[5][5])
{
int i,j;
for(i=0;i<5;i++) {
for(j=0;j<5;j++) {
b[i][j]; }
}
}
So this is the closest I have come to completing it. It produces the number of elements I want, also within the range I want. However its not producing the 5x5 grid I need. Where have I gone wrong?
EDIT: I'm not going for neatness at the moment, I just want to get the program working how I want it too and then i'll neaten it up.
EDIT 2: Never mind, realised what I didn't include. Its fine now. Thanks for the help.

How to assign value to procedure's struct parameter?

I'm making a program to input some data to array of struct. When I tried to assign temporary struct temp to procedure's struct parameter *daf, the program's always force closed. Here's my code:
#include <stdio.h>
typedef struct {
int num;
char name[50];
float value;
} Mhs;
typedef Mhs ListMhs[50];
void inputData(int nEf, ListMhs *daf);
int main() {
ListMhs listmhs;
inputData(5, &listmhs);
return 0;
}
void inputData(int nEf, ListMhs *daf) {
int i;
ListMhs temp;
for (i=0; i<nEf; i++) {
printf("Num: ");
scanf("%d", &temp[i].num);
printf("Name: ");
scanf("%s", &temp[i].name);
printf("Value: ");
scanf("%f", &temp[i].value);
}
//assign value
for (i=0; i<nEf; i++) {
*daf[i] = temp[i];
}
}
Your problem lies in the line *daf[i] = temp[i];
[] has higher precedence than *
So it should be (*daf)[i] = temp[i];
The original line *daf[i] = temp[i]; is actually *(daf[i]) = temp[i];and was trying to treat daf as an array of ListMhs and taking the ith element of it and then dereferencing it. Obviously as you were only passing in a pointer to one ListMhs, as soon as i was greater than 0 you would have problems. The program probably tried to write to protected memory after the second or third iteration, which is why it hard crashed. If you had a debugger of some sort attached you would have probably got a more helpful error.
Here is the list of C++ operator precedence: http://en.cppreference.com/w/cpp/language/operator_precedence

error: request for member 'valore' in something not a structure or union

It tells me that there was an error. For me it's a problem of pointer or something about the structure, but I don't know exactly.
#include <stdio.h>
#include <stdlib.h>
#define MAX 100
typedef struct
{
char luogo[20];
float valore;
}rilevazione;
void BubbleSort(float valore[], int n);
int main()
{
int i=0, n=0, j=0;
rilevazione*dato=NULL;
dato=(rilevazione*)malloc(MAX*sizeof(rilevazione));
while(i<MAX)
{
printf("inserisci luogo %d: ", i+1);
scanf("%s", dato[i].luogo);
printf("inserisci valore %d: ", i+1);
scanf("%f", &dato[i].valore);
if(strcmp(dato[i].luogo, "end")==0) break;
i++;
}
n=i;
printf("il numero di misure e' %d", n);
scanf("%d", &n);
BubbleSort(dato.valore, n);
for(j=0; j<n; j++)
{
printf("valore: %d luogo: %s", dato[i].valore, dato[i].luogo);
}
return 0;
}
void BubbleSort(float valore[], int n)
{
int i=0, temp=0, j=0;
int scambi=1;
while(i<=n && scambi!=0)
{
scambi=0;
j=n;
while(j>=i)
{
if(valore[j]>valore[j+1])
{
temp=valore[j];
valore[j]=valore[j+1];
valore[j+1]=temp;
scambi=1;
}
j=j-1;
}
i=i+1;
}
return;
}
Your BubbleSort takes an array of floats but you are are trying to pass it just one float and not correctly either. dato.valore has no meaning. dato[n].valore does. Do you see the difference?
Choices:
create an array of floats from your array of structs.
Update BubbleSort to sort the struct array you already have.
Update your sort routine to take a function pointer and calls the function for each item in the list to be sorted.
The last choice is how most libraries deal with this.
That's probably because when you do
BubbleSort(dato.valore, n);
you are missing an index in dato... which is a pointer.
So you would need something like dato[XXX].valore.
rilevazione*dato=NULL;
dato=(rilevazione*)malloc(MAX*sizeof(rilevazione));
change to
rilevazione *dato;
dato=(rilevazione*)malloc(MAX*sizeof(rilevazione));
if (dato == NULL) { error in malloc'ing data array...
Always check the result of a memory allocation. I'm not sure if C will recognize a pointer declaration when it's all jammed together -- better be safe and put a space in there.
Since dato is an array (actually, a pointer to an array), I suspect that your call to BubbleSort() is not happy with treating it as a scalar structure. You're going to have to pass the entire array of structures into BubbleSort and pick apart the valore component inside the function.
I'll assume that the use of a Bubble Sort is merely incidental and that for real production code you'd use something a little faster running.
That's probably because when you do
BubbleSort(dato.valore, n);
you are missing an index in dato... which is a pointer, so it needs an index.
So you would need something like dato[index].valore.

Resources