Question

In: Computer Science

Write a program in C language 1- Define a struct for students with the aforementioned attributes,...

Write a program in C language

1- Define a struct for students with the aforementioned attributes, test it by populating one
initialized struct variable with arbitrary input and take screenshots of the
output.

2- For each student, struct add an array of
number grades for a class the students are enrolled in such as S E 185. Then
write functions which find the max, average, and minimum score for a specified
assignment identified by a number, for example, Assignment 0 will be found at
index 0 of each student.
Create a new struct called university with the following attributes: university
name, an array of struct students, built year, and location. Create some random
students and assign those students to an arbitrary university. Create three
different universities with different students

3- Create a struct pointer variable for a student. You can initialize a struct pointer
variable in a similar way to a primitive variable type pointer initialization. We are
going to do some simple pointer to struct accesses. This part can be
counterintuitive and confusing so make sure you take your time on this part. The
difference between accessing structs and pointer structs is the notation used to
access the inherent attributes of the struct. To access an attribute of a pointer
struct, we use “->” and we do it as follows: Suppose we have a pointer struct
called menu that has attributes food and drink. We can access an attribute like
this: menu -> drink or menu -> food. Your task for this problem of the lab is to
initialize some pointer structs for students and populate them using pointer
notation.

Solutions

Expert Solution

We use structures to store data of different types. For example, you are a student. Your name is a string and your phone number and roll_no are integers. So, here name, address and phone number are those different types of data. Here, structure comes in picture.

Defining a Structure

The syntax for structure is:

struct structure_name
{
  data-type member-1;
  data-type member-2;
  data-type member-3;
  data-type member-4;
};

In our case, let's name the structure as 'student'. The members of the structure in our case are name, roll_no and phone_number.

So, our structure will look like:

struct student
{
  int roll_no;
  char name[30];
  int phone_number;
};

Just as we declare variables of type int, char etc, we can declare variables of structure as well.

Suppose, we want to store the roll no., name and phone number of three students. For this, we will define a structure of name 'student' (as declared above) and then declare three variables, say 'p1', 'p2' and 'p3' (which will represent the three students respectively) of the structure 'student'.

struct student
{
  int roll_no;
  char name[30];
  int phone_number;
};
main()
{
  struct student p1, p2, p3;
}

Here, p1, p2 and p3 are the variables of the structure 'student'.

We can also declare structure variables at the time of defining structure as follows.

struct student
{
  int roll_no;
  char name[30];
  int phone_number;
}p1, p2, p3;

Now, let's see how to enter the details of each student i.e. roll_no, name and phone number.

Suppose, we want to assign a roll number to the first student. For that, we need to access the roll number of the first student. We do this by writing

p1.roll_no = 1;

This means that use dot (.) to use variables in a structure. p1.roll_no can be understood as roll_no of p1.

If we want to assign any string value to a variable, we will use strcpy as follows.

strcpy(p1.name, "Brown");

Now let's store the details of all the three students.

#include <stdio.h>
#include <string.h>
int main()
{
  struct student
  {
    int roll_no;
    char name[30];
    int phone_number;
  };
  struct student p1 = {1,"Brown",123443};
  struct student p2, p3;
  p2.roll_no = 2;
  strcpy(p2.name,"Sam");
  p2.phone_number = 1234567822;
  p3.roll_no = 3;
  strcpy(p3.name,"Addy");
  p3.phone_number = 1234567844;
  printf("First Student\n");
  printf("roll_no : %d\n", p1.roll_no);
  printf("name : %s\n", p1.name);
  printf("phone_number : %d\n", p1.phone_number);
  printf("Second Student\n");
  printf("roll_no : %d\n", p2.roll_no);
  printf("name : %s\n", p2.name);
  printf("phone_number : %d\n", p2.phone_number);
  printf("Third Student\n");
  printf("roll_no : %d\n", p3.roll_no);
  printf("name : %s\n", p3.name);
  printf("phone_number : %d\n", p3.phone_number);
  return 0;
}

Store Information in Structure and Display it

