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
Related
I have a program that asks for a number of students and then for each of their first, last names and studentID. I'm attempting to print each of the values that are stored in the array of students. However, I get an error on the line printf("%d\n", *(students+i)->studentID); of Indirection requires pointer operand ('int' invalid).
I tried changing the line to printf("%d\n", (students+i)->studentID); and it seems to work. Why is this happening and why don't we need to do this for the print statements above that are printing characters? Thanks
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef struct Students {
char firstName[20];
char lastName[20];
int studentID;
} Student;
void printRecords(Student *students, int size){
for(int i = 0; i < size; i++){
printf("%c\n", *(students+i)->firstName); // prints
printf("%c\n", *(students+i)->lastName); // prints
printf("%d\n", *(students+i)->studentID); // does not print
}
}
int main(int argc, const char * argv[]) {
int number_of_records;
printf("Please enter the number of records you would like to add:\n");
scanf("%d", &number_of_records);
Student *S;
S = (Student*)malloc(sizeof(Student) * number_of_records);
for(int i = 0; i < number_of_records; i++){
printf("First name of student %d\n", i+1);
scanf("%s/n", S[i].firstName);
printf("Last name of student %d\n", i+1);
scanf("%s/n", S[i].lastName);
printf("StudentID of student %d\n", i+1);
scanf("%d/n", &S[i].studentID);
}
printRecords(S, number_of_records);
}
*(students+i)->studentID is an equivalent of *((students+i)->studentID)
You try to dereference the integer and you get the compile error.
The first compiles ok because
*(students+i)->firstName is the same as *((students+i)->firstName) and the member firstName is an array which decays to the pointer of the char * type. You can of course dereference pointers.
-> is an (implicit) indirection operator -- a->b is the same as (*a).b. So when you write
*(students+i)->studentID
that's the same as
*(*(students+i)).studentID
with TWO indirection operations.
You can use the indirection operator here, but then you use the member operator . instead of ->:
printf("%d\n", (*(students+i)).studentID);
This is semantically the same as
printf("%d\n", (students+i)->studentID);
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.
I am a student trying to learn c coming from c++. I wrote the following code and it compiles fine; however, when I execute it I get an endless loop when calling the print function. I looked over the code and it seems to be valid to me, so why is it printing an endless loop?
#include <stdio.h>
#include <stdlib.h>
struct student
{
int id;
int score;
};
void generate(struct student *students, int n)
{
int randomId = rand () % n + 1;
int randomTestScore = rand() % 100 + 1;
students->id = randomId;
students->score = randomTestScore;
}
void sort(struct student *students, int n)
{
/*using insertion sort*/
for (unsigned int i = 1; i < n; ++i)
{
int next = students[i].score;
int j = i;
while(j > 0 && students[j-1].score > next)
{
students[j].score = students[j-1].score;
j--;
}
students[j].score = next;
}
}
void print(struct student *students, int n)
{
for (unsigned int i = 0; i < n; i++)
{
printf("Student at position No: %d Test Score: %d\n", i+1, students[i].score);
}
}
int main()
{
/*user enters num of students to create scores for*/
int num_students;
printf("Enter Num of students\n");
scanf("%d", num_students);
/*allocate memory for the amount of students user wants*/
struct student *userStudents = malloc(num_students*sizeof(struct student));
printf("Randomly filling students IDs & Test Scores...\n");
for (unsigned int i = 0; i < num_students; ++i)
{
generate(&userStudents[i], num_students);
}
printf("Array of students before sorting:\n");
print(userStudents, num_students);
printf("\nNow, sorting students by test scores...\n\n");
sort(userStudents, num_students);
printf("Array of students after sorting:\n");
print(userStudents, num_students);
return 0;
}
To use scanf() correctly it needs to alter the passed variable in place, and since there is no pass by refrence in c, you need to pass the address of the variable, so scanf() is able to modify it though a pointer, hence you need to use the & operator, but that is not enough.
The scanf() family of functions, return a value that must be checked before you can access the scanned values, you should never ignore that value, under any circumstances you should check for it.
What your code is doing is called undefined behavior, it's interpreting the passed integer as if it was a pointer, which is undefined behavior.
To prevent that you can activate compiler warnings, many compilers know what kind of parameter the *f functions expect, i.e. the functions which take a string as a format to be parsed and to allow the function to correctly grab the rest of the parameters passed via variable arguments to it.
The correct way to call scanf() in your program is
if (scanf("%d", &num_students) != 1)
return 1;
that is, from main() and hence it's ending the program, because you can't continue after that condition was true, in that case what actually happens is that num_students is not initialized, that would once again cause undefined behavior.
Change the call to scanf to:
/*
* correct way of calling scanf, passing the address of the wanted variable
*/
scanf("%d", &num_students);
^
This elliminates segmentation faults and makes the code runs OK on my machine.
I had a previous hint that you'd need to change your declaration of userStudents to a pointer to pointers, however I was incorrect. You are clearly correctly allocating enough contiguous memory to hold all of your structs pointed by *userStudents.
I have been trying to see where the problem is but couldnt find it. Every time, the values of array memory gives me 0, even though int count works and keeps counting as the struct data value, only array does not save the value.
#include<stdlib.h>
#include<stdio.h>
#define SIZE 1000
struct registers
{
int data;
} registerX;
void first(int *counter, struct registers* X1, int m[][2])
{
int value;
printf("Enter the value for the X\n");
scanf("%d", &value);
X1->data = value;
m[*counter][1] = X1->data;
*counter = ++*counter;
}
int main()
{
int memory[SIZE][2];
int choice;
int count = 0;
printf("Enter the instruction number:\n");
while(choice != 107)
{
scanf("%d", &choice);
if(choice == 101)
{
memory[count][0] = 101;
first(&count, ®isterX, memory);
printf("%d\n", memory[count][1]);
printf("%d\n", memory[count][0]);
}
}
}
You have some problems in your code.
Firstly,choice in while(choice != 107) is uninitialized. To fix it,use a do...while loop instead of a while loop as you want the loop body to execute once before checking the condition.
Secondly,*counter = ++*counter; undefined behaviour has KerrekSB points out in his comment. To fix it,use (*counter)++;.
Lastly,you print uninitialized elements of your array in the last two printfs. The reason is that you increment *counter in the function which will also modify count in main as counter is a pointer which points to the address of count.
I'm working on a homework assignment and I've hit a brick wall. I think I have all of the code that I need, I just need to get the program to compile. The object of the assignment is
Create a structure to hold student names and averages. The structure should contain a first name, last name and an integer grade average.
Then:
Write a program that will do the following:
1.) Create an array of pointers to these student structures.
2.) Prompt the user for names and averages.
3.) After you get the student’s information use malloc to provide the memory to store the information.
4.) Place the address of the student, returned by malloc, into the pointer array.
5.) AFTER the user indicates there are no more students:
Search the data entered and find the highest and lowest grade
average.
a)Print the name and grade for the highest grade
b)Print the name and grade for the lowest grade
c)Print the average of all grades entered
Here is my code:
#include "stdafx.h"
#include <string.h>
#include <stdlib.h>
#define SIZE 25
int enterStudents (int ePointArray[SIZE]);
void searchData (int *sPointArray, int *sHigh, int *sLow);
int calculateAvg (int, int *avgPointArray);
void printData (int, int *pHigh, int *pLow);
struct student
{
char firstName[20];
char lastName[20];
int average;
};
int main()
{
int pointArray[SIZE], high[3], low[3];
int i = 0, studentCounter, avgGrade;
for (i = 0; i < SIZE; i++)
pointArray[i] = 0;
studentCounter = enterStudents(pointArray);
searchData(pointArray, high, low);
avgGrade = calculateAvg(studentCounter, pointArray);
printData(avgGrade, high, low);
return 0;
}
int enterStudents (int ePointArray[SIZE])
{
char tempFname[20], tempLname[20], yesNo[2] = "y";
int tempAvg, counter = 0;
int *studPtr;
struct student aStud={"\0", "\0", 0};
while( counter < SIZE && strcmp(yesNo, "y")==0)
{
printf(" Enter first name: ");
scanf("%s", tempFname);
printf(" Enter last name: ");
scanf("%s", tempLname);
printf(" Enter grade average:");
scanf("%d", tempAvg);
strcpy(aStud.firstName, tempFname);
strcpy(aStud.lastName, tempLname);
aStud.average = tempAvg;
studPtr = malloc(sizeof(struct student));
ePointArray[counter] = *studPtr;
counter++;
printf("/n");
printf(" Do you have more students? yes or no:");
scanf("%s", yesNo);
}
return counter;
}
void searchData (int sPointArray[SIZE], int sHigh[3], int sLow[3])
{
int searchCounter = 0;
while( searchCounter = 0)
{
if( *sPointArray[searchCounter].average > *sPointArray[searchCounter+1].average)
{
sHigh[0] = &sPointArray[searchCounter].firstName;
sHigh[1] = &sPointArray[searchCounter].lastName;
sHigh[2] = &sPointArray[searchCounter].average;
}
if( *sPointArray[searchCounter].average < *sPointArray[searchCounter+1].average)
{
sLow[0] = &sPointArray[searchCounter].firstName;
sLow[1] = &sPointArray[searchCounter].lastName;
sLow[3] = &sPointArray[searchCounter].average;
}
searchCounter++;
}
}
int calculateAvg( int totalStudents, int avgPointArray[SIZE])
{
int sum = 0;
int avgCounter;
double overallAvg;
for( avgCounter = 0; avgCounter < totalStudents; avgCounter++)
sum = sum + *avgPointArray[avgCounter].average;
overallAvg = sum/totalStudents;
return overallAvg;
}
void printData (int pAverage, int pHigh[3], int pLow[3])
{
printf(" Highest Grade: %s %s %d", pHigh[0], pHigh[1], pHigh[3]);
printf("/n");
printf(" Lowest Grade: %s %s %d", pLow[0], pLow[2], pLow[3]);
printf("/n");
printf(" Average Grade: %d",pAverage);
}
The main chunk of problems come from the searchData function. In the if statements, every occurrence of *sPointArray and &sPointArray is underlined in red and the error reads
"Error: expression must have class type"
The same thing also happens in the calculateAvg function with *avgPointArray in the for loop. I know that the error is a fairly common problem for noobie C programmers (i.e myself) and that it generally has to do with writing the code as a function instead of a statement or something like that, but I can't for the life of me find where I have went wrong. Any help would be highly appreciated. I've been working at this for so long my vision is blurring.
Also, for anyone who solves this in like two seconds and wants proof that I'm a true idiot, there is an error in the enterStudents function where it says StudPtr = malloc(sizeof...). The error shows under the assignment symbol and says
"Error: a value of type "void*" cannot be assigned to an entity of type "int*".
I understand this concept in theory, but some advice for how to fix it would be highly appreciated.
Thank you in advance for any help.
You declare the sPointArray as an array of integers, but use it as an array of structures.