How to scanf() and printf() nested structs in C? - c

I created two structs, each of which I defined as a 3rd struct variable. I'm confused about calling those variables in the scanf() function and the printf() function. This is my code so far
#include <stdio.h>
#include <string.h>
#define MAX 5
typedef struct {
char namaJalan[30];
int noRumah;
char kota[30];
char provinsi[30];
} Alamat;
typedef struct {
int tanggal;
int bulan;
int tahun;
} tanggalLahir;
typedef struct {
int noDosen;
int nidn;
char nama[30];
char tempat[30];
Alamat alamat;
tanggalLahir tglLahir;
} dataDosen;
int main() {
Alamat a;
tanggalLahir t;
dataDosen d[MAX];
for (int i = 0; i < MAX; i++) {
printf("\nData dosen ke %d\n", i+1);
printf("No. Dosen: ");
scanf("%d", &d[i].noDosen);
printf("NIDN: ");
scanf("%d", &d[i].nidn);
printf("Nama: ");
scanf("%s", d[i].nama);
printf("Alamat (Jalan - No. - Kota - Provinsi ): ");
I'm confused to define this scanf
//how to define scanf variable made of struct?
scanf("%s%d%s%s", &d[i].alamat);
printf("Tempat lahir: ");
scanf("%s", d[i].tempat);
printf("Tanggal lahir (DD/MM/YYYY): ");
scanf("%d%d%d", &d[i].tglLahir);
}
printf("================ DATA DOSEN ==================\n");
printf("\n");
printf("NO\tNIDN\tNAMA\tALAMAT\tTEMPAT LAHIR\tTANGGAL LAHIR");
And how to define printf variable made of struct?
for (int i = 0; i < MAX; i++) {
printf("%d\t%d\t%s\t%s%d%s\t%s\t%d%d%d\n",
d[i].noDosen, d[i].nidn, d[i].nama, d[i].alamat, d[i].tempat, d[i].tglLahir);
}
return 0;
}

Related

Sort a structure in descending order

I have to sort this strucure in descending order, based on the "med" variable stored in this strucure, so if students 1 med > students 2 med, then the struct shall be printed as : * student 2 info * then * student 1 info *
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
struct om
{
char name[20];
int n1,n2,n3;
float med;
} a[3];
int main()
{
int i;
printf("Student's data");
for (i=0; i<3; i++)
{
printf("\nName:");
scanf("%s", a[i].name);
printf("\nGrade at maths:");
scanf("%d", &a[i].n1);
printf("\nGrade at programming:");
scanf("%d", &a[i].n2);
printf("\nGrade at english:");
scanf("%d", &a[i].n3);
a[i].med=(a[i].n1+a[i].n2+a[i].n3)/3;
}
}
Here is an example of how to do this, try to understand how the sorting function works based on some example inputs:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define NUM_STUDENTS 3
struct student
{
char name[20];
int math, prog, engl;
double avg;
} students[NUM_STUDENTS];
static int compare_students(const void *s1, const void *s2)
{
double avg1 = ((struct student *)s1)->avg;
double avg2 = ((struct student *)s2)->avg;
return (avg1 > avg2) - (avg1 < avg2);
}
int main()
{
printf("Student data:\n");
for (int i=0; i<NUM_STUDENTS; i++)
{
printf("Name:");
scanf("%s", students[i].name);
printf("Grade at maths:");
scanf("%d", &students[i].math);
printf("Grade at programming:");
scanf("%d", &students[i].prog);
printf("Grade at english:");
scanf("%d", &students[i].engl);
students[i].avg = (double)students[i].math + students[i].prog + students[i].engl) / NUM_STUDENTS;
}
qsort(students, NUM_STUDENTS, sizeof(struct student), compare_students);
for (int i=0; i<NUM_STUDENTS; i++)
{
printf("Student %d: %s\n", i, students[i].name);
}
return 0;
}
I have also tried to make some general improvements, like adding a #define for the number of students, using more readable variable names and using double instead of float variables (using the latter almost never makes sense in practice). Also note that your average calculation was wrong before because the result was truncated.
man_d_sort(struct om a[])
{
if (a[0].med >= a[1].med)
{
if (a[0].med >= a[2].med)
printf("%.2lf", a[0].med);
else
printf("%.2lf", a[2].med);
}
else
{
if (a[1].med >= a[2].med)
printf("%.2lf ", a[1].med);
else
printf("%.2lf ", a[2].med);
}
}

Structure Array Size in C