#include <stdio.h>
struct student {
    char firstName[50];
    int roll;
    float marks;
} s[10];

int main() {
    int i;
    printf("Enter information of students:\n");

    // storing information
    for (i = 0; i < 5; ++i) {
        s[i].roll = i + 1;
        printf("\nFor roll number%d,\n", s[i].roll);
        printf("Enter first name: ");
        scanf("%s", s[i].firstName);
        printf("Enter marks: ");
        scanf("%f", &s[i].marks);
    }
    printf("Displaying Information:\n\n");

    // displaying information
    for (i = 0; i < 5; ++i) {
        printf("\nRoll number: %d\n", i + 1);
        printf("First name: ");
        puts(s[i].firstName);
        printf("Marks: %.1f", s[i].marks);
        printf("\n");
    }
    return 0;
}

Output

Enter information of students: 

For roll number1,
Enter name: Tom
Enter marks: 98

For roll number2,
Enter name: Jerry
Enter marks: 89
.
.
.
Displaying Information:

Roll number: 1
Name: Tom
Marks: 98
.
.
.

In this program, a structure student is created. The structure has three members: name (string), roll (integer) and marks (float).

Then, we created an array of structures s having 5 elements to store information of 5 students.

Using a for loop, the program takes the information of 5 students from the user and stores it in the array of structure. Then using another for loop, the information entered by the user is displayed on the screen.

Code examples on this page can be copied over from my public/cs31/C_examples directory:

   # if you don't have a cs31 subdirectory, create one first:
   mkdir cs31
   # copy over my C example files into your cs31 subdirectory:
   cd cs31
   cp -r /home/newhall/public/cs31/C_examples  .
   # cd into your copy, run make to compile
   cd C_examples
   make
   ls

Structs

C is not an object-oriented language, and thus does not have support for classes. It does, however, have support for defining structured types (like the data part of classes).

A struct is a type used to represent a heterogeneous collection of data; it is a mechanism for treating a set of different types as a single, coherent unit. For example, a student may have a name, age, gpa, and graduation year. A struct type can be defined to store these four different types of data associated with a student.

In general, there are three steps to using structured types in C programs:

  1. Define a new struct type representing the structure.
  2. Declare variables of the struct type
  3. Use DOT notation to access individual field values

Defining a struct type

struct type definitions should appear near the top of a program file, outside of any function definition. There are several different ways to define a struct type but we will use the following:

struct <struct name> {
  <field 1 type> <field 1 name>;
  <field 2 type> <field 2 name>;
  <field 3 type> <field 3 name>;
  ...
};

Here is an example of defining a new type 'struct studentT' for storing student data:

struct studentT {
   char name[64];
   int  age;
   int  grad_yr;
   float gpa;
};

// with structs, we often use typedef to define a shorter type name
// for the struct; typedef defines an alias for a defined type
// ('studentT' is an alias for 'struct studentT')
typedef struct studentT studentT; 

Declaring variables of struct types

Once the type has been defined, you can declare variables of the structured type:

struct studentT  student1;   // student1 is a struct studentT
studentT  student2;          // student2 is also a struct studentT
                             // (we are just using the typedef alias name)

studentT cs31[50];           // an array of studentT structs: each bucket
                             // stores a studentT struct

Accessing field values

To access field values in a struct, use dot notation:

<variable name>.<field name>

It is important to think very carefully about type when you use structs to ensure you are accessing field values correctly based on their type. Here are some examples:

student1.grad_yr = 2017;
student1.age = 18 + 2;
strcpy(student1.name, "Joseph Schmoe");
student2.grad_yr = student1.grad_yr;
cs31[0].age = student1.age;
cs31[5].gpa = 3.56;

structs are lvalues, meaning that you can use them on the left-hand-side of an assignment statement, and thus, can assign field values like this:

student2 = student1;  // student2 field values initialized to the value of
                      // student1's corresponding field values
cs31[i] = student2;

Question: For each expression below, what is its type? Are any invalid? (here are the answers)

   (1) student1
   (2) student1.grad_yr
   (3) student1.name
   (4) student1.name[2]
   (5) cs31
   (6) cs31[4]
   (7) cs31[4].name
   (8) cs31[4].name[5]

