1. Write various data types supported in C with examples.
Introduction: In C programming, data types specify the type of data that a variable can hold. They are essential for defining variables and managing memory efficiently.
Types of Data Types in C: C supports the following primary data types:
-
Basic Data Types:
- int: Used for integers (whole numbers).
Example:int age = 25;
- float: Used for single-precision floating-point numbers.
Example:float height = 5.8;
- double: Used for double-precision floating-point numbers.
Example:double pi = 3.14159;
- char: Used for characters.
Example:char grade = 'A';
- int: Used for integers (whole numbers).
-
Derived Data Types:
- Array: A collection of elements of the same type.
Example:int marks[5] = {90, 85, 78, 92, 88};
- Pointer: Stores the address of another variable.
Example:int *p; p = &age;
- Structure: A user-defined data type to group related variables.
Example:struct Student { int id; char name[50]; float marks; };
- Array: A collection of elements of the same type.
-
Enumeration (enum): Represents named integer constants.
Example:enum Days {Monday, Tuesday, Wednesday}; Days today = Monday;
-
Void Data Type: Represents no value or a return type for functions.
Example:void displayMessage() { printf("Hello, World!"); }
Modifiers: Data types can have modifiers to adjust their size or range:
- short, long, signed, unsigned.
Example:unsigned int x = 100;
Conclusion: Choosing the correct data type ensures memory efficiency and prevents errors. C offers a wide range of data types to accommodate various programming needs.
2. What are header files? Why are they important?
Definition:
Header files in C are files that contain function declarations, macros, and definitions that can be shared across multiple program files. They typically have a .h
extension.
Examples of Header Files:
-
Standard Header Files:
#include <stdio.h>
: Provides input/output functions likeprintf
andscanf
.#include <math.h>
: Contains mathematical functions likesqrt
andpow
.#include <string.h>
: Includes string manipulation functions likestrcpy
andstrlen
.
-
User-Defined Header Files:
- Custom header files created by the programmer using
#include "filename.h"
.
- Custom header files created by the programmer using
Importance of Header Files:
- Code Reusability: Allows commonly used functions to be reused without redefining them.
- Modularity: Helps in organizing code by separating declarations and definitions.
- Ease of Maintenance: Changes in the header file automatically reflect across all files that include it.
- Standardization: Provides a standard interface for functions and macros.
Example:
#include <stdio.h>
int main() {
printf("Header files are important!\n");
return 0;
}
Conclusion: Header files simplify programming by providing predefined functions, enhancing code readability and modularity.
3. Write limitations of the switch case.
Introduction:
The switch
statement in C allows multi-way branching. It is used to execute one block of code out of many based on the value of an expression.
Limitations of the Switch Case:
-
No Ranges Allowed:
switch
cannot handle ranges (e.g.,case 1 to 5
).- Example:
// This is not valid case 1 ... 5: printf("Range not supported");
-
Only Integral or Enumerated Data Types:
- Only
int
,char
, andenum
types are allowed. Floating-point and strings are not supported. - Example:
case 3.5:
orcase "hello":
is invalid.
- Only
-
No Conditional Cases:
- It cannot handle conditional expressions like
case (x > 5):
. - Example: You cannot check
case (a > b)
in a switch.
- It cannot handle conditional expressions like
-
Duplication of Cases:
- Duplicate
case
values cause a compilation error. - Example:
switch(x) { case 1: printf("Duplicate!"); case 1: printf("Error!"); }
- Duplicate
-
No Default Handling for Missing Cases:
- Without a
default
, unhandled cases result in no action.
- Without a
-
Nested Switches Can Be Confusing:
- Complex nested
switch
cases reduce readability and are prone to errors.
- Complex nested
Conclusion:
The switch
statement is a powerful construct but has limitations that make it unsuitable for complex logic.
Here are detailed answers to the remaining questions:
4. Differentiate between scope and lifetime of a variable.
Introduction: Variables in C have attributes such as scope and lifetime, which define their accessibility and duration in memory.
Scope of a Variable: The scope of a variable refers to the portion of the program where the variable can be accessed.
- Types of Scope:
-
Local Scope: Variables declared inside a function or block are accessible only within that block.
Example:void example() { int x = 10; // Local scope printf("%d", x); }
-
Global Scope: Variables declared outside all functions are accessible throughout the program.
Example:int globalVar = 50; // Global scope void example() { printf("%d", globalVar); }
-
Block Scope: Variables declared inside loops or conditional blocks are accessible only within those blocks.
Example:if (1) { int blockVar = 20; // Block scope printf("%d", blockVar); }
-
Lifetime of a Variable: The lifetime of a variable refers to the duration for which the variable exists in memory.
- Types of Lifetime:
-
Automatic (Local) Lifetime:
Variables declared within functions exist during the function's execution.
Example:void example() { int x = 10; // Exists during function execution }
-
Static Lifetime:
Variables declared with thestatic
keyword retain their value even after the function ends.
Example:void example() { static int counter = 0; counter++; printf("%d", counter); }
-
Dynamic Lifetime:
Variables allocated using dynamic memory allocation (malloc
,calloc
, etc.) exist until explicitly freed.
Example:int *ptr = (int *)malloc(sizeof(int)); free(ptr);
-
Key Differences:
Aspect | Scope | Lifetime |
---|---|---|
Definition | Portion of the program where a variable can be accessed. | Duration for which the variable exists in memory. |
Types | Local, Global, Block. | Automatic, Static, Dynamic. |
Keyword Impact | extern affects scope. |
static affects lifetime. |
Example | Global variables have program-wide scope. | Static variables persist across function calls. |
Conclusion: Understanding the scope and lifetime of variables is crucial for efficient memory management and error-free programming.
5. Define preprocessor and its usage in programming.
Introduction:
The C preprocessor is a tool that processes code before it is passed to the compiler. Preprocessor commands begin with a #
symbol and are executed before the actual compilation starts.
Definition: A preprocessor is a directive that instructs the compiler to perform specific tasks like file inclusion, macro substitution, and conditional compilation before compiling the source code.
Types of Preprocessor Directives:
-
File Inclusion: Includes header files in the program.
Syntax:#include <filename>
Example:#include <stdio.h>
-
Macro Substitution: Replaces a symbolic name with a value or code fragment.
Syntax:#define name value
Example:#define PI 3.14159 printf("%f", PI);
-
Conditional Compilation: Compiles certain parts of the code based on conditions.
Syntax:#ifdef MACRO // Code #endif
Example:
#define DEBUG #ifdef DEBUG printf("Debugging enabled"); #endif
-
Other Directives:
#undef
: Undefines a macro.#pragma
: Issues special commands to the compiler (e.g., disabling warnings).
Usage of Preprocessor:
-
Code Modularity:
#include
helps organize code into reusable files.
-
Simplify Code:
- Macros reduce repetitive code and simplify complex expressions.
-
Improved Readability:
- Conditional compilation allows debugging and testing specific parts of the program.
-
Portability:
- Preprocessors handle platform-specific configurations, making code portable.
Example Code:
#include <stdio.h>
#define SQUARE(x) (x * x) // Macro
int main() {
int num = 5;
printf("Square of %d is %d", num, SQUARE(num));
return 0;
}
Conclusion: The preprocessor plays a vital role in improving code maintainability, readability, and efficiency. Proper use of preprocessor directives ensures robust and flexible programs.
6. Write short notes on the following:
(i) Enumerated Data Type
Definition: An enumerated data type (enum) is a user-defined data type in C that consists of a set of named integer constants. It enhances code readability by allowing meaningful names to be assigned to values.
Syntax:
enum Days {Monday, Tuesday, Wednesday, Thursday, Friday, Saturday, Sunday};
Here, Monday
has a value of 0, Tuesday
has 1, and so on.
Example:
enum Days today;
today = Wednesday;
printf("Today is day number: %d", today); // Output: 2
Advantages:
- Improves code readability.
- Prevents the use of invalid values.
- Makes debugging easier.
(ii) String
Definition:
A string in C is an array of characters terminated by a null character (\0
). Strings are widely used to store and manipulate text data.
Example:
char name[10] = "Alice";
printf("Name: %s", name);
String Functions (from <string.h>
):
strlen
: Finds the length of a string.strcpy
: Copies one string to another.strcmp
: Compares two strings.strcat
: Concatenates two strings.
Advantages:
- Simplifies text manipulation.
- Allows easy storage and retrieval of text data.
(iii) Macro Expansion
Definition: A macro in C is a preprocessor directive that defines a constant or expression that can be replaced throughout the code during preprocessing.
Syntax:
#define MACRO_NAME value_or_expression
Example:
#define PI 3.14159
printf("Value of PI: %f", PI);
Advantages:
- Reduces code redundancy.
- Enhances readability.
- Improves performance as it avoids function calls.
(iv) File Inclusion
Definition:
File inclusion allows a program to include the content of one file into another. It is achieved using the #include
directive.
Types of File Inclusion:
-
Standard Library Files:
Included using angle brackets (<>
).
Example:#include <stdio.h>
-
User-Defined Files:
Included using double quotes (""
).
Example:#include "myheader.h"
Benefits:
- Encourages code modularity.
- Reduces redundancy.
- Simplifies maintenance.
7. Write a program in C to print the following pattern:
2 3 4 5 6 7
3 4 5 6 7
4 5 6 7
5 6 7
6 7
7
Code:
#include <stdio.h>
int main() {
int i, j;
for (i = 2; i <= 7; i++) {
for (j = i; j <= 7; j++) {
printf("%d ", j);
}
printf("\n");
}
return 0;
}
Output: This program uses nested loops. The outer loop controls the starting number, and the inner loop prints numbers from the current starting number to 7.
8. What are different file opening modes? Write a program in C.
File Opening Modes in C:
- "r": Opens a file for reading.
- "w": Opens a file for writing (creates a new file or truncates an existing one).
- "a": Opens a file for appending data.
- "r+": Opens a file for both reading and writing.
- "w+": Opens a file for both writing and reading (truncates existing file).
- "a+": Opens a file for both appending and reading.
Program: Read numbers from a file (INPUT) and write odd and even numbers to separate files (ODD, EVEN).
Code:
#include <stdio.h>
int main() {
FILE *inputFile, *oddFile, *evenFile;
int num;
// Open files
inputFile = fopen("INPUT.txt", "r");
oddFile = fopen("ODD.txt", "w");
evenFile = fopen("EVEN.txt", "w");
if (inputFile == NULL) {
printf("Error opening INPUT file.\n");
return 1;
}
// Read numbers and classify them
while (fscanf(inputFile, "%d", &num) != EOF) {
if (num % 2 == 0) {
fprintf(evenFile, "%d\n", num); // Write even numbers to EVEN
} else {
fprintf(oddFile, "%d\n", num); // Write odd numbers to ODD
}
}
// Close all files
fclose(inputFile);
fclose(oddFile);
fclose(evenFile);
printf("Odd and even numbers written to ODD.txt and EVEN.txt\n");
return 0;
}
Explanation:
- The program opens
INPUT.txt
for reading and two other files,ODD.txt
andEVEN.txt
, for writing. - It reads numbers from
INPUT.txt
usingfscanf
. - Based on the parity (odd/even), the number is written to the respective file using
fprintf
. - All files are closed at the end.
9(a). Write a program to calculate the sum of the following series up to the first 100 terms:
The series is .
Explanation:
- The formula for the sum of cubes of the first natural numbers is:
- We can calculate the sum iteratively or directly using the formula. Here, we will compute it iteratively to better understand loops.
C Code Implementation:
#include <stdio.h>
int main() {
int i;
long long sum = 0;
// Calculate the sum of cubes of the first 100 terms
for (i = 1; i <= 100; i++) {
sum += i * i * i;
}
printf("The sum of the series (1^3 + 2^3 + ... + 100^3) is: %lld\n", sum);
return 0;
}
Output: The program will output the sum of cubes for the first 100 terms.
9(b). Given an array of 20 integers, write a program in C to search for a given integer in that array.
Explanation:
- Searching involves checking each element in the array until the desired number is found.
- We can implement this using Linear Search, which has a time complexity of .
C Code Implementation:
#include <stdio.h>
int main() {
int arr[20], i, key, found = 0;
// Input 20 integers into the array
printf("Enter 20 integers:\n");
for (i = 0; i < 20; i++) {
scanf("%d", &arr[i]);
}
// Input the number to search
printf("Enter the number to search: ");
scanf("%d", &key);
// Search for the key in the array
for (i = 0; i < 20; i++) {
if (arr[i] == key) {
found = 1;
printf("Number found at position %d (index %d)\n", i + 1, i);
break;
}
}
if (!found) {
printf("Number not found in the array.\n");
}
return 0;
}
Output:
- If the number exists, it will display the position.
- If not, it will display a "Number not found" message.
10(a). Write a program in C to multiply two matrices of dimension.
Explanation:
- Matrix multiplication involves calculating the dot product of rows and columns.
- For matrices, the time complexity is .
C Code Implementation:
#include <stdio.h>
#define N 3 // Dimension of the matrix
int main() {
int A[N][N], B[N][N], C[N][N];
int i, j, k;
// Input Matrix A
printf("Enter elements of Matrix A (%dx%d):\n", N, N);
for (i = 0; i < N; i++) {
for (j = 0; j < N; j++) {
scanf("%d", &A[i][j]);
}
}
// Input Matrix B
printf("Enter elements of Matrix B (%dx%d):\n", N, N);
for (i = 0; i < N; i++) {
for (j = 0; j < N; j++) {
scanf("%d", &B[i][j]);
}
}
// Initialize Matrix C to zero
for (i = 0; i < N; i++) {
for (j = 0; j < N; j++) {
C[i][j] = 0;
}
}
// Multiply A and B, store result in C
for (i = 0; i < N; i++) {
for (j = 0; j < N; j++) {
for (k = 0; k < N; k++) {
C[i][j] += A[i][k] * B[k][j];
}
}
}
// Display the result matrix
printf("Resultant Matrix (C = A x B):\n");
for (i = 0; i < N; i++) {
for (j = 0; j < N; j++) {
printf("%d ", C[i][j]);
}
printf("\n");
}
return 0;
}
Input Example: Matrix :
1 2 3
4 5 6
7 8 9
Matrix :
9 8 7
6 5 4
3 2 1
Output: Resultant Matrix :
30 24 18
84 69 54
138 114 90
10(b). Declare a structure which contains the following members and write a program in C to list all students who scored more than 75 marks. The structure contains:
- Roll No.
- Name
- Father's Name
- Age
- City
- Marks
Explanation:
- A structure is a user-defined data type in C used to group related variables under one name.
- The program will define a structure to hold student details and filter out students scoring more than 75 marks.
C Code Implementation:
#include <stdio.h>
#include <string.h>
// Define the structure
struct Student {
int rollNo;
char name[50];
char fatherName[50];
int age;
char city[50];
float marks;
};
int main() {
int n, i;
// Input number of students
printf("Enter the number of students: ");
scanf("%d", &n);
// Declare an array of structures
struct Student students[n];
// Input details for each student
for (i = 0; i < n; i++) {
printf("Enter details of student %d:\n", i + 1);
printf("Roll No: ");
scanf("%d", &students[i].rollNo);
printf("Name: ");
scanf(" %[^\n]", students[i].name); // To handle spaces in names
printf("Father's Name: ");
scanf(" %[^\n]", students[i].fatherName);
printf("Age: ");
scanf("%d", &students[i].age);
printf("City: ");
scanf(" %[^\n]", students[i].city);
printf("Marks: ");
scanf("%f", &students[i].marks);
}
// Display students with marks greater than 75
printf("\nStudents scoring more than 75 marks:\n");
for (i = 0; i < n; i++) {
if (students[i].marks > 75) {
printf("\nRoll No: %d\n", students[i].rollNo);
printf("Name: %s\n", students[i].name);
printf("Father's Name: %s\n", students[i].fatherName);
printf("Age: %d\n", students[i].age);
printf("City: %s\n", students[i].city);
printf("Marks: %.2f\n", students[i].marks);
}
}
return 0;
}
Input Example:
Enter the number of students: 2
Enter details of student 1:
Roll No: 101
Name: John
Father's Name: Michael
Age: 20
City: New York
Marks: 80
Enter details of student 2:
Roll No: 102
Name: Alice
Father's Name: Robert
Age: 21
City: Los Angeles
Marks: 70
Output:
Students scoring more than 75 marks:
Roll No: 101
Name: John
Father's Name: Michael
Age: 20
City: New York
Marks: 80.00
11(a). Explain dynamic memory concept with proper example.
Explanation:
- Dynamic memory allocation refers to allocating memory at runtime using functions like
malloc
,calloc
,realloc
, andfree
from the<stdlib.h>
library. - Advantages:
- Allows flexibility in memory usage.
- Reduces wastage of memory by allocating exactly the required amount.
Functions:
malloc(size_t size)
: Allocates memory of specified size in bytes and returns a pointer.calloc(n, size)
: Allocates memory for an array ofn
elements and initializes all to zero.realloc(ptr, size)
: Resizes the memory block pointed to byptr
.free(ptr)
: Frees the allocated memory.
Example Program:
#include <stdio.h>
#include <stdlib.h>
int main() {
int n, i;
int *arr;
// Input the number of elements
printf("Enter the number of elements: ");
scanf("%d", &n);
// Dynamically allocate memory for the array
arr = (int *)malloc(n * sizeof(int));
if (arr == NULL) {
printf("Memory allocation failed!\n");
return 1;
}
// Input elements into the array
printf("Enter %d integers:\n", n);
for (i = 0; i < n; i++) {
scanf("%d", &arr[i]);
}
// Display the elements
printf("The elements are:\n");
for (i = 0; i < n; i++) {
printf("%d ", arr[i]);
}
// Free the allocated memory
free(arr);
printf("\nMemory successfully freed.\n");
return 0;
}
11(b). Explain different types of modes and I/O functions in file handling.
File Modes in C:
- r (Read): Opens an existing file for reading. The file must exist.
- w (Write): Creates a file for writing. If the file exists, its content is overwritten.
- a (Append): Opens a file for appending data. If the file doesn’t exist, it is created.
- r+ (Read/Write): Opens an existing file for reading and writing.
- w+ (Write/Read): Creates a file for writing and reading. Overwrites if the file exists.
- a+ (Append/Read): Opens a file for appending and reading. Creates the file if it doesn’t exist.
Common File I/O Functions:
fopen()
: Opens a file.fclose()
: Closes a file.fprintf()
/fscanf()
: Used for formatted input/output.fgets()
/fputs()
: Used for string input/output.fread()
/fwrite()
: Used for binary file operations.
Example Program:
#include <stdio.h>
int main() {
FILE *file;
char data[100];
// Writing to a file
file = fopen("example.txt", "w");
if (file == NULL) {
printf("Failed to create file.\n");
return 1;
}
fprintf(file, "Hello, this is a file handling example.\n");
fclose(file);
// Reading from the file
file = fopen("example.txt", "r");
if (file == NULL) {
printf("Failed to open file.\n");
return 1;
}
while (fgets(data, 100, file) != NULL) {
printf("%s", data);
}
fclose(file);
return 0;
}
12(a). Define recursive function. Write a program to find the factorial of a number with a recursive function.
Definition of Recursive Function
A recursive function is a function that calls itself to solve a smaller instance of the same problem. It is characterized by the presence of a base condition, which is used to stop the recursion. Recursive functions are useful for solving problems that can be broken down into smaller, similar sub-problems, such as calculating factorials, generating Fibonacci sequences, or solving mathematical puzzles like the Tower of Hanoi.
Key Characteristics of a Recursive Function:
- Base Case: Terminates the recursion.
- Recursive Case: The function calls itself with a smaller input, reducing the problem's complexity with each call.
Example: Factorial Calculation
The factorial of a non-negative integer n
is defined as:
For example:
- By definition, .
Explanation of Code:
- Base Case: If
n == 0
orn == 1
, return 1 because and . - Recursive Case: If
n > 1
, return .
C Code:
#include <stdio.h>
// Recursive function to calculate factorial
int factorial(int n) {
if (n == 0 || n == 1) // Base condition
return 1;
else
return n * factorial(n - 1); // Recursive call
}
int main() {
int num;
// Input number
printf("Enter a number to find its factorial: ");
scanf("%d", &num);
// Handling negative numbers
if (num < 0) {
printf("Factorial of a negative number is undefined.\n");
} else {
// Output the factorial
printf("Factorial of %d is %d\n", num, factorial(num));
}
return 0;
}
Working of the Program:
Example for Input:
- Step 1: factorial(4) = 4 × factorial(3)
- Step 2: factorial(3) = 3 × factorial(2)
- Step 3: factorial(2) = 2 × factorial(1)
- Step 4: factorial(1) = 1 (Base Case)
- Result:
Memory Allocation in Recursion:
Each recursive call allocates memory in the stack for the function parameters and local variables until the base case is reached. After reaching the base case, the stack unwinds, and the results are combined.
Advantages of Recursion:
- Simplifies code for problems like factorial, Fibonacci, and tree traversals.
- Reduces the need for complex loops.
Disadvantages of Recursion:
- Higher memory usage due to stack calls.
- Risk of stack overflow for large inputs if base condition is not reached.
Iterative Approach for Comparison:
Recursion can be replaced with iteration in some cases. Here's how factorial would look in an iterative approach:
#include <stdio.h>
int factorial(int n) {
int result = 1;
for (int i = 1; i <= n; i++) {
result *= i;
}
return result;
}
While iteration is generally more memory-efficient, recursion is easier to read and write for certain problems.
Applications of Recursive Functions:
- Mathematical computations: Factorials, Fibonacci series.
- Problem-solving: Tower of Hanoi, maze traversal.
- Data structures: Tree traversals (in-order, pre-order, post-order).
Summary:
Recursive functions provide a powerful tool for solving problems with repetitive patterns. In the case of factorial, recursion simplifies the problem-solving process by breaking it down into smaller sub-problems.
b). Write a program to check whether a given number is an Armstrong number or not.
Definition:
- An Armstrong number of
n
digits is a number such that the sum of its digits raised to the powern
equals the number itself.
C Code:
#include <stdio.h>
#include <math.h>
int main() {
int num, originalNum, remainder, n = 0;
double result = 0;
printf("Enter an integer: ");
scanf("%d", &num);
originalNum = num;
// Count number of digits
while (originalNum != 0) {
originalNum /= 10;
n++;
}
originalNum = num;
// Check Armstrong condition
while (originalNum != 0) {
remainder = originalNum % 10;
result += pow(remainder, n);
originalNum /= 10;
}
if ((int)result == num)
printf("%d is an Armstrong number.\n", num);
else
printf("%d is not an Armstrong number.\n", num);
return 0;
}
13(a). Write a program to copy a string to another string using the standard library function. Use dynamic memory allocation to accept the string.
C Code:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main() {
char *source, *destination;
int length;
printf("Enter the length of the string: ");
scanf("%d", &length);
// Dynamic memory allocation for source string
source = (char *)malloc((length + 1) * sizeof(char));
if (source == NULL) {
printf("Memory allocation failed.\n");
return 1;
}
printf("Enter the string: ");
scanf(" %[^\n]", source);
// Dynamic memory allocation for destination string
destination = (char *)malloc((length + 1) * sizeof(char));
if (destination == NULL) {
printf("Memory allocation failed.\n");
free(source);
return 1;
}
// Copy string using strcpy
strcpy(destination, source);
printf("Source String: %s\n", source);
printf("Destination String: %s\n", destination);
// Free allocated memory
free(source);
free(destination);
return 0;
}
13(b). Differentiate between call by value and call by reference.
Call by Value:
- A copy of the actual parameter is passed to the function.
- Changes made inside the function do not affect the original variable.
- Used when the original data should remain unchanged.
- Example:
void modify(int x) { x = 10; }
Call by Reference:
- The actual parameter is passed to the function using its address.
- Changes made inside the function affect the original variable.
- Used to modify the original data or when working with large data to avoid copying.
- Example:
void modify(int *x) { *x = 10; }
Comments
Post a Comment