I am quite new to programming. Memory allocation also, still confuses me. And our professor asked us to make an array of structures wherein users will input the array size. This is to know how many entries will the users enter in the telephone directory.
Here is it so far:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
struct TelDirectory {
char name[50];
char address[100];
char tel[20];
};
int main() {
int num, add, del, prev = 0;
char ask;
*//asking for the number of entries*
printf("Number of entries: ");
scanf(" %i", &num);
struct TelDirectory *entry[num];
Input(entry, prev, num);
Display(entry, num);
//Input and Displaying
void Input(struct TelDirectory *entry[], int prev, int num) {
int i;
for (i = prev; i < num; i++) {
entry[i] = (struct TelDirectory *)malloc(sizeof(struct TelDirectory) * num);
printf("\nEnter name (last, first, middle): ");
scanf(" %[^\n]", entry[i]->name);
printf("Enter address: ");
scanf(" %[^\n]", entry[i]->address);
printf("Enter telephone number: ");
scanf(" %[^\n]", entry[i]->tel);
}
void Display(struct TelDirectory *entry[], int num) {
int i, j;
printf("%i\n", num);
struct TelDirectory *temp;
temp = (struct TelDirectory *) malloc(sizeof(struct TelDirectory) * num);
for (i = 0; i < num; i++) {
for (j = i+1; j < num; j++) {
if (strcasecmp(entry[i]->name, entry[j]->name) > 0) {
temp = entry[i];
entry[i] = entry[j];
entry[j] = temp;
}
}
}
printf("\n\t\t\t\t\tInformation\n");
printf("------------------------------------------------------------------------------------------------\n");
printf("Name\t\t\t\t\tAddress\t\t\t\t\tTelephone Number\n");
printf("------------------------------------------------------------------------------------------------\n");
for (i = 0; i < num; i++) {
printf("%-30s\t\t%-30s\t\t%-30s\n", entry[i]->name, entry[i]->address, entry[i]->tel);
}
printf("------------------------------------------------------------------------------------------------\n");
}
And, we will also be asking the users if they will update the directory through either INSERTING more entries or DELETING entries. Is it possible to change the structure array size on run time?

C - Passing a pointer to an array to a function to print the array

I have a code like this for a student management system. The input function works fine but I haven't figured out why my output function stop immediately when i call it.( I know that i can not return a local array from a function in C, but i assign the array to a pointer and return that pointer, is it ok?)
Here is my code:
struct Student
{
char name[50];
char birth[25];
char gender[10];
float math, physics;
};
struct Student* input(int n, struct Student *p)
{
int i, id = 1;
struct Student s[n];
getchar();
for(i = 0; i < n; i++)
{
printf("Name: ");
fgets(s[i].name, 50, stdin);
s[i].name[strlen(s[i].name)-1] = '\0';
printf("Date of birth: ");
fgets(s[i].birth,25,stdin);
s[i].birth[strlen(s[i].birth)-1] = '\0';
printf("Gender: ");
fgets(s[i].gender,10,stdin);
s[i].gender[strlen(s[i].gender)-1] = '\0';
printf("Math = ");
scanf("%f", &s[i].math);
printf("Physics = ");
scanf("%f", &s[i].physics);
getchar();
}
p = s;
return p;
}
void outPut(int n, struct Student *p)
{
int i;
for(i = 0; i < n; i++)
{
printf("%s %s %s %f %f\n", p[i].name, p[i].birth, p[i].gender, p[i].math, p[i].physics);
}
}
int main()
{
int n;
struct Student *p, *p1;
int choice;
printf("-----------Student Management-----------");
printf("\n1. Add new students.\n2. Print student list.\n");
do
{
printf("Your choice = ");
scanf("%d", &choice);
switch(choice)
{
case 1:
printf("Number of students = ");
scanf("%d", &n);
input(n,p);
break;
case 2:
outPut(n,p);
break;
}
}
while(choice!=0);
return 0;
}
You are defining your array as a local variable. It means that it will no longer exist after the function ends. To avoid this, declare your array as a pointer and use malloc to initialize it:
struct Student *s = malloc(sizeof(Student) * n);
It will behave as a regular array and you will be able to use itself as the function return.

I'm trying to create a program with a loop that prompts the user to enter data in the array elements

I'm trying to create a program with a loop that prompts the user to enter data in the array elements. And when the user no longer can enter data, print to screen the data entered in a last in, first out order.
And this is my attempt...
#include <stdio.h>
#include <math.h>
#include <stdlib.h>
#include <string.h>
struct Name_Age
{
char Name[10];
int Age;
};
void printMe(struct Name_Age info)
{
printf("Name: %s\n", info.Name);
printf("Age: %d\n", info.Age);
}
int main()
{
int size = 0, i = 0, j = 0;
struct Name_Age * array_ptr = (struct Name_Age*)malloc((size + 1)* sizeof(struct Name_Age));
struct Name_Age myInfo = *array_ptr;
printf("Enter size of array: ");
scanf("%d\n", size);
for (i = 0; i < size; ++i)
{
printf("Enter Name: \n");
scanf("%s\n", myInfo.Name);
printf("Enter Age: \n");
scanf("%d\n", myInfo.Age);
}
printMe(myInfo);
return 0;
};
First, scanf("%d", &size) replace scanf("%d\n", size), put &size instead of size as argument(You need an address), and put the malloc things after this line of code, because you need an exact size value before malloc. Same thing with all the scanf stuffs.
As you want to print out all your input names and ages in order, I changed your code like this:
#include <stdio.h>
#include <stdlib.h>
struct Name_Age
{
char Name[10];
int Age;
};
void printMe(struct Name_Age *infoList, int size)
{
int i;
for (i = size-1; i >= 0; --i)
{
printf("Name: %s\n", infoList[i].Name);
printf("Age: %d\n", infoList[i].Age);
printf("\n");
}
}
int main()
{
int size, i;
printf("Enter size of array: ");
scanf("%d", &size);
struct Name_Age * array_ptr = (struct Name_Age*)malloc(size* sizeof(struct Name_Age));
for (i = 0; i < size; ++i)
{
printf("Enter Name: \n");
scanf("%s", array_ptr[i].Name);
printf("Enter Age: \n");
scanf("%d", &array_ptr[i].Age);
}
printMe(array_ptr, size);
return 0;
}
Try to test and compare with your code, questions are welcome.
You can use fgets to read strings and cast the string to digits with atoi. The storage is not complete, but with my changes you can read to structs and specify the size of the loop (TODO: Save a list of structs so that you actually can print a list of structs that you have specified.)
#include <stdio.h>
#include <stdlib.h>
struct Name_Age {
char Name[10];
int Age;
};
void printMe(struct Name_Age info) {
printf("Name: %s\n", info.Name);
printf("Age: %d\n", info.Age);
}
int main() {
int size = 0, i = 0, j = 0;
struct Name_Age *array_ptr = malloc((size + 1) * sizeof(struct Name_Age));
struct Name_Age myInfo = *array_ptr;
printf("Enter size of array: ");
char tmp[10];
fgets(tmp, 10,stdin);
size = atoi(tmp);
for (i = 0; i < size; ++i) {
printf("Enter Name: ");
fgets(myInfo.Name, 10,stdin);
printf("Enter Age: ");
fgets(tmp, 10,stdin);
myInfo.Age = atoi(tmp);
}
printMe(myInfo);
return 0;
};
Test
$ ./a.out
Enter size of array: 2
Enter Name: Superman
Enter Age: 25
Enter Name: Batman
Enter Age: 27
Name: Batman
Age: 27
See also this question about fgets fgets how to read int
Obviously using fgets() is a much better approach, but making the fewest amount of changes as possible to your code and still achieving your result is the following:
#include <stdio.h>
#include <stdlib.h>
struct Name_Age
{
char Name[10];
int Age;
};
void printMe(struct Name_Age *info);
int main(void)
{
int size, i;
struct Name_Age *array_ptr;
printf("Enter size of array: ");
scanf("%d", &size);
array_ptr = malloc(size * sizeof *array_ptr);
for (i = 0; i < size; ++i)
{
printf("Enter Name: ");
scanf(" %s", array_ptr[i].Name);
printf("Enter Age: ");
scanf("%d", &array_ptr[i].Age);
printf("\n");
}
for (i = 0; i < size; ++i)
printMe(&array_ptr[i]);
return 0;
}
void printMe(struct Name_Age *info)
{
printf("Name: %s\n", info->Name);
printf("Age: %d\n", info->Age);
}
Note that passing the struct by pointer to the function should be faster, note that you don't need the myInfo struct; you can just directly modify the elements of the array. Note the space before %s in the scanf() line, this is to discard any whitespace (including \n), this is done automatically for %d so it is only necessary for your strings (technically not the first iteration of the loop, but it doesn't fail if no whitespace is found). If you have any questions about why I made the changes I did, please feel free to comment on this answer!
example of fix
//struct Name_Age myInfo = *array_ptr;//Not necessary
printf("Enter size of array: ");
scanf("%d", &size);//remove `\n`, add `&`
//To ensure after the size has been determined
struct Name_Age * array_ptr = (struct Name_Age*)malloc(size * sizeof(struct Name_Age));//Cast is not necessary in C
for (i = 0; i < size; ++i)
{
printf("Enter Name: \n");
scanf("%s", array_ptr[i].Name);//remove `\n`
printf("Enter Age: \n");
scanf("%d", &array_ptr[i].Age);//need `&`
}
for (i = 0; i < size; ++i)
printMe(array_ptr[i]);

conflicting types for allocArray

guys I'm trying to compile my program in c but I'm getting this error (conflicting types for allocArray)?
Here is my code:
#include <stdio.h>
#include <stdlib.h>
int number(int);
char *allocArray(int);
int main ()
{
printf("Enter a number: ");
int userNumber;
scanf("%d", &userNumber);
int m= number(userNumber);
printf("\nThe number is %d", m);
printf("\n");
printf("*****************************************************\n");
printf("The array is %s", alloArray(5));
}
int number(int n)
{
int num = n;
return num;
}
char *alloArray(int num)
{
char *addr;
addr = (char *) malloc(num);
//addr = char[num];
return addr;
}
You've misspelt allocArray as alloArray (twice, in fact).

Resources