Passing structs to functions

When structs are passed to functions, they are passed BY VALUE. That means that the function will receive a COPY OF the struct, and that copy is what is manipulated from within the function. All field values in the copy will have the exact same values as the field values of the original struct - but the original struct and the copy occupy different locations in memory. As such, changing a field value within the function will NOT change the corresponding field value in the original struct that was passed in.

If one of the fields in a struct is a statically declared array (like the name field in the studentT struct), the parameter gets a copy of the entire array (every bucket value). This is because the complete statically declared array resides within the struct, and the entire struct is copied over as a unit. You can think of the struct as a chunk of memory (0's and 1's) that is copied over to the parameter without anything being added to it or taken out. So, a function passed student1 CANNOT change any of the contents of the student1 variable (because the function is working with a COPY of student1, and thus the student.name array in the copy starts at a different memory location than the student.name array of the original struct). This may seem odd given how arrays are passed to functions (an array parameter does not get a copy of every array bucket of its argument, instead it REFERS to the same array as the argument array). This seemingly different behavior is actually consistent with the rule that a parameter gets THE VALUE of its argument. It is just that the value of an array argument (the base address of the array) is different than the value of an int, float, struct, ..., argument. For example, here are some expressions and their values:

 
Argument Expression      Expression's Value (Parameter gets this value)
--------------------     --------------------------------------------
student1                 {"Joseph Schmoe", 20, 2017, 3.56}
student1.gpa             3.56
cs31                     base address of the cs31 array     
student1.name            base address of the name field array
student1.name[2]         's'

Only when the value passed to a function is an address of a memory location can the function modify the contents of the memory location at that address: a function passed student1 (a struct value) CANNOT change any of the contents of the student1 variable; but a function passed student1.name (the base address of an array) CAN change the contents of the buckets of the name field - because when student1.name is passed in, what is being passed in is the memory location of the array, NOT a copy of the entire array.

Example: Here is an example function call with a stack drawing showing how different types are passed.

lvalues

An lvalue is an expression that can appear on the left hand side of an assignment statement. In C, single variables or array elements are lvalues. The following example illustrates valid and invalid C assignment statements based on lvalue status:

struct studentT  student1;   
studentT  student2;          
int x;
char arr[10], ch;

x = 10;                         // valid C: x is an lvalue
ch = 'm';                       // valid C: ch is an lvalue
student1 = student2;            // valid C: student1 is an lvalue
arr[3] = ch;                    // valid C: arr[3] is an lvalue
x + 1 = 8;                      // invalid C: x+1 is not an lvalue
arr = "hello there";            // invalid C: arr is not an lvalue
arr = student1.name;            // invalid C: arr is not an lvalue
student1.name = student2.name;  // invalid C: name (an array of char) is not an lvalue

See struct.c for more examples.
Exercise: implement and test two functions in this file: printStudent and initStudent.

C pointer variables

A pointer variable stores the address of a memory location that stores a value of the type to which it points ("a level of indirection"). Here is a picture of a pointer variable ptr pointing to a memory storage location that stores value an int value 12:

         -----           -----
     ptr | *-|--------->| 12 |
         -----           -----

Through a pointer variable (ptr) the value stored in the location it points to (12) can be indirectly be accessed.

Pointer variables are used most often in C programs for:

  1. "pass-by-reference" function parameters: to write functions that can modify an argument's value.
  2. Dynamic Memory Allocation (for arrays in particular): to write programs that allocate space (or re-allocate space) as the program runs. This is useful when sizes of data structures like arrays are not known at compile time, and to support growing the size of data structures as the program runs.

Rules for using pointer variables

The rules for using pointer variable are similar to regular variables, you just need to think about two types: (1) the type of the pointer variable; and (2) the type stored in the memory address to which it points.

  1. First, declare a pointer variable using type_name *var_name:
    int *ptr;   // stores the memory address of an int (ptr "points to" an int)
    char *cptr; // stores the memory address of a char (cptr "points to" a char) 
    
    Think about Type
    ptr and cptr are both pointers but their specific type is different:
    • ptr's type is "pointer to int". It can point to a memory location that stores an int value.
    • cptr's type is "pointer to char" It can point to a memory location that stores an char value, and through cptr we can indirectly access that char value.
  2. Next, initialize the pointer variable (make it point to something). Pointer variables store addresses. Initialize a pointer to the address of a storage location of the type to which it points. One way to do this is to use the ampersand operator on regular variable to get its address value:
    int x;
    char ch;
    ptr = &x;    // ptr get the address of x, pointer "points to" x
                  ------------          ------
              ptr | addr of x|--------->| ?? |  x
                  ------------          ------
    cptr = &ch;  // ptr get the address of ch, pointer "points to" ch 
    cptr = &x;  // ERROR!  cptr can hold a char address only (it's NOT a pointer to an int)
                    
    
    All pointer variable can be set to a special value NULL. NULL is not a valid address but it is useful for testing a pointer variable to see if it points to a valid memory address before we access what it points to:
    ptr = NULL;             ------                    ------ 
    cptr = NULL;       ptr | NULL |-----|       cptr | NULL |----|
                            ------                    ------ 
    
  3. Use the pointer variable:
    • make it point to a location (and you can change which location it points to)
    • Use *var_name to dereference the pointer to access the value in the location that it points to.
    Some examples:
    int *ptr1, *ptr2, x, y;
    x = 8;
    ptr1 = NULL;
    ptr2 = &x;           ------------           ------
                    ptr2 | addr of x|--------->|  8  |  x
                         ------------           ------
    *ptr2 = 10;    // dereference ptr2: "what ptr2 points to gets 10"
                         ------------           ----- 
                    ptr2 | addr of x|--------->| 10  |  x
                         ------------           ----- 
    
    y = *ptr2 + 3;  // dereference ptr2: "y gets what ptr2 points to plus 3"
                       ----- 
                       ----- 
    
    ptr1 = ptr2;   // ptr1 gets address value stored in ptr2
                         ------------            ----- 
                    ptr2 | addr of x |--------->| 10  |  x
                         ------------            ----- 
                                                  /\ 
                         ------------              | 
                    ptr1 | addr of x |--------------
                         ------------             
    
    // TODO: finish tracing through this code and  show what is printed
    *ptr1 = 100;
    ptr1 = &y;
    *ptr1 = 80;
    printf("x = %d y = %d\n", x, y);
    printf("x = %d y = %d\n", *ptr2, *ptr1);
    

Be careful about type when using pointer variables (drawing pictures helps):

ptr = 20;       // ERROR?  this assigns ptr to point to address 20
*ptr = 20;      // this assigns 20 the value pointed to by ptr

What happens if you dereference an pointer variable that does not contain a valid address:

ptr = NULL;
*ptr = 6;    // CRASH!  your program crashes with a segfault (a memory fault)

ptr = 20;
*ptr = 6;    // CRASH!  segfault (20 is not a valid address)

This is one reason to initialize pointer variables to NULL: you can test for NULL and not dereference in your program:

if(ptr != NULL) {
  *ptr = 6;
}


Pointers and Functions "pass by reference"

Pointers allow a way to write functions that can modify their arguments' values: the C way of implementing Pass by Reference. We have actually already seen this with array parameters: the function parameter gets the value of the base address of the array (it points to the same array as its argument) and thus the function can modify the values stored in the array buckets. We can use this same idea in general to write a function that can modify its argument's value. The steps are:

  1. declare the function parameter to be a pointer to the variable type
       int change_value(int *input>) {
    
  2. pass in the address of the argument
        int x;
        change_value(&x);
    
  3. in the function, dereference the parameter to change the argument's value
        *input = 100;  // what input points to (x's location) gets 100
    

Try out:

  1. Look at a program that does C style pass by reference:
    vim passbyreference.c
    
    Try running it and see if you understand what is happening and why.

    Draw the call stack for the first call to this function:

    • where are variables a and b located on the stack?
    • where are the parameter values located?
    • what values does each parameter get?
    • and what does this mean with respect to the value of each argument after the call?
  2. Implement a program with a swap function that swaps the values stored in its two arguments. Make some calls to it in main to test it out.

Here are the answers

(note: technically, everything in C is passed by value; C-style pass-by-reference is just passing the value of an address (a pointer) to a function as opposed to passing the value of an int or float or ...)

Dynamic Memory Allocation

A common uses of pointer variables is to use them to point to memory that your program allocates at runtime. This is very useful for writing programs where the size of an array or other data structure is not know until runtime, or that may grow or shrink over the lifetime of a run of a program.

malloc and free

malloc and free are functions for allocating and deallocating memory in the Heap. The Heap is a portion of program memory that is separate from the stack. No variables are allocated in the heap, but chunks of anonymous memory can be allocated and its address can be assigned to a global or local pointer variable.

Heap memory must be explicitly allocated and deallocated by your program.

  • To allocate Heap memory, call malloc passing in the total number of bytes of contiguous heap memory you want to allocate. malloc returns the base address of this heap memory to the caller or NULL on error.
    int *p;
    p = (int *)malloc(4);  // allocate 4 bytes of heap memory and assign addr to p
    *p = 6;   // the heap memory p points to gets the value 6
    
    malloc's return type is a bit odd. It is a void * which means it is a pointer to a non-specific type (or to any type). Because of this, we re-cast the return type to be a pointer to the specific type we are using (int *) in the example above.
  • Sometimes malloc fails, so you should always test its return value for NULL before dereferencing the pointer value:
    p = (int *)malloc(4);
    if(p == NULL) {
       printf("Bad malloc error\n");
       exit(1);   // or return from this function or ...
    }
    *p = 6;
    
  • Instead of passing the exact number of bytes to malloc, use the sizeof function in an expression instead (sizeof([type name])):
    p = (int *)malloc(sizeof(int));
    
  • malloc is often used to allocate an array of some type on the heap, by specifying the total number of bytes in the array using an expression of (size of the type of each bucket and the number of buckets:
    int *arr;
    char *c_arr;
    
    // allocate an array of 20 ints on the heap:
    arr = (int *)malloc(sizeof(int)*20);
    
    // allocate an array of 10 chars on the heap:
    c_arr = (char *)malloc(sizeof(char)*10);
    
  • Because the pointer variable stores the base address of the array allocated in the heap, you can use array syntax to access its buckets:
    arr[0] = 8;  // these two statements are identical: both put 8 in bucket 0
    *arr = 8;
    arr[3] = 10;  // puts 10 in bucket 3 of the array pointed to by arr  
    
    Here is a picture of what this looks like in memory. Note that the Stack and the Heap are separate parts of memory.
  • When you are done using the memory you allocated with malloc, you need to explicitly deallocate it by calling the free function (it is also good to set the pointer's value to NULL after calling free:
    free(p);
    free(arr);
    free(c_arr);
    p = NULL;
    arr = NULL;
    c_arr = NULL;
    

See my Strings in C page for some examples of dynamically allocated strings and the string library (when dynamically allocating space for strings it is important to allocate enough space to store all chars in the string including the terminating null char)

Pointers, the Heap, and Functions

Passing a pointer value to a function has the same semantics as passing the address of a variable to a function: the function can modify the value pointed to.

As you write functions that take pointer values as parameters, it if very important to think about the type of argument you are passing. This will help you figure out the syntax for how to pass the argument value and the correct matching function parameter type.

Here is an example of passing a malloc'ed array to a function:

int main() {
  int *arr1;
  arr1 = malloc(sizeof(int)*10);
  if(!arr1) {
     printf("malloc error\n");
     exit(1);  
  }
  init_array(arr1, 10);
  ...
}
void init_array(int *arr, int size) {
  int i;
  for(i=0; i< size; i++) {
     arr[i] = i; 
  }
}

Here is a picture of what this looks like in memory. This should look very familiar to passing statically declared arrays, just notice the difference in which part of memory the array is located.

Try out:


Related Solutions

write a Program in C++ Using a structure (struct) for a timeType, create a program to...
write a Program in C++ Using a structure (struct) for a timeType, create a program to read in 2 times into structures, and call the method addTime, in the format: t3 = addTime(t1, t2); Make sure to use add the code to reset and carry, when adding 2 times. Also, display the resultant time using a function: display(t3);
Using C++ language, create a program that uses a struct with array variables that will loop...
Using C++ language, create a program that uses a struct with array variables that will loop at least 3 times and get the below information: First Name Last Name Job Title Employee Number Hours Worked Hourly Wage Number of Deductions Claimed Then, determine if the person is entitled to overtime and gross pay. Afterwards, determine the tax and net pay. Output everything to the screen. Use functions wherever possible. Bonus Points: Use an input file to read in an unknown...
C# language Question: You need to write a program for students who receive bursaries in the...
C# language Question: You need to write a program for students who receive bursaries in the department, managing the free hours they have to do. For each recipient you store the recipient’s name and the number of hours outstanding. All recipients start with 90 hours. Implement class Recipients which has the private attributes Name and Hours. In addition to the constructor, the class has the following methods: public String getName() // Returns the name of the recipient public int getHours()...
Create a C++ program that follows the specifications below: *Define a struct with 4 or more...
Create a C++ program that follows the specifications below: *Define a struct with 4 or more members. *Application must have at least one user-defined function *Declare an array of your struct using a size of 10 or more *Load the date for each element in your array from a text file *Display the data in your array in the terminal *provide brief comments for each line of code
Using C Language Write a program segment that computes 1 + 2 + 3 + ......
Using C Language Write a program segment that computes 1 + 2 + 3 + ... + ( n - 1) + n , where n is a data value. Follow the loop body with an if statement that compares this value to (n * (n + 1)) / 2 and displays a message that indicates whether the values are the same or different. Please give me code to just copy and paste
Lab 1 Write a program in the C/C++ programming language to input and add two fractions...
Lab 1 Write a program in the C/C++ programming language to input and add two fractions each represented as a numerator and denominator. Do not use classes or structures. Print your result (which is also represented as a numerator/denominator) to standard out. If you get done early, try to simplify your result with the least common denominator. The following equation can be used to add fractions: a/b + c/d = (a*d + b*c)/(b*d) Example: 1/2 + 1/4 = ( 1(4)...
Write the following in C language for Arduino: Write a program that turns on the LED...
Write the following in C language for Arduino: Write a program that turns on the LED at 25%, 50%, 75%, 100%, and then 0% brightness with a one second delay in between each change. Remember you are going to need to use a PWM pin and use the "analogWrite" command. The maximum value for our Arduino R3 boards is 255 and you need five steps (25%, 50%, 75%, 100%, and 0%) so you will need to determine the values for...
Write a C Program that uses file handling operations of C language. The Program should perform...
Write a C Program that uses file handling operations of C language. The Program should perform following operations: 1. The program should accept student names and students’ assignment marks from the user. 2. Values accepted from the user should get saved in a .csv file (.csv files are “comma separated value” files, that can be opened with spreadsheet applications like MS-Excel and also with a normal text editor like Notepad). You should be able to open and view this file...
C# Programming Language Write a C# program ( Console or GUI ) that prompts the user...
C# Programming Language Write a C# program ( Console or GUI ) that prompts the user to enter the three examinations ( test 1, test 2, and test 3), homework, and final project grades then calculate and display the overall grade along with a message, using the selection structure (if/else). The message is based on the following criteria: “Excellent” if the overall grade is 90 or more. “Good” if the overall grade is between 80 and 90 ( not including...
C LANGUAGE ONLY Write a C program to count the frequency of each element in an...
C LANGUAGE ONLY Write a C program to count the frequency of each element in an array. Enter the number of elements to be stored in the array: 3 Input 3 elements of the array: element [0]: 25 element [1]: 12 element [2]: 43 Expected output: The frequency of all elements of an array: 25 occurs 1 times 12 occurs 1 times 3 occurs 1 times
ADVERTISEMENT
ADVERTISEMENT
ADVERTISEMENT