Вы находитесь на странице: 1из 338

Farzin Asadi

Essentials of C
Programming
with Microsoft®
Visual Studio®
Essentials of C Programming with Microsoft®
Visual Studio®
Farzin Asadi

Essentials of C Programming
with Microsoft® Visual
Studio®
Farzin Asadi
Department of Electrical and Electronics Engineering
Maltepe University
Istanbul, Turkey

ISBN 978-3-031-35710-7    ISBN 978-3-031-35711-4 (eBook)


https://doi.org/10.1007/978-3-031-35711-4

© The Editor(s) (if applicable) and The Author(s), under exclusive license to Springer Nature
Switzerland AG 2023
This work is subject to copyright. All rights are solely and exclusively licensed by the Publisher, whether
the whole or part of the material is concerned, specifically the rights of translation, reprinting, reuse of
illustrations, recitation, broadcasting, reproduction on microfilms or in any other physical way, and
transmission or information storage and retrieval, electronic adaptation, computer software, or by similar
or dissimilar methodology now known or hereafter developed.
The use of general descriptive names, registered names, trademarks, service marks, etc. in this publication
does not imply, even in the absence of a specific statement, that such names are exempt from the relevant
protective laws and regulations and therefore free for general use.
The publisher, the authors, and the editors are safe to assume that the advice and information in this book
are believed to be true and accurate at the date of publication. Neither the publisher nor the authors or the
editors give a warranty, expressed or implied, with respect to the material contained herein or for any
errors or omissions that may have been made. The publisher remains neutral with regard to jurisdictional
claims in published maps and institutional affiliations.

This Springer imprint is published by the registered company Springer Nature Switzerland AG
The registered company address is: Gewerbestrasse 11, 6330 Cham, Switzerland
In loving memory of my father Moloud Asadi
and my mother Khorshid Tahmasebi, always
on my mind, forever in my heart.
Preface

C is a general-purpose procedure-oriented computer programming language. C


programming language was developed in 1972 by Dennis Ritchie at Bell
Laboratories. It was named “C” because it is an offspring of BCPL (Basic Combined
Programming Language) which was popularly called “B” language. C was invented
to write an operating system called UNIX. The UNIX OS was totally written in C.
C is a procedure-oriented language. Procedures, also known as routines,
subroutines, or functions, simply consist of a series of computational steps to be
carried out. In procedural programming model, the problem is break down into
some small tasks and one or more procedures are written to do each task. Then
written procedures are called to obtain the problem solution. Another programming
model is Object Oriented Programming (OOP). OOP can be defined as a
programming model which is based upon the concept of objects. Objects contain
data in the form of attributes and code in the form of methods. OOP is not supported
in C. C++ was developed in the 1980s by Bjarne Stroustrup as an extension of
C. C++ can be considered as the OOP version of C.
C has now become a widely used professional language. Some of the advantages
of C language are:
1. Learning C programming is easy: C language has a small number of keywords
and symbols to learn. C language has one of the simplest syntax in comparison
to another programming languages.
2. C has enriched library for built-in functions: C has many pre-written, ready-­
to-­use libraries which contain useful functions to do a specific task. Presence of
these libraries eliminates the need to write the code from the ground up.
3. Compiled C code has a fast execution speed: C code executes faster than other
programming languages such as Java, Ruby, PHP, etc.
4. C language supports dynamic memory allocation: In C Language you can
allocate memory dynamically or statically. In static memory allocation, the
allocation of memory performs at the compile time. In dynamic memory
allocation, the allocation of memory performs at the execution or run time.

vii
viii Preface

Generally, C programming is the first programming course that students of


engineering and science take. This book is written to support a first course on C
programming language. There is no prerequisite for this book.
This book contains many examples to show how different tasks can be done in
C. All of the given examples are tested in Microsoft Visual Studio® to ensure that
they work properly without any error.
I hope that this book will be useful to the readers, and I welcome comments on
the book.

Istanbul, Turkey Farzin Asadi


Contents

1 Installation of Microsoft® Visual Studio® ����������������������������������������������    1


1.1 Introduction��������������������������������������������������������������������������������������    1
1.2 Installation of Visual Studio��������������������������������������������������������������    1
1.3 Entering the C Code to Visual Studio ����������������������������������������������    6
1.4 Running the C Code with Visual Studio ������������������������������������������   10
1.5 Errors in the Code ����������������������������������������������������������������������������   12
1.6 Color of Keywords in Visual Studio ������������������������������������������������   13
1.7 Comments ����������������������������������������������������������������������������������������   16
1.8 C Is a Case Sensitive Language��������������������������������������������������������   17
Further Reading ����������������������������������������������������������������������������������������   17
2 
Basics of C Programming������������������������������������������������������������������������   19
2.1 Introduction��������������������������������������������������������������������������������������   19
2.2 Primary Data Types in C������������������������������������������������������������������   19
2.3 Creating Variables ����������������������������������������������������������������������������   20
2.4 C Programming Naming Conventions����������������������������������������������   21
2.5 Printing on the Screen����������������������������������������������������������������������   21
2.6 Overflow of Variables������������������������������������������������������������������������   25
2.7 size_t Data Type��������������������������������������������������������������������������������   26
2.8 Minimum and Maximum of Primary Data Types����������������������������   27
2.9 Taking a Value From the User����������������������������������������������������������   28
2.10 Blocks ����������������������������������������������������������������������������������������������   32
2.11 Global Variables��������������������������������������������������������������������������������   34
2.12 Constants������������������������������������������������������������������������������������������   34
2.13 Enumeration��������������������������������������������������������������������������������������   35
2.14 typedef Keyword������������������������������������������������������������������������������   37
Further Readings����������������������������������������������������������������������������������������   38
3 Conditional Statements ��������������������������������������������������������������������������   39
3.1 Introduction��������������������������������������������������������������������������������������   39
3.2 if Command��������������������������������������������������������������������������������������   39
3.3 if-else Command������������������������������������������������������������������������������   41

ix
x Contents

3.4 Conditional Ternary Operator ����������������������������������������������������������   42


3.5 Logical Operators������������������������������������������������������������������������������   43
3.6 Nested if Statements ������������������������������������������������������������������������   44
3.7 switch-case Statement����������������������������������������������������������������������   45
Further Reading ����������������������������������������������������������������������������������������   49
4 Loops ��������������������������������������������������������������������������������������������������������   51
4.1 Introduction��������������������������������������������������������������������������������������   51
4.2 for Loop��������������������������������������������������������������������������������������������   51
4.3 break Command��������������������������������������������������������������������������������   64
4.4 continue Command ��������������������������������������������������������������������������   65
4.5 while Loop����������������������������������������������������������������������������������������   66
4.6 Infinite Loop��������������������������������������������������������������������������������������   67
4.7 do-while Loop����������������������������������������������������������������������������������   70
Further Reading ����������������������������������������������������������������������������������������   74
5 Arrays��������������������������������������������������������������������������������������������������������   75
5.1 Introduction��������������������������������������������������������������������������������������   75
5.2 Defining an Array������������������������������������������������������������������������������   75
5.3 Arrays and Pointers��������������������������������������������������������������������������   77
5.4 Length of an Array����������������������������������������������������������������������������   79
5.5 Removing an Element from the Array����������������������������������������������   80
5.6 2D Arrays������������������������������������������������������������������������������������������   81
5.7 Size of 2D Arrays������������������������������������������������������������������������������   83
5.8 malloc Function��������������������������������������������������������������������������������   84
5.9 calloc Function����������������������������������������������������������������������������������   87
Further Reading ����������������������������������������������������������������������������������������   88
6 Functions��������������������������������������������������������������������������������������������������   89
6.1 Introduction��������������������������������������������������������������������������������������   89
6.2 Definition of a Function��������������������������������������������������������������������   89
6.3 Pass by Value������������������������������������������������������������������������������������   92
6.4 List of Functions ������������������������������������������������������������������������������   94
6.5 void Functions����������������������������������������������������������������������������������   95
6.6 Scope and Lifetime of Variables ������������������������������������������������������   98
6.7 Function to Convert Fahrenheit to Celsius����������������������������������������   99
6.8 Combinations (nCr) Calculator��������������������������������������������������������   99
6.9 Password Checker ���������������������������������������������������������������������������� 100
6.10 Heads and Tails �������������������������������������������������������������������������������� 101
6.11 Cost of a Hotel���������������������������������������������������������������������������������� 102
6.12 Fibonacci Sequence (Iterative Approach) ���������������������������������������� 104
6.13 Fibonacci Sequence (Recursive Approach)�������������������������������������� 105
6.14 Recursive Factorial���������������������������������������������������������������������������� 106
6.15 Recursive Product ���������������������������������������������������������������������������� 107
6.16 Recursive Max and Min�������������������������������������������������������������������� 107
6.17 Static Variables���������������������������������������������������������������������������������� 109
Contents xi

6.18 Pass by Reference ���������������������������������������������������������������������������� 111


6.19 Passing an Array to a Functions�������������������������������������������������������� 112
6.20 Functions with Variable Number of Arguments�������������������������������� 115
6.21 Entering the Functions to Separate Files������������������������������������������ 117
6.22 extern Keyword�������������������������������������������������������������������������������� 122
Further Reading ���������������������������������������������������������������������������������������� 123
7 Some Useful Functions���������������������������������������������������������������������������� 125
7.1 Introduction�������������������������������������������������������������������������������������� 125
7.2 Running an .exe File ������������������������������������������������������������������������ 125
7.3 Playing a .wav File���������������������������������������������������������������������������� 126
7.4 main Arguments�������������������������������������������������������������������������������� 128
7.5 exit Function ������������������������������������������������������������������������������������ 134
7.6 atexit Function���������������������������������������������������������������������������������� 134
7.7 Reading the Mouse Pointer Position������������������������������������������������ 136
7.8 Timer������������������������������������������������������������������������������������������������ 138
7.9 Shutting Down the Computer ���������������������������������������������������������� 139
Further Reading ���������������������������������������������������������������������������������������� 139
8 Pointers ���������������������������������������������������������������������������������������������������� 141
8.1 Introduction�������������������������������������������������������������������������������������� 141
8.2 Address-of (&) Operator������������������������������������������������������������������ 141
8.3 Pointers �������������������������������������������������������������������������������������������� 142
8.4 Dereferencing (*) Operator�������������������������������������������������������������� 143
8.5 Pointer Arithmetic���������������������������������������������������������������������������� 145
8.6 Call by Reference������������������������������������������������������������������������������ 146
8.7 malloc Function�������������������������������������������������������������������������������� 148
8.8 NULL Pointer ���������������������������������������������������������������������������������� 149
8.9 void Pointer �������������������������������������������������������������������������������������� 152
Further Reading ���������������������������������������������������������������������������������������� 153
9 Structures and Unions ���������������������������������������������������������������������������� 155
9.1 Introduction�������������������������������������������������������������������������������������� 155
9.2 Defining a Structure�������������������������������������������������������������������������� 155
9.3 typedef Keyword������������������������������������������������������������������������������ 157
9.4 Copying the Content of a Structure Variable Into Another
Structure Variable������������������������������������������������������������������������������ 158
9.5 Functions with Structure Arguments������������������������������������������������ 159
9.6 Array of Structures���������������������������������������������������������������������������� 161
9.7 Arrow Operator �������������������������������������������������������������������������������� 164
9.8 Dereferencing a Pointer to a Structure���������������������������������������������� 166
9.9 Unions ���������������������������������������������������������������������������������������������� 168
9.10 Pointer to a Union ���������������������������������������������������������������������������� 169
Further Reading ���������������������������������������������������������������������������������������� 170
xii Contents

10 Mathematical Functions�������������������������������������������������������������������������� 171


10.1 Introduction������������������������������������������������������������������������������������ 171
10.2 Precedence of Operators ���������������������������������������������������������������� 171
10.3 Remainder of Division�������������������������������������������������������������������� 174
10.4 sizeof Operator�������������������������������������������������������������������������������� 175
10.5 Type Casting ���������������������������������������������������������������������������������� 176
10.6 Mathematical Constants������������������������������������������������������������������ 180
10.7 Power Function ������������������������������������������������������������������������������ 181
10.8 Square Root Function �������������������������������������������������������������������� 182
10.9 Cubic Root Function ���������������������������������������������������������������������� 183
10.10 Logarithm Function������������������������������������������������������������������������ 183
10.11 Trigonometric Functions���������������������������������������������������������������� 184
10.12 Inverse Trigonometric Functions���������������������������������������������������� 184
10.13 Hyperbolic Functions���������������������������������������������������������������������� 185
10.14 Inverse Hyperbolic Functions �������������������������������������������������������� 186
10.15 Exponential Function���������������������������������������������������������������������� 187
10.16 Rounding and Truncating Numbers������������������������������������������������ 187
10.17 floor and ceil Functions������������������������������������������������������������������ 188
10.18 fabs and hypot Functions���������������������������������������������������������������� 189
10.19 Generation of Random Numbers���������������������������������������������������� 189
10.20 Floating Point Numbers������������������������������������������������������������������ 194
10.21 Complex Functions ������������������������������������������������������������������������ 196
10.22 Binary and Hexadecimal Numbers ������������������������������������������������ 198
10.23 Bitwise Operation �������������������������������������������������������������������������� 199
10.24 GNU Scientific Library������������������������������������������������������������������ 200
Further Readings���������������������������������������������������������������������������������������� 201
11 String Processing�������������������������������������������������������������������������������������� 203
11.1 Introduction������������������������������������������������������������������������������������ 203
11.2 Defining a String ���������������������������������������������������������������������������� 203
11.3 String Inputs������������������������������������������������������������������������������������ 204
11.4 strlen Function�������������������������������������������������������������������������������� 206
11.5 strcpy Function�������������������������������������������������������������������������������� 207
11.6 strncpy Function������������������������������������������������������������������������������ 207
11.7 memset Function���������������������������������������������������������������������������� 208
11.8 memcpy Function���������������������������������������������������������������������������� 209
11.9 memmove Function������������������������������������������������������������������������ 209
11.10 strcmp Function������������������������������������������������������������������������������ 211
11.11 strncmp Function���������������������������������������������������������������������������� 212
11.12 memcmp Function�������������������������������������������������������������������������� 213
11.13 strcat Function�������������������������������������������������������������������������������� 214
11.14 strncat Function������������������������������������������������������������������������������ 215
11.15 strtok Function�������������������������������������������������������������������������������� 215
11.16 strcspn Function������������������������������������������������������������������������������ 219
11.17 strspn Function�������������������������������������������������������������������������������� 220
Contents xiii

11.18 atoi Function ���������������������������������������������������������������������������������� 221


11.19 atof Function ���������������������������������������������������������������������������������� 221
11.20 sscanf Function ������������������������������������������������������������������������������ 222
11.21 sprintf Function������������������������������������������������������������������������������ 224
11.22 strchr Function�������������������������������������������������������������������������������� 224
Further Reading ���������������������������������������������������������������������������������������� 226
12 Character Processing������������������������������������������������������������������������������ 227
12.1 Introduction������������������������������������������������������������������������������������ 227
12.2 isalnum Function���������������������������������������������������������������������������� 227
12.3 isalpha Function������������������������������������������������������������������������������ 228
12.4 isdigit Function ������������������������������������������������������������������������������ 229
12.5 iscntrl Function ������������������������������������������������������������������������������ 230
12.6 ispunct Function������������������������������������������������������������������������������ 233
12.7 isspace Function������������������������������������������������������������������������������ 234
12.8 islower Function������������������������������������������������������������������������������ 236
12.9 isupper Function������������������������������������������������������������������������������ 237
12.10 tolower Function ���������������������������������������������������������������������������� 237
12.11 toupper Function ���������������������������������������������������������������������������� 238
12.12 getch Function�������������������������������������������������������������������������������� 239
Further Reading ���������������������������������������������������������������������������������������� 240
13 Time and Date������������������������������������������������������������������������������������������ 241
13.1 Introduction������������������������������������������������������������������������������������ 241
13.2 Making Delay with Sleep Function������������������������������������������������ 241
13.3 Time Measurement ������������������������������������������������������������������������ 243
13.4 time Function���������������������������������������������������������������������������������� 243
13.5 Date and Time �������������������������������������������������������������������������������� 244
13.6 gmtime Function ���������������������������������������������������������������������������� 245
13.7 localtime Function�������������������������������������������������������������������������� 247
13.8 asctime Function ���������������������������������������������������������������������������� 248
13.9 strftime Function���������������������������������������������������������������������������� 249
13.10 _strtime and _strdate Functions������������������������������������������������������ 250
Further Reading ���������������������������������������������������������������������������������������� 251
14 Sorting and Searching ���������������������������������������������������������������������������� 253
14.1 Introduction������������������������������������������������������������������������������������ 253
14.2 Bubble Sort ������������������������������������������������������������������������������������ 253
14.3 Insertion Sort���������������������������������������������������������������������������������� 259
14.4 Quick Sort Algorithm���������������������������������������������������������������������� 262
14.5 Quick Sort for Integer Values���������������������������������������������������������� 263
14.6 Quick Sort for Double Values �������������������������������������������������������� 264
14.7 Quick Sort for Strings �������������������������������������������������������������������� 266
14.8 Binary Search���������������������������������������������������������������������������������� 268
Further Reading ���������������������������������������������������������������������������������������� 273
xiv Contents

15 File Processing������������������������������������������������������������������������������������������ 275


15.1 Introduction������������������������������������������������������������������������������������ 275
15.2 Creating a New File������������������������������������������������������������������������ 275
15.3 Append Mode���������������������������������������������������������������������������������� 278
15.4 ftell Function���������������������������������������������������������������������������������� 279
15.5 fprintf Function ������������������������������������������������������������������������������ 279
15.6 fseek Function�������������������������������������������������������������������������������� 281
15.7 rewind Function������������������������������������������������������������������������������ 283
15.8 Reading a File �������������������������������������������������������������������������������� 284
15.9 End Of File (EOF)�������������������������������������������������������������������������� 286
15.10 fgets Function���������������������������������������������������������������������������������� 287
15.11 getc Function���������������������������������������������������������������������������������� 288
15.12 Writing to a Binary File������������������������������������������������������������������ 289
15.13 Reading from Binary Files�������������������������������������������������������������� 291
15.14 Error Handling�������������������������������������������������������������������������������� 294
Further Readings���������������������������������������������������������������������������������������� 295
16 
Useful Functions to Work with Files and Directories �������������������������� 297
16.1 Introduction������������������������������������������������������������������������������������ 297
16.2 Copying .txt Files (I)���������������������������������������������������������������������� 297
16.3 Copying .txt Files (II) �������������������������������������������������������������������� 298
16.4 Copying Files with CopyFileA Function (I) ���������������������������������� 300
16.5 Copying Files with CopyFileA Function (II)���������������������������������� 301
16.6 Rename a File �������������������������������������������������������������������������������� 303
16.7 Remove a File �������������������������������������������������������������������������������� 303
16.8 Printing the Contents of a Directory ���������������������������������������������� 304
16.9 Obtaining the Address of Current Working Directory�������������������� 307
16.10 Changing the Current Working Directory�������������������������������������� 308
16.11 Making Directories ������������������������������������������������������������������������ 308
16.12 Removing Directories �������������������������������������������������������������������� 309
Further Reading ���������������������������������������������������������������������������������������� 310
17 
Serial Communication in C�������������������������������������������������������������������� 311
17.1 Introduction������������������������������������������������������������������������������������ 311
17.2 Reading from the Serial Port���������������������������������������������������������� 311
17.3 Writing to the Serial Port���������������������������������������������������������������� 315
Further Readings���������������������������������������������������������������������������������������� 319
18 Graphical User Interface������������������������������������������������������������������������ 321
18.1 Introduction������������������������������������������������������������������������������������ 321
18.2 Making a Simple GUI Project�������������������������������������������������������� 321
Further Readings���������������������������������������������������������������������������������������� 333
Index�������������������������������������������������������������������������������������������������������������������� 335
Chapter 1
Installation of Microsoft® Visual Studio®

1.1 Introduction

Visual Studio® is an Integrated Development Environment (IDE) from Microsoft®.


It is used to develop computer programs including websites, web apps, web services
and mobile apps. The most basic edition of Visual Studio, the Community edition,
is available free of charge. This chapter shows how to install the Community edition
and compile a C program with it.

1.2 Installation of Visual Studio

You can install the Community edition of Visual Studio free of charge. You need the
Visual Studio installer to install the Community edition. The Visual Studio installer
can be downloaded from the Microsoft site. Search for “visual studio installer” to
find the download page (Fig. 1.1).

© The Author(s), under exclusive license to Springer Nature Switzerland AG 2023 1


F. Asadi, Essentials of C Programming with Microsoft® Visual Studio®,
https://doi.org/10.1007/978-3-031-35711-4_1
2 1 Installation of Microsoft® Visual Studio®

Fig. 1.1 Downloading the Visual Studio installer

After installing the Visual Studio installer, run it and install the C++ (Figs. 1.2
and 1.3) with the installation details shown in Fig. 1.4.

Fig. 1.2 Installation of C++ programming language

Fig. 1.3 Desktop development with C++ is selected


1.2 Installation of Visual Studio 3

Fig. 1.4 Installation


details
4 1 Installation of Microsoft® Visual Studio®

After installation, run the Visual Studio. Window shown in Fig. 1.5 appears in the
first run. Click the Create a new project button (Fig. 1.5) to continue.

Fig. 1.5 Visual Studio window

The window shown in Fig. 1.6 appears after clicking the Create a new project
button. Search for “Empty Project” (Fig. 1.6) and click the Next button.

Fig. 1.6 Create a new project window


1.2 Installation of Visual Studio 5

Now give a name to your project and save it in the desired location (Fig. 1.7).
After clicking the Create button, an empty project is generated for you (Fig. 1.8).

Fig. 1.7 Configure your new project window

Fig. 1.8 Visual Studio environment


6 1 Installation of Microsoft® Visual Studio®

You can close the current project by clicking the File> Close Solution (Fig. 1.9).

Fig. 1.9 File> Close Solution

You can make a new project by clicking the File> New> Project… (Fig. 1.10).
After clicking the File> New> Project…, the window shown in Fig. 1.6 appears and
you can make what you want.

Fig. 1.10 File> New> Project

1.3 Entering the C Code to Visual Studio

Making an empty project is studied in the previous section. This sections shows how
to add a C file to the generated project. In this section, we need the Solution Explorer
window (Fig. 1.11). Click the View> Solution Explorer (Fig. 1.12) if you can-
not see it.
1.3 Entering the C Code to Visual Studio 7

Fig. 1.11 Solution Explorer

Fig. 1.12 View> Solution Explorer

You can add a C file to the project by right clicking on Source Files, select the
Add and New Item (Fig. 1.13). After clicking the New Item, the Add New Item
window appears. Select the C++ File (.cpp) however, save your work with .c exten-
sion (Fig. 1.14).
8 1 Installation of Microsoft® Visual Studio®

Fig. 1.13 Add> New Item

Fig. 1.14 C++ File (.cpp)

After clicking the Add button in Fig. 1.14, a file is added under the Source Files
(Fig. 1.15). Double click on it to open it. Now you can write your code (Fig. 1.16).
Press the Ctrl+S to save your code.
1.3 Entering the C Code to Visual Studio 9

Fig. 1.15 main.c

Fig. 1.16 Source code is entered


10 1 Installation of Microsoft® Visual Studio®

1.4 Running the C Code with Visual Studio

Press the F5 key of your keyboard to run the entered code. You can use the Build>
Build Solution (Fig. 1.17) as well. The Output window (Fig. 1.18) shows the prog-
ress of Build process. The Build process is successful according to Fig. 1.18.

Fig. 1.17 Build> Build Solution

Fig. 1.18 Output window

Visual Studio runs the code after the build process. Figure 1.19 show the output
of code shown in Fig. 1.16.
1.4 Running the C Code with Visual Studio 11

Fig. 1.19 Output of the code

Let’s take a look at the files generated by Visual Studio. Go to the path where you
saved your project (Fig. 1.20). You will see two folders (Debug and Project1) and
one file (Project1.sln) there.

Fig. 1.20 Generated files and folders

Open the Debug folder. The executable file generated from the code is here
(Fig. 1.21).

Fig. 1.21 Contents of Debug folder

Return to the Project 1 folder and open it (Fig. 1.22). Contents of Project 1 folder
are shown in Fig. 1.23.

Fig. 1.22 Contents of Project1 folder


12 1 Installation of Microsoft® Visual Studio®

Fig. 1.23 main.c file

The main file in Fig. 1.23 contains the C code that you wrote in Visual Studio
environment. You can use the Notepad to open it (Fig. 1.24). The code shown in
Fig. 1.16 is the same as the code shown in Fig. 1.24.

Fig. 1.24 main.c is opened in Notepad

1.5 Errors in the Code

When your code has an error, the build process is stopped and an error message
appears in the Error List window. For instance, if you remove the ‘;’ after ‘return 0’
(Fig. 1.25), the Error List shown in Fig. 1.26 appears on the bottom of the screen
and tells you that you have an error in the seventh line.
1.6 Color of Keywords in Visual Studio 13

Fig. 1.25 Semicolon is removed from the code

Fig. 1.26 Error List window

1.6 Color of Keywords in Visual Studio

C programming language has 44 keywords. These keywords are shown in Table 1.1.
First four columns contain the more important keywords.

Table 1.1 Keywords of C language


auto double int struct _Alignas _Static_assert
break else long switch _Alignof
case enum register typedef _Atomic _Thread_local
char extern return union _Bool
continue for signed void _Complex inline
do if static while _Generic
default goto sizeof volatile _Imaginary restrict
const float short unsigned _Noreturn

By default, Visual Studio uses two different colors (blue and purple) for these
keywords (Fig. 1.27).
14 1 Installation of Microsoft® Visual Studio®

Fig. 1.27 By default, keywords are shown in blue and purple

You can change the default colors if you like. To do so click the Tools> Options…
(Fig. 1.28).

Fig. 1.28 Tools> Options

The Options window appears after clicking the Options… (Fig. 1.29).
1.6 Color of Keywords in Visual Studio 15

Fig. 1.29 Option window

Select the Fonts and Colors. Use the C/C++ User Keywords (Fig. 1.30) and C/
C++ Keywords – Control (Fig. 1.30) to select the desired colors (Fig. 1.31).

Fig. 1.30 Options window


16 1 Installation of Microsoft® Visual Studio®

Fig. 1.31 Options window

1.7 Comments

Comments have no effect on the running of the program and they will be ignored by
the compiler. They are added with the purpose of making the source code easier for
humans to understand. You can use the /* */ and // for multiline and single line com-
ments, respectively. Visual Studio shows the comments in green color. An example
is shown below:
/* this is simple program to print a message
on the screen. After printing the message it
waits untill the user press a key.
*/

#include <stdio.h>

int main() {
printf("Hello World!"); //this line prints the message on the screen
getch(); //waits untill a key is pressed
return 0; //returns 0 to the operating system
}
Further Reading 17

1.8 C Is a Case Sensitive Language

C is a case sensitive language. It means that capital letters and small letters are con-
sidered different things. For instance, in the following code, two variables are
defined with a and A names and each one has its own value. Output of this code is
shown in Fig. 1.32.
#include <stdio.h> //adds the stdio library to our code
//printf function is defined here

int main() //each C code has a main function


{
int a = 1; //defines an integer variable a
int A = 2; //defines an integer variable A
printf("Value of a is: %d\n", a); //prints a
printf("Value of b is: %d\n", A); //prints A
return 0; //return 0 to the operating system.
//when we return 0 it means that
//program finished successfuly
}

Fig. 1.32 Output of the code

Further Reading

1. Deitel P, Deitel H (2022) C how to program: with case studies in applications and systems
programming, 9th edn. Pearson
Chapter 2
Basics of C Programming

2.1 Introduction

This chapter studies the basic programming skills such as defining different types of
variables, printing on the screen, and taking values from the user.

2.2 Primary Data Types in C

Here are the five primitive or primary data types that one can find in C programming
language:
(a) Integer: We use these for storing various whole numbers, such as −500, 8, 67,
2390, etc.
(b) Character: It refers to all ASCII character sets as well as to the single alpha-
bets, such as ‘x’, ‘Y’, etc.
(c) Double: These include all large types of numeric values that do not come under
either floating-point data type or integer data type. Double variables require 8
bytes of memory. Double type is more accurate in comparison to the
floating-point.
(d) Floating-point: These refer to all the real number values or decimal points,
such as 40.1, 820.673, 5.9, etc. Floating-point variables require 4 bytes
of memory.
(e) Void: This term refers to no values at all. We mostly use this data type when
defining the functions in a program. This type is defined with the aid of key-
word void.

© The Author(s), under exclusive license to Springer Nature Switzerland AG 2023 19


F. Asadi, Essentials of C Programming with Microsoft® Visual Studio®,
https://doi.org/10.1007/978-3-031-35711-4_2
20 2 Basics of C Programming

Table 2.1 shows the primary data types and their format specifiers. Format speci-
fiers are studied in Sect. 2.5. Signed datatypes can be both positive and negative.
Unsigned datatypes accept positive values only.

Table 2.1 Primary data types and their format specifier


Memory Format specifier (see
Data type (bytes) Range Sect. 2.5)
short int 2 −32,768 to 32,767 %hd
unsigned 2 0 to 65,535 %hu
short int
unsigned int 4 0 to 4,294,967,295 %u
int 4 −2,147,483,648 to %d
2,147,483,647
long int 4 −2,147,483,648 to %ld
2,147,483,647
unsigned 4 0 to 4,294,967,295 %lu
long int
long long 8 −(2^63) to (2^63)−1 %lld
int
unsigned 8 0 to %llu
long long 18,446,744,073,709,551,615
int
signed char 1 −128 to 127 %c
unsigned 1 0 to 255 %c
char
float 4 1.2E-38 to 3.4E+38 %f
double 8 1.7E-308 to 1.7E+308 %lf
long double 8 1.7E-308 to 1.7E+308 %Lf

2.3 Creating Variables

To create a variable, specify the variable type and name: type variableName; You
can assign an initial value to the variable as well: type
variableName = initialValue;
Let’s study some examples:
int a; // creates an integer variable with name a.

double b = 12.3; // creates a double variable with name b and


// gives the initial value of 12.3 to it.

char c = 'X'; // creates an character variable with name c and puts X into it.
2.5 Printing on the Screen 21

2.4 C Programming Naming Conventions

Meaningful descriptive names must be given to variables. Below rules must be fol-
lowed when naming a variable:
(a) Names can contain letters, digits, and underscores.
(b) Names must begin with a letter or an underscore (_).
(c) Names are case sensitive (for instance, myVar and myvar are different variables).
(d) Names cannot contain whitespaces or special characters, such as !, #, %, etc.
(e) Reserved words (such as int) cannot be used as names.
Let’s study some of the examples:
int var1; // it is correct
int 1var; // it is incorrect – the name of the variable should not start using a
number
int my_var1; // it is correct
int my$var; // it is incorrect – no special characters should be in the name of the
variable
char else; // there must be no keywords in the name of the variable
int my var; // it is incorrect – there must be no spaces in the name of the variable

2.5 Printing on the Screen

The printf function prints a formatted output on the screen. An escape sequence in
C language is a sequence of characters that does not represent itself when used
inside string literal or character. Some of the important escape sequences are shown
in Table 2.2.

Table 2.2 Common escape Escape sequence Description


sequences \n Newline
\t Horizontal tab
\r Carraige return

Format specifiers are used to display the value of variables. Table 2.3 shows the
important format specifiers.
22 2 Basics of C Programming

Table 2.3 Format specifiers Specifier Description


%c Character
%e Scientific notation (mantissa/exponent)
using e character
%E Scientific notation (mantissa/exponent)
using E character
%g Uses the shorter of %e or %f
%G Uses the shorter of %E or %f
%o Signed octal
%s String of characters
%x Unsigned hexadecimal integer
%X Unsigned hexadecimal integer (capital
letters)
%p Pointer address
%d Prints an int variable
%c Prints a char variable
%f Prints a float/double variable
%lf Prints a double variable
%hd Prints a short int variable
%u Prints an unsigned int variable
%ld Prints a long int variable
%lld Prints a long long int variable
%lu Prints an unsigned long int variable
%llu Prints an unsigned long long int variable
%c Prints a signed char variable
%c Prints an unsigned char variable
%Lf Prints a long double variable

Let’s study some examples. The following code defines three variables and prints
them on the screen. Output of this code is shown in Fig. 2.1.
#include <stdio.h>

int main()
{
float a = 120.63;
double b = 786.633;
int c = 639;

printf("a=%f\n", a);
printf("b=%lf\n", b);
printf("c=%d\n", c);

return 0;
}

Fig. 2.1 Output of


the code
2.5 Printing on the Screen 23

The following code prints the variables using scientific notations. Output of this
code is shown in Fig. 2.2. Note that %e or %E works with float or double data
types only.
#include <stdio.h>

int main()
{
float a = 120.63;
double b = 786.633;

printf("a=%e\n", a);
printf("b=%e\n", b);

return 0;
}

Fig. 2.2 Output of


the code

The following code shows how to print a double variable up to two decimal
points. Output of this code is shown in Fig. 2.3.
#include <stdio.h>

int main()
{
double a = 123.456789;

printf("a=%.2f", a);

return 0;
}

Fig. 2.3 Output of


the code

The following code shows how to print hexadecimal equivalent of a decimal


value. Output of this code is shown in Fig. 2.4.
#include <stdio.h>

int main()
{
int a = 156;
printf("Hexadecimal equivalent of 156 is %X.", a);
return 0;
}
24 2 Basics of C Programming

Fig. 2.4 Output of


the code

The following code is an example of escape sequences. Output of this code is


shown in Fig. 2.5. \n shifts the cursor to a new line, \t shifts the cursor four spaces
to the right, and \r positions the cursor to the beginning of the current line.
#include <stdio.h>

int main() {
printf("1. We are learning C programming...");
printf("2. C is a powerful language\n");
printf("3. C\tis\ta\tcase sensitive language\n");
printf("4. C is developed by Dennis M. Ritchie \rin the early 1970");
return 0;
}

Fig. 2.5 Output of the code

The following code shows how to clear the screen. Output of this code is shown
in Fig. 2.6.
#include <stdio.h>
#include <stdlib.h>

int main() {
printf("1. We are learning C programming...");
printf("2. C is a powerful language\n");
printf("3. C\tis\ta\tcase sensitive language\n");
printf("4. C is developed by Dennis M. Ritchie \rin the early 1970");

system("cls");
return 0;
}

Fig. 2.6 Output of the code


2.6 Overflow of Variables 25

The following code shows how to print the % and \ on the screen. Output of this
code is shown in Fig. 2.7.
#include <stdio.h>

int main()
{
printf("80%% of students passed the course.\n");
printf("backslash \\");
return 0;
}

Fig. 2.7 Output of


the code

The following code shows how to position the cursor at the desired row and col-
umn. Output of this code is shown in Fig. 2.8.
#include<stdio.h>
#include<windows.h>

int main()
{
COORD c1;
c1.X = 0;
c1.Y = 0;
SetConsoleCursorPosition(GetStdHandle(STD_OUTPUT_HANDLE), c1);
printf("*");//* is placed at (0,0)

c1.X= 16;
c1.Y = 2;
SetConsoleCursorPosition(GetStdHandle(STD_OUTPUT_HANDLE), c1);
printf("?");//? is placed at (16,2)

return 0;
}

Fig. 2.8 Output of


the code

2.6 Overflow of Variables

Variable overflow occurs when you attempt to store inside a variable a value that is
larger than the maximum value the variable can hold. The C standard defines this
situation as undefined behavior (meaning that anything might happen).
26 2 Basics of C Programming

Let’s study an example. In the following code, variable a has the maximum
allowed value. Overflow occurs if you increase the value of variable by at least one
unit. Output of the following code is shown in Fig. 2.9. Note that values shown for
variables b and c are wrong.
#include <stdio.h>

int main()
{
int a = 2147483647;
int b = 2147483647 + 1;
int c = 2147483647 + 2;

printf("Expected value for a is 2147483647. Value of a= %d\n", a);


printf("Expected value for b is 2147483647+1. Value of b= %d\n", b);
printf("Expected value for a is 2147483647+2. Value of c= %d\n", c);

return 0;
}

Fig. 2.9 Output of the code

2.7 size_t Data Type

The datatype size_t is unsigned integral type. It can never be negative. The sizeof
operator and functions like: strlen and strcspn (Chap. 11) return size_t type.
Functions like: malloc and memcpy take the size_t as input arguments.
The following code prints the maximum value that can be stored in a size_t vari-
able. Output of this code is shown in Fig. 2.10.
#include <stdio.h>
#include <stdint.h> //SIZE_MAX is defined here

int main()
{
// minimum range of size_t is 0 up to 4,294,967,295
printf("Maximum value that can be stored in size_t vars: %zu", SIZE_MAX);

return 0;
}

Fig. 2.10 Output of the code


2.8 Minimum and Maximum of Primary Data Types 27

2.8 Minimum and Maximum of Primary Data Types

The following code prints the minimum and maximum values that can be stored in
char (character data type), int (integer data type), and long long (long integer data
type) variables. This code also tells how much memory is required to store these
data types in memory. Output of this code is shown in Fig. 2.11.
#include <stdio.h>
#include <limits.h>

int main()
{
printf("size of a char variable in Bytes:%d \n", sizeof(char));
printf("Minimum of a char variable: %d\n",CHAR_MIN);
printf("Maximum of a char variable: %d\n", CHAR_MAX);

printf("\n\nsize of a int variable in Bytes:%d \n", sizeof(int));


printf("Minimum of a int variable: %d\n", INT_MIN);
printf("Maximum of a int variable: %d\n", INT_MAX);

printf("\n\nsize of a long variable in Bytes:%d \n", sizeof(long));


printf("Minimum of a long variable: %ld\n", LONG_MIN);
printf("Maximum of a long variable: %ld\n", LONG_MAX);

printf("\n\nsize of a long long variable in Bytes:%d \n", sizeof(long long));


printf("Minimum of a long long variable: %lld\n", LLONG_MIN);
printf("Maximum of a long long variable: %lld\n", LLONG_MAX);

return 0;
}

Fig. 2.11 Output of the code


28 2 Basics of C Programming

Let’s study another example. The following code prints the minimum and maxi-
mum values that can be stored in float and double data types. This code also tells
how much memory is required to store these data types in memory. Output of this
code is shown in Fig. 2.12.
#include <stdio.h>
#include <float.h>

int main()
{
printf("Minimum value of a floating point number:%e \n", FLT_MIN);
printf("Maximum value of a floating point number:%e \n\n", FLT_MAX);

printf("Minimum value of a double number:%e \n", DBL_MIN);


printf("Maximum value of a double number:%e \n\n", DBL_MAX);

printf("Epsilon for floating point numbers:%e \n", FLT_EPSILON);


printf("Epsilon for double point numbers:%e \n", DBL_EPSILON);
printf("Epsilon=Smallest positive number x, such that x + 1.0 is not equal to
1.0.\n\n");

return 0;

Fig. 2.12 Output of the code

2.9 Taking a Value From the User

The scanf function (scanf stands for scan formatted string) is the commonly used
function to take input from the user. It reads formatted input from the standard input
such as keyboards. The name of the variable that is read by the scanf function must
have an & behind it.
The following type specifiers are recognized by the scanf function:
%d to accept input of integers
%ld to accept input of long integers
%lld to accept input of long long integers
%f to accept input of real number
%c to accept input of character types
2.9 Taking a Value From the User 29

%s to accept input of a string


Let’s study an example. In the following code, scanf function is used to read the
radius variable. Sample output of this code is shown in Fig. 2.13.
//This code take the radius of a circle and calculates its perimeter and area.

#define _CRT_SECURE_NO_WARNINGS // put this line otherwise


// the scanf command doesn't work
#include <stdio.h>

int main() {
//variables are defined here
float radius=0.0;
float perimeter = 0.0;
float area = 0.0;

//taking the radius and calculation of area and perimeter


printf("Please enter the radius: ");
scanf("%f", &radius); //NOTE:& must be put before the name of the variable
area = 3.1415926 * radius * radius;
perimeter = 2*3.1415926 * radius;

//printing the results


printf("Perimeter=%f\n",perimeter);
printf("Area=%f\n",area);

return 0;
}

Fig. 2.13 Output of


the code

The previous code prints the results up to six decimal points. The following code
shows how to control the number of decimal places. This code prints the results up
to three decimal places. Sample output of this code is shown in Fig. 2.14.
#define _CRT_SECURE_NO_WARNINGS // put this line otherwise
// the scanf command doesn't work
#include <stdio.h>

int main() {
//variables are defined here
float radius = 0.0;
float perimeter = 0.0;
float area = 0.0;

//taking the radius and calculation of area and perimeter


printf("Please enter the radius: ");
scanf("%f", &radius);
area = 3.1415926 * radius * radius;
perimeter = 2 * 3.1415926 * radius;

//printing the results


printf("Perimeter=%.3f\n", perimeter);
printf("Area=%.3f\n", area);

return 0;
}
30 2 Basics of C Programming

Fig. 2.14 Output of


the code

Let’s study some more examples. The following code reads a character and prints
its ASCII code. Sample output of this code is shown in Fig. 2.15. Table of ASCII
code are shown in Fig. 2.16.
#define _CRT_SECURE_NO_WARNINGS // put this line otherwise
// the scanf command doesn't work
#include <stdio.h>

int main() {
char c;
printf("Please enter a character: ");
scanf("%c", &c);

printf("ASCII value of \'%c\'=%d\n", c, c); //\' is used to print a single quote


//\n is used to send the cursor to
the next line
return 0;

Fig. 2.15 Output of


the code
2.9 Taking a Value From the User 31

Fig. 2.16 Table of ASCII code


32 2 Basics of C Programming

The following code takes two integer values from the user and puts them into
variables x and y. The code then swaps the values of variable x and y. Sample output
of this code is shown in Fig. 2.17.
#define _CRT_SECURE_NO_WARNINGS // put this line otherwise
// the scanf command doesn't work
#include <stdio.h>

int main()
{
int x, y, temp;

printf("please enter first number: ");


scanf("%d", &x);
printf("please enter second number:");
scanf("%d", &y);

printf("\n\nBefore swap");
printf("\nvalue of x = %d\n", x);
printf("value of y = %d\n", y);

temp = x;
x= y;
y = temp;

printf("\n\nAfter swap\n");
printf("value of x = %d\n", x);
printf("value of y = %d\n", y);
}

Fig. 2.17 Output of


the code

2.10 Blocks

A block is a program region that contains the definitions of variables and delimits
the regions where these definitions apply. In C programming language, a block is
created using a pair of curly braces. The beginning of the block is denoted by an
open curly brace '{' and the end is denoted by a closing curly brace '}'.
2.10 Blocks 33

A variable declared inside a block is accessible in the block and all inner blocks
of that block, but not accessible outside the block. Basically, these are local to the
blocks in which the variables are defined and are not accessible outside. Variables
declared in a block will be destroyed after exiting from the block.
Following is an example. Output of this code is shown in Fig. 2.18.
#include <stdio.h>
int main() {
int n = 1;
int m = 0;
{
int n = 2;
printf("value of n inside the block: %d\n", n);
printf("value of m is accesible from the inner block: %d\n", m);
}
printf("value of n outside the block: %d\n", n);
}

Fig. 2.18 Output of the code

Let’s study another example. You will receive an error (Fig. 2.19) if you try to
compile the following code. Note that variable a is not accessible outside the block.
#include <stdio.h>

int main()
{
{
int a = 1;
}
printf("%d", a);
}

Fig. 2.19 Error List window


34 2 Basics of C Programming

2.11 Global Variables

Variables declared inside of a block are accesible in that block (and inner blocks)
only and are not accesible in other places of the code. You need to define a global
variable if you need a variable that is accessible everywhere.
You can create a global variable by declaring it before the main function. For
example, variable b is a global variable in the following code. Output of this code is
shown in Fig. 2.20.
#include <stdio.h>

int b = 2;

int main()
{
{
printf("I can see the variable b, b=%d\n", b);
}
printf("Me too, b=%d\n", b);
}

Fig. 2.20 Output of


the code

2.12 Constants

A constant is a value that cannot be changed in the program. Constants can be


defined in two ways: using the #define directive and using the const keyword. Let’s
study an example.
The following code takes the radius of a circle from the user and calculates the
perimeter and area. Value of π is defined using the #define directive.
#define _CRT_SECURE_NO_WARNINGS // put this line otherwise
// the scanf command doesn't work
#define PI 3.1415926

#include <stdio.h>

int main() {
//variables are defined here
float radius=0.0;
float perimeter = 0.0;
float area = 0.0;

//taking the radius and calculation of area and perimeter


printf("Please enter the radius: ");
scanf("%f", &radius);
area = PI * radius * radius;
perimeter = 2 * PI * radius;

//printing the results


printf("Perimeter=%f\n",perimeter);
printf("Area=%f\n",area);

return 0;
}
2.13 Enumeration 35

The following code is quite similar to the previous code. This code used the const
keyword to define the π.
#define _CRT_SECURE_NO_WARNINGS // put this line otherwise
// the scanf command doesn't work
#include <stdio.h>

int main() {
//constant values are defined here
const float PI = 3.1415926;
//variables are defined here
float radius=0.0;
float perimeter = 0.0;
float area = 0.0;

//taking the radius and calculation of area and perimeter


printf("Please enter the radius: ");
scanf("%f", &radius);
area = PI * radius * radius;
perimeter = 2 * PI * radius;

//printing the results


printf("Perimeter=%f\n",perimeter);
printf("Area=%f\n",area);

return 0;
}

The following code defines a constant array. (Arrays are studied in Chap. 5)
#include <stdio.h>

int main()
{
const int a[] = {1,2,3,4,5};

return 0;
}

2.13 Enumeration

Enumeration (or enum) is a user defined data type in C. It is mainly used to assign
names to integral constants; the names make a program easy to read and maintain.
Let’s study an example. In the following code values of 0, 1, 2, 3, …, 6 will be
assigned to Monday, Tuesday, Wednesday, …, Sunday. We declared two variables
(today and tomorrow) and assigned initial value to them. Output of this code is
shown in Fig. 2.21.
36 2 Basics of C Programming

#include <stdio.h>

enum Day {Monday, Tuesday, Wednesday, Thursday,


Friday, Saturday, Sunday};

int main()
{
enum Day today = Tuesday;
enum Day tommarow = Wednesday;
printf("today= %d\n", today);
printf("tommarow= %d\n", tommarow);

return 0;
}

Fig. 2.21 Output of


the code

You can assign any value to each of the names. Following is an example. Output
of this code is shown in Fig. 2.22.
#include <stdio.h>

enum Day {
Monday=50, Tuesday=51, Wednesday=52, Thursday=53,
Friday=20, Saturday=21, Sunday=22
};

int main()
{
enum Day Day1= Monday;
enum Day Day2 = Tuesday;
enum Day Day3 = Wednesday;
enum Day Day4 = Thursday;
enum Day Day5 = Friday;
enum Day Day6 = Saturday;
enum Day Day7 = Sunday;

printf("Day1= %d\n", Day1);


printf("Day2= %d\n", Day2);
printf("Day3= %d\n", Day3);
printf("Day4= %d\n", Day4);
printf("Day5= %d\n", Day5);
printf("Day6= %d\n", Day6);
printf("Day7= %d\n", Day7);

return 0;
}
2.14 typedef Keyword 37

Fig. 2.22 Output of


the code

2.14 typedef Keyword

The C programming language provides a keyword called typedef, which you can
use to give a type a new name. Let’s study some examples.
In the following code, uint is another name to unsigned int data type. Output of
this code is shown in Fig. 2.23.
#include <stdio.h>

typedef unsigned int uint;

int main()
{
uint a=123;
printf("value of a is %u.", a);
return 0;
}

Fig. 2.23 Output of


the code

The typedef keywords can be used with enum and struct types as well. Following
is an example. Compare this code with the code given in the previous section.
Output of this code is shown in Fig. 2.24.
#include <stdio.h>

typedef enum Day {Monday, Tuesday, Wednesday, Thursday,


Friday, Saturday, Sunday} day;

int main()
{
day today = Tuesday;
day tommarow = Wednesday;
printf("today= %d\n", today);
printf("tommarow= %d\n", tommarow);

return 0;
}
38 2 Basics of C Programming

Fig. 2.24 Output of


the code

You can use the typedef with structures as well (see Chap. 9).

Further Readings

1. https://bit.ly/3N71Oqk
2. https://bit.ly/43RAPoz
Chapter 3
Conditional Statements

3.1 Introduction

Conditional Statements are used to make decisions based on the conditions. This
chapter studies different types of conditional statements in C programming.

3.2 if Command

The if command permits you to run a specific code when one or more conditions are
satisfied. You can run a specific code when the condition(s) is not satisfied as well.
Figure 3.1 shows how if command works: When the condition of if statement is
satisfied, the commands inside the {} are run. When the condition of if statement is
not satisfied, the commands inside the {} are ignored and the program continue
running from the command after the }.

© The Author(s), under exclusive license to Springer Nature Switzerland AG 2023 39


F. Asadi, Essentials of C Programming with Microsoft® Visual Studio®,
https://doi.org/10.1007/978-3-031-35711-4_3
40 3 Conditional Statements

Fig. 3.1 Behavior of if command

Let’s study an example. In the following code, two Boolean variables are defined.
Note that you need to use the stdbool.h when you want to define Boolean variables.
Defined Boolean variables are used in the condition section of if statements. Output
of this code is shown in Fig. 3.2. Note that the if statement with true condition is run.
#include <stdio.h>
#include <stdbool.h>

int main()
{
bool b1 = true;
bool b2 = false;

if (b1)
{
printf("b1 is true, therefore this line is printed");
}
if (b2)
{
printf("b2 is false, therefore this line is NOT printed");
}
}

Fig. 3.2 Output of


the code

You are not forced to use {} when you only have a single line command in the
then section of the if statement. For example, previous code can be written as:
3.3 if-else Command 41

#include <stdio.h>
#include <stdbool.h>

int main()
{
bool b1 = true;
bool b2 = false;

if (b1)
printf("b1 is true, therefore this line is printed");

if (b2)
printf("b2 is false, therefore this line is NOT printed");
}

Table 3.1 shows the commonly used operators in the condition section of if
statements.

Table 3.1 Commonly used relational operators


Operator Description
== Checks if the values of two operands are equal or not. If yes, then the condition
becomes true. You cannot use the assignment operator in the condition section of if
statements
!= Checks if the values of two operands are equal or not. If the values are not equal, then
the condition becomes true
> Checks if the value of left operand is greater than the value of right operand. If yes,
then the condition becomes true
< Checks if the value of left operand is less than the value of right operand. If yes, then
the condition becomes true
>= Checks if the value of left operand is greater than or equal to the value of right
operand. If yes, then the condition becomes true
<= Checks if the value of left operand is less than or equal to the value of right operand.
If yes, then the condition becomes true

3.3 if-else Command

You can use the else command to determine what should be done when the condi-
tion of if statement is not satisfied.
Let’s study an example. In this example, we want to write a C program to deter-
mine whether a given number is even or odd. The following code takes a number
from the user and divides it by two. When the remainder of division by two is zero,
the number is even. When the remainder of division is not zero, the number is odd.
Remainder of an integer divisions can be calculated with the aid of % operator.
Sample output for this code is shown in Fig. 3.3.
42 3 Conditional Statements

#define _CRT_SECURE_NO_WARNINGS // put this line otherwise


// the scanf command doesn't work

#include <stdio.h>

int main() {
int num;
printf("Enter an integer: ");
scanf("%d", &num);

// true if num is perfectly divisible by 2.


if (num % 2 == 0) // when reminder is zero:
printf("%d is even.", num);
else
printf("%d is odd.", num);

return 0;
}

Fig. 3.3 Output of


the code

3.4 Conditional Ternary Operator

Conditional ternary operator takes three operands: a condition followed by a ques-


tion mark, then an expression to execute if the condition is true followed by a colon,
and finally an expression to execute if the condition is false. Use of conditional
ternary operator decreases the readability of your code. Therefore, its use is not
recommended.
Let’s study an example. The following code uses the conditional ternary operator
to determine whether a number is even or odd. Sample output of this code is shown
in Fig. 3.4.
#define _CRT_SECURE_NO_WARNINGS // put this line otherwise
// the scanf command doesn't work
#include <stdio.h>
int main() {
int num;
printf("Enter an integer: ");
scanf("%d", &num);

(num % 2 == 0) ? printf("%d is even.", num) : printf("%d is odd.", num);


return 0;
}

Fig. 3.4 Output of


the code
3.5 Logical Operators 43

Let’s study another example. In the following code, the value of 5 is assigned to
variable c when variables a and b are equal. Zero is assigned to variable c when
variables a and b are not equal.
#include <stdio.h>

int main()
{
int a = 10;
int b = 10;
int c = 1;

c = (a == b) ? 5 : 0;

printf("value of c is: %d", c);

return 0;
}

The previous code can be written in the following more readable way:
#include <stdio.h>

int main()
{
int a = 10;
int b = 20;
int c = 1;

if (a == b)
c = 5;
else
c = 0;

printf("value of c is: %d", c);

return 0;
}

3.5 Logical Operators

Logical operators can be used in the condition section of if statements to make more
complex conditions. Logical operators are shown in Table 3.2.

Table 3.2 Logical operators


Operator Description
&& Called Logical AND operator. If both the operands are non-zero, then the condition
becomes true
|| Called Logical OR Operator. If any of the two operands is non-zero, then the
condition becomes true
! Called Logical NOT Operator. It is used to reverse the logical state of its operand. If a
condition is true, then Logical NOT operator will make it false
44 3 Conditional Statements

Let’s study an example. The following code detects whether an entered number
is in the (3, 5] or [7,9) intervals. Sample output of this code is shown in Fig. 3.5.
#define _CRT_SECURE_NO_WARNINGS // put this line otherwise
// the scanf command doesn't work
#include <stdio.h>

int main(){
float num1;
printf("please enter a number:");
scanf("%f", &num1);

if ((num1 > 3 && num1 <= 5) || (num1 >= 7 && num1 < 9))
printf("it is in the allowed list...");
else
printf("it is NOT in the allowed list...");

return 0;
}

Fig. 3.5 Output of


the code

3.6 Nested if Statements

Nested if in C programming is placing if statement inside another if statement.


Nested if is helpful if you want to check the condition inside a condition.
Let’s study an example. The following code takes a number from the user and
determines whether it is positive, negative, or zero. Sample output of this code is
shown in Fig. 3.6.
#define _CRT_SECURE_NO_WARNINGS // put this line otherwise
// the scanf command doesn't work
#include <stdio.h>
int main() {
int num;
printf("Enter an integer: ");
scanf("%d", &num);

if (num != 0) {
if (num < 0) {
printf("Entered number is negative...");
}else{
printf("Entered number is positive...");
}
}else{
printf("Entered number is zero, neither positive, nor negative!");
}
return 0;
}
3.7 switch-case Statement 45

Fig. 3.6 Output of


the code

Let’s study another example. The following code takes two integer numbers
from the user and compares them with each other. Comparison result is printed with
a suitable message on the screen. Sample output of this code is shown in Fig. 3.7.
#define _CRT_SECURE_NO_WARNINGS // put this line otherwise
// the scanf command doesn't work
#include <stdio.h>

int main()
{
int a,b;
printf("Enter two integer values: ");
scanf("%d %d", &a,&b);

if (a >= b) {
if (a == b) {
printf("These values are equal to each other.");
} else {
printf("%d>%d", a, b);
}
} else {
printf("%d<%d", a, b);
}

return 0;
}

Fig. 3.7 Output of


the code

3.7 switch-case Statement

The switch-case statement allows you to execute one code block among many alter-
natives. You can do the same thing with the if-else ladder. However, the syntax of
the switch statement is much easier to read and write. The flowchart of switch-­case
statement is shown in Fig. 3.8.
46 3 Conditional Statements

Fig. 3.8 Behavior of switch…case command

Let’s study an example. The following code uses the switch-case statement to
simulate a simple calculator. Sample outputs of this code is shown in Figs. 3.9
and 3.10.
3.7 switch-case Statement 47

#define _CRT_SECURE_NO_WARNINGS // put this line otherwise


// the scanf command doesn't work
#include <stdio.h>

int main(){
char op;
float num1, num2;

printf("please enter an operator (+,-,*,/): ");


scanf("%c", &op);

printf("please enter two numbers: ");


scanf("%f %f", &num1, &num2);

switch (op) {
case '+':
printf("%.2f+%.2f=%.2f",num1,num2, num1 + num2);
break;
case'-':
printf("%.2f-%.2f=%.2f", num1, num2, num1 - num2);
break;

case'*':
printf("%.2f*%.2f=%.2f", num1, num2, num1 * num2);
break;

case'/':
printf("%.2f/%.2f=%.2f", num1, num2, num1 / num2);
break;

default:
printf("Error, operator is not correct!");
}
return 0;
}

Fig. 3.9 Output of


the code

Fig. 3.10 Output of


the code

Let’s study another example. The following code takes an integer number
between 20 and 29 and writes the name of the number. Sample outputs of this code
is shown in Figs. 3.11 and 3.12.
48 3 Conditional Statements

#define _CRT_SECURE_NO_WARNINGS // put this line otherwise


// the scanf command doesn't work
#include <stdio.h>

int main()
{
int num;

printf("Enter an integer from 20 and 29: ");


scanf("%d", &num);

if (num >= 20 && num <= 29) {


switch (num - 20) {
case 0:
printf("twenty");
break;

case 1:
printf("twnety one");
break;
case 2:
printf("twnety two");
break;

case 3:
printf("twnety three");
break;

case 4:
printf("twnety four");
break;

case 5:
printf("twnety five");
break;

case 6:
printf("twnety six");
break;

case 7:
printf("twnety seven");
break;

case 8:
printf("twnety eight");
break;

case 9:
printf("twnety nine");
break;
}
}
else {
printf("Entered value is not in the correct range.");
}
return 0;
}
Further Reading 49

Fig. 3.11 Output of


the code

Fig. 3.12 Output of


the code

Further Reading

1. Deitel P, Deitel H (2022) C how to program: with case studies in applications and systems
programming, 9th edn. Pearson
Chapter 4
Loops

4.1 Introduction

In programming, loops are used to repeat a block of code until the specified condi-
tion is met. C programming has three types of loops:
1. for loop
2. while loop
3. do-while loop
Use the for loop if number of iterations is known. Use while and do-while loop
when the number of iterations is not known: Use do-while if the loop must be run at
least one time.

4.2 for Loop

The syntax of the for loop is:


for (initializationStatement; testExpression; updateStatement)
{
// statements inside the body of loop
}

Let’s see how for loop works. The initialization statement is executed only once.
Then, the test expression is evaluated. If the test expression is evaluated to false, the
for loop is terminated. However, if the test expression is evaluated to true, state-
ments inside the body of the for loop are executed, and the update expression is
updated and again the test expression is evaluated. This process goes on until the
test expression is false. When the test expression is false, the loop terminates. The
flowchart of for loop is shown in Fig. 4.1.

© The Author(s), under exclusive license to Springer Nature Switzerland AG 2023 51


F. Asadi, Essentials of C Programming with Microsoft® Visual Studio®,
https://doi.org/10.1007/978-3-031-35711-4_4
52 4 Loops

Fig. 4.1 For loop


flowchart

Let’s study an example. The following code prints the numbers from 0 to 9.
Output of this code is shown in Fig. 4.2.
#include <stdio.h>

int main()
{
for (int i = 0; i < 10; i++) {
printf("%d\n", i);
}
printf("Program finished.");
return 0;
}
4.2 for Loop 53

Fig. 4.2 Output of the code

The variables defined in the for loop will be destroyed once the for-loop execu-
tion is terminated. For example, the following program does not compile (Fig. 4.3).
#include <stdio.h>

int main()
{
for (int i = 0; i < 10; i++)
{
printf("%d\n", i);
}
printf("value of i after loop termination is: %d.", i);//variable i is destroyed.
//there is no access to it
//at this point of the code
return 0;
}

Fig. 4.3 Error List window

The variables defined outside the for loop will not be destroyed when the for-­
loop execution is finished. For instance, in the following code, the variable i is
accessible after loop execution is finished. Output of this code is shown in Fig. 4.4.
54 4 Loops

#include <stdio.h>

int main()
{
int i;
for (i = 0; i < 10; i++) {
printf("%d\n", i);
}
printf("\nvalue of i after loop termination is: %d.",i);
return 0;
}

Fig. 4.4 Output of the code

The previous code can be written as follow as well. Output of following code is
shown in Fig. 4.5.
int main()
{
int i=0;
for (i ; i < 10; i++) {
printf("%d\n", i);
}
printf("\nvalue of i after loop termination is: %d.",i);
return 0;
}
4.2 for Loop 55

Fig. 4.5 Output of the code

Let’s study more examples. The following code prints the even numbers from 0
to 8 on the screen. Output of this code is shown in Fig. 4.6.

#include <stdio.h>

int main()
{
for (int i = 0; i < 10; i=i+2) {
printf("%d\n",i);
}

return 0;
}

Fig. 4.6 Output of


the code

The following code prints the multiplication table. Output of this code is shown
in Fig. 4.7.

#include <stdio.h>

int main()
{
for (int i = 1; i < 10; i++) {
for (int j=1; j<10; j++){
printf("%d\t", i*j);
if (j == 9) printf("\n");
}
}
return 0;
}
56 4 Loops

Fig. 4.7 Output of the code

The following code draws the right triangle shown in Fig. 4.8.
#include <stdio.h>

int main()
{
for (int i = 0; i < 10; i++) {
for (int j = 0; j < i; j++) {
printf("*");
}
printf("\n");
}
}

Fig. 4.8 Output of the code


4.2 for Loop 57

The following code draws the triangle shown in Fig. 4.9.


#include <stdio.h>

int main()
{
int N = 6; //N-1 gives the number of rows

int i, j, k;
for (i = 1; i <= N; i++)
{
for (j = N; j > i; j--)
{
printf(" ");
}
for (k = 1; k < i; k++)
{
printf("* ");
}
printf("\n");
}
return 0;
}

Fig. 4.9 Output of the code

The following code calculates the factorial of value entered to variable n. Output
of this code is shown in Fig. 4.10.
#include <stdio.h>

int main()
{
int n = 5;

int product = 1;
for (int i = 1; i <= n; i++)
product *= i;
printf("%d!=%d\n\n", n, product);

return 0;
}
58 4 Loops

Fig. 4.10 Output of


the code

Let’s change the above code to print the factorial of numbers from 1 to 20. The
following code uses the nested for loops to calculate the factorial of numbers from
1 to 20. Output of this code is shown in Fig. 4.11. The correct values of factorials
are shown in the right side of Fig. 4.11. Therefore, the code gave correct results.
#include <stdio.h>

int main()
{
long long product;

for (int i = 1; i <= 20; i++)


{
product = 1;
for (int j = 1; j <= i; j++)
product *= j;
printf("%d!=%lld\n\n", i, product);
}

return 0;
}
4.2 for Loop 59

Fig. 4.11 Output of the code and correct values of factorial

The previous code can be written as follows as well. Output of this code is shown
in Fig. 4.12. You can compare the outputs with the correct values shown in Fig. 4.11
to ensure that the code works correctly.
#include <stdio.h>

int main()
{
__int64 product; //__int64 is the same as long long

for (int i = 1; i <= 20; i++)


{
product = 1;
for (int j = 1; j <= i; j++)
product *= j;
printf("%d!=%lld\n\n", i, product);
}
return 0;
}
60 4 Loops

Fig. 4.12 Output of the code


4.2 for Loop 61

Note that you will obtain a wrong result if you use the int type. In the below code,
product is defined as integer. Output of this code is shown in Fig. 4.13. Note that
starting from 13! outputs are wrong. The reason is the quick overflow of integer
variable.
int main()
{
int product; //variable product is defined as int

for (int i = 1; i <= 20; i++)


{
product = 1;
for (int j = 1; j <= i; j++)
product *= j;
printf("%d!=%d\n\n", i, product);
}

return 0;
}
62 4 Loops

Fig. 4.13 Output of the code


4.2 for Loop 63

The following code extracts the factors of a number. Output of this code is shown
in Fig. 4.14.

#define _CRT_SECURE_NO_WARNINGS // put this line otherwise


// the scanf command doesn't work
#include <stdio.h>

int main()
{
int number;
printf("please enter a number: ");
scanf("%d", &number);
printf("factors of entered number are:\n");
for (int i = 1; i <= number/2; i++) {
if (number % i == 0) {
printf("%d\n", i);
}
}

return 0;
}

Fig. 4.14 Output of the code

In the following code, a delay is made with a loop which counts from 1 to
1,000,000,000. The time.h library is used to measure the generated delay. Output of
this code is shown in Fig. 4.15.
64 4 Loops

#include <stdio.h>
#include <time.h>
#define limit 1000000000

int main()
{
clock_t start = clock();
for (int i = 1; i <= limit; i++) {};
clock_t end = clock();

printf("Number of clock pulses: %ld", (long)(end - start));


float t = (float)(end - start) / CLOCKS_PER_SEC;
printf("\nTime (sec): %.2f", t);

return 0;
}

Fig. 4.15 Output of the code

4.3 break Command

The break statement in C programming has the following two usages:


1. When a break statement is encountered inside a loop (that is, for loop, do-­
while loop, or while loop), the loop is immediately terminated and the pro-
gram control resumes at the next statement following the loop.
2. It can be used to terminate a case in the switch statement (Chap. 3).
Let’s study an example. The following code prints the numbers from 0 to 4. We
asked the for loop to stop when i reaches at least 5. Therefore, as soon as i reached
5, the loop is terminated. Output of this code is shown in Fig. 4.16.
#define _CRT_SECURE_NO_WARNINGS

#include <stdio.h>

int main()
{
for (int i = 0; i < 10; i++) {
if (i >=5) break;
printf("%d\n", i);
}
printf("first command after the for loop");
return 0;
}
4.4 continue Command 65

Fig. 4.16 Output of the code

4.4 continue Command

The continue statement works somewhat like the break statement. Instead of forcing
termination, it forces the next iteration of the loop to take place, skipping any code
in between.
For the for loop, continue statement causes the conditional test and increment
portions of the loop to execute. For the while and do-while loops, continue
statement causes the program control to pass to the conditional tests.
Let’s study an example. The following code uses the continue statement to avoid
printing the even numbers on the screen. Output of this code is shown in Fig. 4.17.
#define _CRT_SECURE_NO_WARNINGS

#include <stdio.h>

int main()
{
for (int i = 0; i < 10; i++) {
if (i % 2 == 0) continue;
printf("%d\n", i);
}
return 0;
}

Fig. 4.17 Output of the code


66 4 Loops

4.5 while Loop

The syntax of the while loop is:


while (testExpression) {
// the body of the loop
}

The while loop evaluates the testExpression inside the parentheses. If testEx-
pression is true, statements inside the body of while loop are executed. Then, tes-
tExpression is evaluated again. The process goes on until testExpression is evaluated
to false. If testExpression is false, the loop terminates (ends).
The flowchart of while loop is shown in Fig. 4.18.

Fig. 4.18. Flowchart of


while loop

Let’s study an example. The following code draws a reverse right triangle.
Sample output of this code is shown in Fig. 4.19.
#define _CRT_SECURE_NO_WARNINGS // put this line otherwise
// the scanf command doesn't work
#include <stdio.h>

int main()
{
int n;
printf("please enter the number of lines: ");
scanf("%d", &n);
while (n>=0) {
for (int i = 0; i < n; i++)
printf("*");
printf("\n");
n--;
}

return 0;
}
4.6 Infinite Loop 67

Fig. 4.19 Output of the code

4.6 Infinite Loop

An infinite loop is a looping construct that does not terminate the loop and executes
the loop forever. It is also called an indefinite loop or an endless loop. It either pro-
duces a continuous output or no output.
For instance, in the following code, value of a is set to ten and its value did not
change at all. Therefore, the condition of while is always true and commands inside
the {} are executed forever. The output of this code is shown in Fig. 4.20. Press the
Ctrl+Pause to stop counting.
#include <stdio.h>

int main()
{
int a = 10;
int b = 0;

while (a>5)
{
b++;
printf("%d",b);
}
return 0;
}
68 4 Loops

Fig. 4.20 Output of the code

The following is a digital clock code. In this code, an infinite loop is used to print
the time each 1 second. After running the code you need to enter the current time
(Fig. 4.21). It starts to show the time after entering the current time (Fig. 4.22).
4.6 Infinite Loop 69

#define _CRT_SECURE_NO_WARNINGS

#include <stdio.h>
#include <Windows.h>

int main()
{
int hour, minute, second;
printf("Please enter the hour: ");
scanf("%d", &hour);
printf("Please enter the minute: ");
scanf("%d", &minute);
printf("Please enter the second: ");
scanf("%d", &second);

while (1) //the while loop runs for ever


{
system("cls"); //clear the screen
printf("Clock: %02d:%02d:%02d", hour,minute, second);
Sleep(1000); //waits for 1 second

second++;
if (second >= 60) {
minute++;
second = 0;
}
if (minute >= 60) {
hour++;
minute = 0;
}
if (hour >= 24) {
hour = 0;
}
}
return 0;
}

Fig. 4.21 Output of


the code

Fig. 4.22 Output of


the code
70 4 Loops

4.7 do-while Loop

The do-while loop is similar to the while loop with one important difference. The
body of do-while loop is executed at least once. Only then, the test expression is
evaluated. The syntax of the do-while loop is:
do
{
// the body of the loop
} while (testExpression);

The body of do-while loop is executed once. Only then, the testExpression is
evaluated. If the testExpression is true, the body of the loop is executed again and
testExpression is evaluated once more. This process goes on until testExpression
becomes false. If testExpression is false, the loop ends. Flowchart of do-while loop
is shown in Fig. 4.23.

Fig. 4.23 Flowchart of


do-while loop

The following code takes a number from the user and prints the number of digits.
Sample output of this code is shown in Fig. 4.24.
#define _CRT_SECURE_NO_WARNINGS // put this line otherwise
// the scanf command doesn't work
#include <stdio.h>

int main()
{
int n, count=0;
printf("please enter a number: ");
scanf("%d", &n);

do {
n = n / 10;
++count;
} while (n != 0);

printf("\nEntered number has %d digits.", count);


return 0;
}
4.7 do-while Loop 71

Fig. 4.24 Output of


the code

Let’s study another example. The following code takes some numbers from the
user. Once zero is entered, the program stops getting more numbers and calculates
sum and average of entered numbers. Sample output of this code is shown in
Fig. 4.25.
#define _CRT_SECURE_NO_WARNINGS // put this line otherwise
// the scanf command doesn't work
#include <stdio.h>

int main()
{
float number, sum=0.0, average=0.0;
int n = 0;

do {
n = n + 1;// you can write it is as n++;
printf("please enter a number: ");
scanf("%f", &number);
sum = sum + number; //you can write it as number+=sum;
} while (number !=0.0);

printf("\n\nNumber of entered numbers: %d\n", n-1);


printf("sum of entered values: %f\n", sum);
printf("average= %.2f\n", (float)sum / (n - 1));
return 0;
}

Fig. 4.25 Output of the code


72 4 Loops

Let’s study some more examples. The following code takes some numbers from
the user and returns the maximum of entered values. This code stops taking new
numbers when the user enters zero. Sample output of this code is shown in Fig. 4.26.
#define _CRT_SECURE_NO_WARNINGS // put this line otherwise
// the scanf command doesn't work
#include <stdio.h>

int main()
{
float number, max=0.0;

do {
printf("please enter a number: ");
scanf("%f", &number);
if (number > max) max = number;
} while (number != 0.0);

printf("Max= %.2f\n", max);


return 0;
}

Fig. 4.26 Output of the code

The following code returns the minimum of entered values. Sample output of
this code is shown in Fig. 4.27.
#define _CRT_SECURE_NO_WARNINGS // put this line otherwise
// the scanf command doesn't work
#include <stdio.h>

int main()
{
float number, min;

printf("please enter a number: ");


scanf("%f", &number);
min = number;

do {
printf("please enter a number: ");
scanf("%f", &number);
if (number != 0.0 && number < min) min = number;
} while (number != 0.0);

printf("Min= %.2f\n", min);


return 0;
}
4.7 do-while Loop 73

Fig. 4.27 Output of the code

The following code is a simple guess game. In this code, the computer selects a
random integer number from 1 to 10 and the user needs to guess the computer’s
number with minimum trials. Here, the do-while loop continues until the user num-
ber equals the computer number. Sample output of this code is shown in Fig. 4.28.
#define _CRT_SECURE_NO_WARNINGS // put this line otherwise
// the scanf command doesn't work
#define _CRT_RAND_S

#include <stdio.h>
#include <stdlib.h>

int main() {
unsigned int number;

//following three line generates a random integre number in the [1,maximum]


range
double maximum = 10.0;
rand_s(&number);
int selectedNumber = (unsigned
int)((double)number/((double)UINT_MAX+1)*maximum)+1;

int userGuess;
int n = 0;

do {
n++;
printf("Enter your guess(1..10):");
scanf("%d",&userGuess);

if (userGuess > selectedNumber) {


printf("Your guess is bigger than selected number");
}

if (userGuess < selectedNumber) {


printf("Your guess is smaller than selected number");
}

if (userGuess == selectedNumber) {
printf("You winned after %d trial.",n);
}
} while (userGuess != selectedNumber);

return 0;
}
74 4 Loops

Fig. 4.28 Output of the code

Further Reading

1. Deitel P, Deitel H (2022) C how to program: with case studies in applications and systems
programming, 9th edn. Pearson
Chapter 5
Arrays

5.1 Introduction

An array is defined as the collection of similar type of data items stored at contigu-
ous memory locations. Arrays are the derived data type in C programming language
which can store the primitive type of data such as int, char, double, float, etc. It also
has the capability to store the collection of derived data types, such as pointers,
structure, etc. The array is the simplest data structure where each data element can
be randomly accessed by using its index number.
C array is beneficial if you have to store similar elements. For example, if we
want to store the marks of a student in six subjects, then we do not need to define
different variables for the marks in the different subject. Instead, we can define an
array which can store the marks in each subject at the contiguous memory locations.
By using the array, we can access the elements easily. Only a few lines of code
are required to access the elements of the array.

5.2 Defining an Array

To create an array, define the data type (like int) and specify the name of the array
followed by square brackets []. For instance, double myArray[7] makes an array
with myArray name and it can store seven double values.
An array with four elements is shown in Fig. 5.1. Note that the first element of
the array has index of zero.

© The Author(s), under exclusive license to Springer Nature Switzerland AG 2023 75


F. Asadi, Essentials of C Programming with Microsoft® Visual Studio®,
https://doi.org/10.1007/978-3-031-35711-4_5
76 5 Arrays

Fig. 5.1 An array with


four elemens

Let’s study an example. The following code defines array a to store five integer
elements. Array a is initialized with 1, 2, 3, 4 and 5 values. Array b can store five
integers but it is not initialized. Output of this code is shown in Fig. 5.2.
#include <stdio.h>

int main()
{
int a[5] = { 1,2,3,4,5 };
printf("value of a[0]=%d\n", a[0]);
printf("value of a[1]=%d\n", a[1]);
printf("value of a[2]=%d\n", a[2]);
printf("value of a[3]=%d\n", a[3]);
printf("value of a[4]=%d\n", a[4]);
int b[5];

return 0;
}

Fig. 5.2 Output of the code

You are not forced to write the number of elements when an array is initialized
(when an array is not initialized you need to determine the number of elements
inside the brackets). For instance, the previous code can be written as follows:
#include <stdio.h>

int main()
{
int a[] = { 1,2,3,4,5 };
printf("value of a[0]=%d\n", a[0]);
printf("value of a[1]=%d\n", a[1]);
printf("value of a[2]=%d\n", a[2]);
printf("value of a[3]=%d\n", a[3]);
printf("value of a[4]=%d\n", a[4]);

int b[5];

return 0;
}
5.3 Arrays and Pointers 77

Let’s study another example. In the following code, five numbers are taken from
the user, stored in an array and then printed in the reverse order, i.e., from the last
one to the first one. Sample output of this code is shown in Fig. 5.3.
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>

int main()
{
int number[5];

for (int i = 0; i < 5; i++)


{
printf("please enter number%d: ", i);
scanf("%d", &number[i]);
}

for (int i = 4; i >=0; i--)


{
printf("%d ", number[i]);
}
return 0;
}

Fig. 5.3 Output of the code

5.3 Arrays and Pointers

As shown in Fig. 5.4, name of an array is a pointer to the first element of the array
(pointers are studied in Chap. 8). Let’s study an example.

Fig. 5.4 Name of the


array is a pointer to the
first element of the array
78 5 Arrays

In the following code, an array with name a is defined. Output of this code is
shown in Fig. 5.5 (address shown on your computer may be different). Note that a
and &a[0] are the same. It is because the array name points to the first element of
the array.
#include <stdio.h>

int main()
{
int a[] = { 1,2,3,4,5 };

printf("a= %p\n", a);


printf("address of a[0]= %p\n\n", &a[0]);
return 0;
}

Fig. 5.5 Output of


the code

Note that &x[0] is equivalent to x and x[0] is equivalent to *x. &x[1] is equiva-
lent to x+1 and x[1] is equivalent to *(x+1). &x[2] is equivalent to x+2 and x[2] is
equivalent to *(x+2), etc. Basically, &x[i] is equivalent to x+i and x[i] is equivalent
to *(x+i).
Let’s study another example. Consider the following code:

#include <stdio.h>

int main() {
int a[] = { 7,1,3,9,0,2,4,5,8,6 };
int* b;
printf("initial value of a[1]= %d", a[1]);

b = a;
b[1] = 60;

printf("\nnow a[1]= %d", a[1]);

printf("\nb[6]=%d a[6]=%d", b[6], a[6]);


return 0;
}

In the above code, array a with ten integer elements and pointer b are defined
(Fig. 5.6). The b=a forces the pointer b to point to first element of the array a
(Fig. 5.7). Therefore, after the b=a line, the values stored in the array a can be
manipulated by using the pointer b. Output of this code is shown in Fig. 5.8.
5.4 Length of an Array 79

a[0] a[1] a[2] a[3] --- a[9]

Fig. 5.6 Array a and pointer b

a[0] a[1] a[2] a[3] --- a[9]

Fig. 5.7 a and b points to the same memory location

Fig. 5.8 Output of


the code

5.4 Length of an Array

You can count the number of elements in an array, i.e., length of an array, with the
aid of sizeof operator. The following code shows how to do so. Output of this code
is shown in Fig. 5.9.

#include <stdio.h>

int main()
{
int array[] = { 1,2,3,4,5,6,7,8,9,10};

int length = sizeof(array) / sizeof(array[0]);

for (int i = 0; i<length; i++)


{
printf("%d", array[i]);
if (i !=length-1) printf(",");
}

return 0;
}

Fig. 5.9 Output of


the code
80 5 Arrays

5.5 Removing an Element from the Array

The following code shows how to remove an element from an array. After removing
the requested element −1 is added to the end of the array. In this code, a function is
defined to remove the element. User defined functions are studied in Chap. 6
(Fig. 5.10).
#include <stdio.h>

void deleteIndex(int array[], int lengthOfArray, int delete_index);

int main()
{
int array[] = { 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14 };
int N = sizeof(array) / sizeof(array[0]);

printf("Original array:\n");
for (int i = 0; i < N; i++)
printf("%d ", array[i]);

deleteIndex(array, N, 3); //removes a[3] from the array


printf("\n\nArray after removing\n");
for (int i = 0; i < N; i++)
printf("%d ", array[i]);

return 0;
}

void deleteIndex(int array[], int lengthOfArray, int delete_index)


{
//if you want to remove the last element of the array
if (delete_index == (lengthOfArray - 1))
{
array[lengthOfArray - 1] = -1;
return; //function finshes and next for loop is not evaluated
}

//if you want to remove an element from middle of the array


for (int i = delete_index; i <lengthOfArray; i++)
{
if (i != (lengthOfArray - 1))
array[i] = array[i + 1];
else
array[i] = -1;
}
}

Fig. 5.10 Output of the code


5.6 2D Arrays 81

5.6 2D Arrays

One dimensional arrays are studied in the previous sections of this chapter. Two-­
dimensional arrays can be defined in C as well. A two-dimensional array with three
rows and four columns is shown in Fig. 5.11.

Column Column Column Column


1 2 3 4

Row 1 x[0] [0] x[0] [1] x[0] [2] x[0] [3]

Row 2 x[1] [0] x[1] [1] x[1] [2] x[1] [3]

Row 3 x[2] [0] x[2] [1] x[2] [2] x[2] [3]

Fig. 5.11 2D array with three rows and four columns

Let’s study an example. The following code defines a two-dimensional array


with two rows and three columns, initializes it, and then prints the values stored in
two specific indexes. Output of this code is shown in Fig. 5.12.
#include <stdio.h>

int main()
{
// |1 3 5|
//array= | |
// |2 4 6|
int array[2][3] = { {1,3,5},{2,4,6} };

printf("array[0][1]=%d\n", array[0][1]);
printf("array[1][2]=%d\n", array[1][2]);
return 0;
}

Fig. 5.12 Output of the code


82 5 Arrays

Let’s study another example. The following code prints the multiplication table
on the screen. It stores the multiplication table in a 9 by 9 array and then prints the
content of the array using a nested for loop. Output of this code is shown in Fig. 5.13.
#include <stdio.h>

int main()
{
int array[9][9];

const int numberOfRows = 9;


const int numberOfColumns = 9;
for (int i = 0; i < numberOfRows; i++) {
for (int j = 0; j < numberOfColumns; j++) {
array[i][j]=(i+1)*(j+1);
}
}

for (int i = 0; i < numberOfRows; i++) {


for (int j = 0; j < numberOfColumns; j++) {
printf("%d\t", array[i][j]);
}
printf("\n");
}

return 0;
}

Fig. 5.13 Output of the code

1 3 5 
Let’s study another example. The following code multiplies mat1=  
6 6 2 8 7 4 2 
with mat2= 1 3 4 4  and prints the obtained result on the screen. Output of this
7 5 6 2 
code is shown in Fig. 5.14.
5.7 Size of 2D Arrays 83

#include <stdio.h>

int main()
{
// this code calculates the matrix product of mat1 and mat2;
// i.e., prod=mat1*mat2
// product is a 2X4 matrix
int mat1[2][3] = { {1,3,5},{7,4,2} };
int mat2[3][4] = { {6,6,2,8},{1,3,4,4},{7,5,6,2}};
int prod[2][4] = { {0,0,0,0},{0,0,0,0} };

// Multiply two matrices and saves the result in prod array


for (int i = 0; i < 2; i++) {
for (int j = 0; j < 4; j++) {
for (int k = 0; k < 3; k++) {
prod[i][j] = prod[i][j] + mat1[i][k] * mat2[k][j];
}
}
}

// prints the result (prod array) on the screen


for (int i = 0; i < 2; i++) {
for (int j = 0; j < 4; j++) {
printf("%d\t",prod[i][j]);
}
printf("\n");
}

return 0;
}

Fig. 5.14 Output of the code

5.7 Size of 2D Arrays

The size of operator can be used to obtain the number of rows and columns a 2D
array has. Let’s study an example. The following code shows how sizeof operator
can be used to determine the number of rows and columns an array has. It uses two
nested for loops to print the content of the 2D array as well. Output of this code is
shown in Fig. 5.15.
84 5 Arrays

#include <stdio.h>

int main()
{
// |1 3 5|
//array= | |
// |2 4 6|
int array[2][3] = { {1,3,5},{2,4,6} };

int numberOfRows = sizeof array / sizeof array[0];


int numberOfColumns = sizeof array[0] / sizeof array[0][0];

printf("Number of rows: %d\n", numberOfRows);


printf("Number of columns: %d\n", numberOfColumns);

printf("array=\n");
for (int i = 0; i < numberOfRows; i++) {
for (int j = 0; j < numberOfColumns; j++) {
printf("%d ", array[i][j]);
}
printf("\n");
}

return 0;
}

Fig. 5.15 Output of the code

5.8 malloc Function

The size of the arrays defined in the previous sections is constant and the compiler
knows how much each array require space on the stack memory. In C programming,
you can define arrays with variable size as well.
The malloc function can be used to allocate the specified number of bytes. The
allocated memory is always on the heap memory. Prototype of malloc function is:
void *malloc(size_t size). It takes the size of the memory block in bytes and return
a pointer to the allocated memory or NULL if the request fails (pointers are studied
in Chap. 8).
Note that the allocated memory must be released before ending the program. The
memory allocated by malloc (or calloc) can be deallocated by calling the free
function. Prototype of free function is void free(void *ptr). The free function takes
the pointer to a memory block previously allocated with malloc (or calloc).
5.8 malloc Function 85

Let’s study an example. In the following code, length of an integer array is asked
at the runtime, then an array with the entered length is made on the heap and filled
with the values entered by the user. Sample output of this code are shown in
Fig. 5.16.
#define _CRT_SECURE_NO_WARNINGS

#include <stdio.h>
#include <stdlib.h> //malloc is defined here.
//add stdlib when you want to use malloc

int main()
{
printf("please enter the length of array: ");
int N=0;
scanf("%d", &N);

int* myArray=malloc(N*sizeof(int)); //making the array of N integers

for (int i = 0; i < N; i++)


{
printf("array[%d]= ", i);
scanf("%d", &myArray[i]);
printf("\n");
}

printf("array entered by you is: ");


for (int i = 0; i < N; i++)
printf("%d ", myArray[i]);

free(myArray);
return 0;
}

Fig. 5.16 Output of the code

Let’s study another example. The following code generates a password with the
length determined by the user at the runtime. This code uses the rand function
(Chap. 10). Sample output of this code is shown in Fig. 5.17.
86 5 Arrays

#define _CRT_SECURE_NO_WARNINGS

#include <stdio.h>
#include <stdlib.h>
#include <string.h> //The strlen function is defined here.
#include <time.h>

int main()
{
int length;
printf("Enter the desired length for the password: ");
scanf("%d", &length);

char* password = malloc((length + 1)*sizeof(char)); //return a pointer to the


password array

char* digits = "0123456789";


int digits_length = strlen(digits);

char* lowers = "abcdefghijklmnopqrstuvwxyz";


int lowers_length = strlen(lowers);

char* uppers = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";


int uppers_length = strlen(uppers);

char* symbols = "!@#^&/()?*";


int symbols_length = strlen(symbols);

srand(time(NULL));//seeds the random number generator used by the function rand

for (int i = 0; i < length; i++)


{
int char_type = rand() % 4; //select one of the above 4 categories:
// digits, lower case
alphabet,
// upper case alphabet
and symbols

switch (char_type)
{
case 0:
password[i] = digits[rand() % digits_length];
break;
case 1:
password[i] = lowers[rand() % lowers_length];
break;
case 2:
password[i] = uppers[rand() % uppers_length];
break;
case 3:
password[i] = symbols[rand() % symbols_length];
break;
}

}
password[length] = '\0'; //makes the last character NULL character
printf("Generated password: %s\n", password);

free(password);
return 0;
}
5.9 calloc Function 87

Fig. 5.17 Output of the code

5.9 calloc Function

Similar to malloc function, the calloc function can be used for dynamic memory
allocation purposes (dynamic memory allocation can be defined as a procedure in
which the size of a data structure, like an array, is changed during the runtime).
However, following differences exists between malloc and calloc:
(a) malloc takes a single argument (the amount of memory to allocate in bytes),
while calloc takes two arguments: the number of elements and the size of each
element.
(b) malloc only allocates memory, while calloc allocates and sets the bytes in the
allocated region to zero.
Let’s study an example. In the following code, the length of an integer array is
asked at the runtime, then an array with the entered length is made on the heap and
initialized with zero. The initialized values are replaced with the values entered by
the user. Sample output of this code are shown in Fig. 5.18.
#define _CRT_SECURE_NO_WARNINGS

#include <stdio.h>
#include <stdlib.h> //calloc is defined here.
//add stdlib when you want to use calloc

int main()
{
printf("please enter the length of array: ");
int N=0;
scanf("%d", &N);
int * myArray;
myArray=( int *) calloc(N , sizeof (int )); //making the array

for (int i = 0; i < N; i++)


{
printf( "array[%d]= " , i);
scanf( "%d" , &myArray[i]);
printf( "\n" );
}

printf( "array entered by you is:" );


for (int i = 0; i < N; i++)
printf("%d " , myArray[i]);

free(myArray);
return 0;
}
88 5 Arrays

Fig. 5.18 Output of the code

Further Reading

1. Deitel P, Deitel H (2022) C how to program: with case studies in applications and systems
programming, 9th edn. Pearson
Chapter 6
Functions

6.1 Introduction

A function is a group of statements that together perform a task. Every C program


has at least one main function, and all the most trivial programs can define addi-
tional functions.
You can divide up your code into separate functions. How you divide up your
code among different functions is up to you, but logically the division is such that
each function performs a specific task.
A function declaration tells the compiler about a function’s name, return type,
and parameters. A function definition provides the actual body of the function.
The C standard library provides numerous built-in functions that your program
can call. For example, strcat to link two strings, memcpy to copy one memory loca-
tion to another location, and many more functions.
This chapter studies the functions.

6.2 Definition of a Function

The general form of a function definition in C programming language is as follows:

return_type function_name(parameterList)
{
body of the function
}

© The Author(s), under exclusive license to Springer Nature Switzerland AG 2023 89


F. Asadi, Essentials of C Programming with Microsoft® Visual Studio®,
https://doi.org/10.1007/978-3-031-35711-4_6
90 6 Functions

A function definition in C programming consists of a function header and a func-


tion body. Here are all the parts of a function:
Return type: A function may return a value. The return_type is the data type of the
value the function returns. Some functions perform the desired operations with-
out returning a value. In this case, the return_type is the keyword void.
Function name: This is the actual name of the function. The function name and the
parameter list together constitute the function signature.
Parameters: A parameter is like a placeholder. When a function is invoked, you pass
a value to the parameter. This value is referred to as actual parameter or argu-
ment. The parameter list refers to the type, order, and number of the parameters
of a function. Parameters are optional; that is, a function may contain no
parameters.
Function body: The function body contains a collection of statements that define
what the function does.
Let’s study an example. Function add in the following code adds two numbers
together. Output of this code is shown in Fig. 6.1.

#include <stdio.h>

int add(int x, int y); //declaration of the function add

int main()
{
printf("add(7,5)=%d\n", add(7,5));

return 0;
}
//function definition is given below:
int add(int x, int y) {
int result = x + y;
return result;
}

Fig. 6.1 Output of the code


6.2 Definition of a Function 91

There is no need to function declaration when the function definition is above the
main function. Following is an example. Output of this code is shown in Fig. 6.2.

#include <stdio.h>

//function definition:
int add(int x, int y) {
int result = x + y;
return result;
}

int main()
{
printf("add(7,5)=%d\n", add(7, 5));

return 0;
}

Fig. 6.2 Output of the code

The return command is the last command that is run in a function. For instance,
in the following code “end of function” expression is not printed on the screen
(Fig. 6.3).

#include <stdio.h>

int add(int x, int y);

int main()
{
printf("add(7,5)=%d\n", add(7, 5));

return 0;
}

int add(int x, int y) {


int result = x + y;
return result;
printf("end of function...");
}
92 6 Functions

Fig. 6.3 Output of the code

In the following code, implicit type casting is applied to the arguments. Output
of this code is shown in Fig. 6.4.
#include <stdio.h>

int add(int x, int y);

int main()
{
printf("add(7.6,5.4)=%d\n", add(7.6, 5.4));

return 0;
}

int add(int x, int y) {


int result = x + y;
return result;
}

Fig. 6.4 Output of the code

6.3 Pass by Value

In pass by value, the function parameters get the copy of actual parameters which
means changes made in function parameters did not reflect in actual parameters.
The following code helps understand the nature of pass by value. Note that the value
of variables a and b did not change after calling the function. Output of this code is
shown in Fig. 6.5.
6.3 Pass by Value 93

#include <stdio.h>

int add(int x, int y);

int main()
{
int a = 7;
int b = 5;

printf("value of variable a before calling the add function=%d\n", a);


printf("value of variable b before calling the add function=%d\n", b);

printf("add(a,b)=%d\n", add(a,b));

printf("value of variable a after calling the add function=%d\n", a);


printf("value of variable b after calling the add function=%d\n", b);
return 0;
}

int add(int x, int y) {


printf("\n---\nfunction is running...\n");
int result = x + y;
x = x + 1;
y = y + 1;
printf("Value of x=%d\n",x);
printf("Value of y=%d\n", y);
printf("End of function...\n---\n");
return result;

Fig. 6.5 Output of the code


94 6 Functions

6.4 List of Functions

Consider the following code. This function contains three functions: main, mult,
and add. Output of this code is shown in Fig. 6.6.
#include <stdio.h>

int add(int x, int y);


int mult(int x, int y);

int main()
{
printf("mult(7,5)=%d\n", mult(7, 5));

return 0;
}

int add(int x, int y) {


int result = x + y;
return result;
}

int mult(int x, int y) {


int result=0;

for (int i = 0; i < x; i++) {


result = result + y; //you can write it as result += y;
}
return result;
}

Fig. 6.6 Output of the code

You can see the list of functions by clicking the function list (Fig. 6.7). Click on
the desired function to go to its definition or declaration.
6.5 void Functions 95

Fig. 6.7 List of functions inside the main.c file

6.5 void Functions

A void function is a function that does not return any value. An example of a void
function is given below. Output of this function is shown in Fig. 6.8.
#include <stdio.h>

void displayMessage();

int main()
{
displayMessage();

return 0;
}

void displayMessage() {
printf("Function is run");
}
96 6 Functions

Fig. 6.8 Output of the code

void functions do not return any value to their calling function. Therefore, there
is no need to use any return command in the function definition. In void functions,
a return statement can help end the execution of the function, and return the control
to the calling function.
Let’s study an example. Consider the following code. Output of this code is
shown in Fig. 6.9. Note that calling the printNumbers with a negative argument
caused a new line.

#include <stdio.h>

void printNumbers(int n);

int main()
{
printNumbers(10);
printNumbers(-5);
printNumbers(8);

return 0;
}

void printNumbers (int n)


{
for (int i = 0; i < n; i++)
{
printf("%d ", i);
}
printf("\n");
}

Fig. 6.9 Output of the code

Let’s change the code in a way that no new line is generated for negative argu-
ments. Change the code to what is shown below. Now, when a negative value is
passed to printNumbers, the return command is run and execution is stopped and
control is returned to the calling function. Output of this code is shown in Fig. 6.10.
Note that there is no white line at this time.
6.5 void Functions 97

void printNumbers(int n);

int main()
{
printNumbers(10);
printNumbers(-5);
printNumbers(8);

return 0;
}

void printNumbers (int n)


{
if (n < 0) return;
for (int i = 0; i < n; i++)
{
printf("%d ", i);
}
printf("\n");
}

Fig. 6.10 Output of the code

The following code uses the return command to call another void function when
negative values are passed to printNumbers. Output of this code is shown in
Fig. 6.11.
#include <stdio.h>

void printNumbers(int n);


void errorMessage();

int main()
{
printNumbers(10);
printNumbers(-5);
printNumbers(8);

return 0;
}

void printNumbers (int n)


{
if (n < 0) return errorMessage();
for (int i = 0; i < n; i++)
{
printf("%d ", i);
}
printf("\n");
}

void errorMessage()
{
printf("Negative numbers are not acceptable!\n");
}
98 6 Functions

Fig. 6.11 Output of the code

6.6 Scope and Lifetime of Variables

Variables defined inside a function (i.e., variables defined between { and }) are
local. Variables defined inside the function will be destroyed when function execu-
tion is finished.
Let’s study an example. In the following code, variable x is defined inside the
myFunction. Variable x is not accessible inside the main function. If you try to com-
pile the following code, you will receive the error message shown in Fig. 6.12.
#include <stdio.h>

int main() {

myFunction();
printf("value of x=%d", x);
return(0);
}

void myFunction()
{
int x = 0;
printf("Hello! I am myFunction.");
}

Fig. 6.12 Error List window


6.8 Combinations (nCr) Calculator 99

6.7 Function to Convert Fahrenheit to Celsius


5
Fahrenheit can be converted to Celsius using the C   F  32  . The following
9
code can convert Fahrenheit to Celsius. Sample output of this code is shown in
Fig. 6.13.
#define _CRT_SECURE_NO_WARNINGS // put this line otherwise
// the scanf command doesn't work
#include <stdio.h>

float Far2Cel(float Ftemp);

int main()
{
float tempF;
float tempC;
printf("Enter the Fahrenheit value: ");
scanf("%f", &tempF);

tempC = Far2Cel(tempF);
printf("Entered value in Celsius= %.2f",tempC);
return 0;
}

float Far2Cel(float Ftemp){


return ((float)5 / 9) * (Ftemp - 32);;
}

Fig. 6.13 Output of the code

6.8 Combinations (nCr) Calculator


n n!
The following code calculates the nCr     . Sample output of this
code is shown in Fig. 6.14.  r  r !  n  r !
100 6 Functions

#define _CRT_SECURE_NO_WARNINGS // put this line otherwise


// the scanf command doesn't work
#include <stdio.h>

int factorial(int n);

int main()
{
int n, r, nPr;

printf("This code calculates nCr.");


printf("Enter n and r: ");
scanf("%d %d", &n, &r);
printf("%dC%d=%d", n, r, factorial(n) / factorial(n - r) / factorial(r));

return 0;
}

int factorial(int n) {
int product = 1;
for (int i = 1; i <= n; i++) {
product = i * product;
}

return product;
}

Fig. 6.14 Output of the code

6.9 Password Checker

The following code is a password checker program. It ensures that the password
entered to the array p has the conditions written in the first four rows. Output of this
code is shown in Fig. 6.15.
6.10 Heads and Tails 101

// at least 8 characters
// at least 1 uppercase letter
// at least 1 lowercase letter
// at least 1 symbol

#include <stdio.h>
#include <stdbool.h>
#include <string.h>
#include <ctype.h>

bool verify_password(char* s);

int main()
{
char p[] ="Aqws6t % Bn@";
if (verify_password(p))
printf("Verified.");
else
printf("Invalid password!");

return 0;
}

bool verify_password(char* s)
{
int length = strlen(s);
if (length < 8) return false;

bool hasUpperCaseLetter = false;


bool hasLowerCaseLetter = false;
bool hasSymbol = false;

for (int i = 0; i<length; i++)


{
if (islower(s[i])) hasLowerCaseLetter = true;
if (isupper(s[i])) hasUpperCaseLetter = true;
if (ispunct(s[i])) hasSymbol = true;
}

if (hasUpperCaseLetter &&
hasLowerCaseLetter &&
hasSymbol) return true;
}

Fig. 6.15 Output of the code

6.10 Heads and Tails

The following programs generate the heads and tails. Sample output of this code is
shown in Fig. 6.16.
102 6 Functions

#include <stdio.h>
#include <time.h>

typedef enum coin {HEADS, TAILS} coin;

coin flipCoin();

int main()
{
srand(time(NULL));

for (int i = 0; i < 10; i++)


{
if (flipCoin() == HEADS)
printf("HEADS\n");
else
printf("TAILS\n");
}

return 0;
}

coin flipCoin()
{
if (rand() % 2 == 0)
return HEADS;
else
return TAILS;
}

Fig. 6.16 Output of the code

6.11 Cost of a Hotel

The following code is a hotel cost calculator. Hotel rates are given as Saturday 600
$, Sunday 550 $ and other days of the week 400 $. Sample output of the code is
shown in Fig. 6.17.
6.11 Cost of a Hotel 103

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <string.h>
typedef enum Day {
Monday, Tuesday, Wednesday, Thursday,
Friday, Saturday, Sunday
} day;
int costCalc(day d);
day str2day(char s[]);

int main()
{
printf("Day of arrival: ");

char dayOfArrival[10];
scanf("%s", dayOfArrival);
int payment= costCalc(str2day(dayOfArrival));
printf("You need to pay: %d $.", payment);
return 0;
}
int costCalc(day d)
{
switch (d)
{
case Monday:
case Tuesday:
case Wednesday:
case Thursday:
case Friday:
return 400;
break;
case Saturday:
return 600;
break;
case Sunday:
return 550;
break;
}
}
day str2day(char s[])
{
if (!strcmp(s,"Monday") | !strcmp(s,"monday"))
return Monday;

if (!strcmp(s,"Tuesday") | !strcmp(s,"tuesday"))
return Tuesday;

if (!strcmp(s,"Wednesday") | !strcmp(s,"wednesday"))
return Wednesday;
if (!strcmp(s,"Thursday") | !strcmp(s,"thursday"))
return Thursday;

if (!strcmp(s,"Friday") | !strcmp(s,"friday"))
return Friday;

if (!strcmp(s,"Saturday") | !strcmp(s,"saturday"))
return Saturday;
if (!strcmp(s,"Sunday") | !strcmp(s,"sunday"))
return Sunday;
}
104 6 Functions

Fig. 6.17 Output of the code

6.12 Fibonacci Sequence (Iterative Approach)

The Fibonacci sequence is a set of integers (the Fibonacci numbers) that starts with
zero, followed by one, then by another one, and then by a series of steadily increas-
ing numbers. The sequence follows the rule that each number is equal to the sum of
the preceding two numbers. The Fibonacci sequence begins with: 0, 1, 1, 2, 3, 5, 8,
13, 21, 34, 55, 89, 144, 233 ... Each number, starting with the third, adheres to the
prescribed formula. For example, the seventh number, 8, is preceded by 3 and 5,
which add up to 8. The sequence can theoretically continue to infinity, using the
same formula for each new number.
The following is an iterative approach to generate the first n terms of Fibonacci
sequence. Sample output of this code is shown in Fig. 6.18.
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>

int main()
{
int term1 = 0;
int term2 = 1;
int tmp=0;
int fibn = 0;
int n = 0;

printf("please enter the number of terms that you want: ");


scanf("%d", &n);

printf("0, 1,");

for (int i = 2; i < n; i++)


{
printf(" %d,", term1 + term2);
tmp = term1+term2;
term1 = term2;
term2 = tmp;
}

return 0;
}

Fig. 6.18 Output of the code


6.13 Fibonacci Sequence (Recursive Approach) 105

6.13 Fibonacci Sequence (Recursive Approach)

A function that calls itself is known as a recursive function (Fig. 6.19). This tech-
nique is known as recursion. The recursion continues until some condition is met to
prevent it. To prevent infinite recursion, if...else statement (or similar approach) can
be used where one branch makes the recursive call, and the other does not.

Fig. 6.19 Working


principle of recursive
functions

The following code generates the first n terms of Fibonacci sequence using a
recursive approach. Sample output of this code is shown in Fig. 6.20.
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>

int main()
{
int term1 = 0;
int term2 = 1;
int tmp = 0;
int fibn = 0;
int n = 0;

printf("please enter the number of terms that you want: ");


scanf("%d", &n);

for (int i = 0; i < n; i++)


{
printf("%d, ", fib(i));
}

return 0;
}

int fib(int n)
{
if (n > 1) return fib(n - 1) + fib(n - 2); //recursive step
else if (n == 1) return 1;
else if (n == 0) return 0;
}
106 6 Functions

Fig. 6.20 Output of the code

Increase the number of terms and compare the speed of both approaches (itera-
tive and recursive) and see which one is more rapid.

6.14 Recursive Factorial

The following code uses the recursive approach to calculate the factorial. Sample
output of this code is shown in Fig. 6.21.
#define _CRT_SECURE_NO_WARNINGS

#include <stdio.h>
int fact(int n);

int main()
{
int n;
printf("Calculation of n! Please enter n: ");
scanf("%d", &n);

printf("%d!=%d",n,fact(n));
return 0;
}

int fact(int k)
{
if (k != 1) return k * fact(k - 1);
else if (k == 1) return 1;
}

Fig. 6.21 Output of the code


6.16 Recursive Max and Min 107

6.15 Recursive Product

The following code uses the recursive approach to calculate the product of two
numbers (hint: for instance, 5 × 3 = 5 + 5 × 2 = 5 + 5 + 5 × 1 = 5 + 5 + 5). Sample
output of this code is shown in Fig. 6.22.
#define _CRT_SECURE_NO_WARNINGS

#include <stdio.h>

int product(int x, int y);

int main()
{
int x,y;
printf("Please enter two numbers: ");
scanf("%d %d", &x,&y);

printf("%d*%d=%d",x,y,product(x,y));
return 0;
}

int product(int x, int y)


{
if (y != 1) return (x + product(x, y - 1));
if (y == 1) return x;

Fig. 6.22 Output of the code

6.16 Recursive Max and Min

The following code uses a recursive approach to calculate the maximum of a given
array. Sample output of this code is shown in Fig. 6.23.
108 6 Functions

#include <stdio.h>

static int N = 0; //counts the number of max function calls

int max(int array[], int n);

int main()
{
int array[] = {4, 1, 8};
int n = 3;

printf("Max= %d\n", max(array,n));


printf("Number of calls= %d\n", N);

return 0;
}

int max(int array[], int n)


{
N++;
if (n == 1) return array[n-1];

int possible_max = max(array, n - 1);

if (possible_max > array[n - 1]) return possible_max;


else return array[n - 1];
}

Fig. 6.23 Output of the code

The following code uses a recursive approach to calculate the minimum of a


given array. Sample output of this code is shown in Fig. 6.24.
6.17 Static Variables 109

#include <stdio.h>

static int N = 0; //counts the number of min function calls

int min(int array[], int n);

int main()
{
int array[] = { 4, 1, 8 };
int n = 3;

printf("Min= %d\n", min(array, n));


printf("Number of calls= %d\n", N);

return 0;
}

int min(int array[], int n)


{
N++;
if (n == 1) return array[n - 1];

int possible_min = min(array, n - 1);

if (possible_min < array[n - 1]) return possible_min;


else return array[n - 1];
}

Fig. 6.24 Output of the code

6.17 Static Variables

Static variables have a property of preserving their value even after they are out of
their scope! Hence, static variables preserve their previous value in their previous
scope and are not initialized again in the new scope. Note that static variables are
allocated memory in data segment, not stack segment. Static variables should not be
declared inside structure. The reason is C compiler requires the entire structure ele-
ments to be placed together, i.e., memory allocation for structure members should
be contiguous.
A static int variable remains in memory while the program is running. A normal
or auto variable is destroyed when a function call where the variable was declared
is over. For example, we can use static int to count a number of times a function is
called, but an auto variable cannot be used for this purpose.
Let’s study some examples. Following code prints 1 1 1 after three call (Fig. 6.25).
110 6 Functions

#include <stdio.h>

void myFunction();

int main()
{
myFunction();
myFunction();
myFunction();

return 0;
}

void myFunction()
{
int calls = 0;
calls++;
printf("calls: %d\n", calls);
}

Fig. 6.25 Output of the code

However, the following code prints 1 2 3 after three calls (Fig. 6.26). Note that
calls variable is defined as static variable at this time.
#include <stdio.h>

void myFunction();

int main()
{
myFunction();
myFunction();
myFunction();

return 0;
}

void myFunction()
{
static int calls = 0; //initialization only happens in the first run
calls++;
printf("calls: %d\n", calls);
}
6.18 Pass by Reference 111

Fig. 6.26 Output of the code

6.18 Pass by Reference

Pass by value is studied in Sect. 6.3. There is another way to pass a function argu-
ment as well: pass by reference. Pass by reference is studied in this section.
Pass by reference (or more exactly, pass by pointer) means to pass the reference
of an argument in the calling function to the corresponding formal parameter of the
called function. The called function can modify the value of the argument by using
its reference passed in.
The following example shows how arguments are passed by reference. The refer-
ence parameters are initialized with the actual arguments when the function is
called. Output of this function is shown in Fig. 6.27.
#include <stdio.h>

void swap(int* a, int* b);

int main() {
int x = 5;
int y = 10;
printf("before calling the swap function: x=%d y=%d", x, y);
swap(&x, &y);
printf("\nafter calling the swap function : x=%d y=%d", x, y);
return(0);
}

void swap(int* a, int* b)


{
int temp;
temp = *a;
*a = *b;
*b = temp;
}
112 6 Functions

Fig. 6.27 Output of the code

6.19 Passing an Array to a Functions

Arrays can be given to functions as argument. Let’s study an example. In the follow-
ing code, calcSum function calculates the sum of array elements given to it. Output
of this code is shown in Fig. 6.28.
#include <stdio.h>

float calcSum(float numbers[], int length); //pass by reference

int main() {
float num[] = { 23.4, 55, 22.6, 3, 40.5, 18 };

int length = (sizeof(num) / sizeof(num[0]));


printf("Sum of elements of array num= %.2f",calcSum(num,length));

return 0;
}

float calcSum (float numbers[], int length)


{
float sum = 0.0;

for (int i = 0; i < length; i++)


{
sum = sum + numbers[i];
}
return sum;
}

Fig. 6.28 Output of the code

The previous code can be written as follows as well. Output of this code is shown
in Fig. 6.29.
6.19 Passing an Array to a Functions 113

#include <stdio.h>

float calcSum(float* numbers, int length); //Equal to: float calcSum(float numbers[],
int length);

int main() {
float num[] = { 23.4, 55, 22.6, 3, 40.5, 18 };

int length = (sizeof(num) / sizeof(num[0]));


printf("Sum of elements of array num= %.2f", calcSum(num, length));

return 0;
}

float calcSum(float* numbers, int length)


{
float sum = 0.0;

for (int i = 0; i < length; i++)


{
sum = sum + numbers[i];
}
return sum;
}

Let’s study another example. In this example, we want to write a function to


calculate the Standard Deviation of a given array. Note that Standard Deviation
1 N
  xi  x  . x and N show the average and number of data points,
2
formula is
N i 1
respectively.
The following code calculates the Standard Deviation of a given array. Output of
this code is shown in Fig. 6.30.

Fig. 6.29 Output of the code


114 6 Functions

#include <stdio.h>
#include <math.h>

double stdev(double x[], int N);

main(void)
{
double a[] = {9.2, 1.5, 6.7, 8.2, 5.5, 7.1};

printf("standard deviation of array a is: %.2f\n", stdev(a,


sizeof(a)/sizeof(a[0])));
return 0;
}

double stdev(double x[], int N)


{
double mu=0, sum=0;
for (int i = 0; i < N; i++)
sum = sum + x[i];
mu = sum / N;

double numerator = 0;
for (int j = 0; j < N; j++)
numerator = numerator + pow((x[j] - mu), 2);

return sqrt(numerator / N);


}

Fig. 6.30 Output of the code

Let’s study another example. In the following code, string str is reversed. Output
of this code is shown in Fig. 6.31.
6.20 Functions with Variable Number of Arguments 115

#include <stdio.h>
#include <string.h>

void reverse_string(char s[], int length);

int main() {
char str[] = "This is a test message.";

printf("originl string is : %s", str);


reverse_string(str, strlen(str));
printf("\nreversed string is: %s", str);

return 0;
}

void reverse_string(char s[], int length)


{
char tmp[50];
strcpy(tmp,s);

for (int i = 0; i < length; i++)


{
s[i] = tmp[length - 1 - i];
}
s[length] = '\0';
}

Fig. 6.31 Output of the code

6.20 Functions with Variable Number of Arguments

Variadic functions are functions that can take a variable number of arguments. In C
programming, a variadic function adds flexibility to the program. It takes one fixed
argument and then any number of arguments can be passed. The variadic function
consists of at least one fixed variable and then an ellipsis(…) as the last parameter.
Let’s study some examples. myFunction in the following code takes a variable
number of arguments and prints them on the screen. Output of this code is shown in
Fig. 6.32.
116 6 Functions

#include <stdio.h>
#include <stdarg.h> // add this library

void myFunction(int num_args, ...);

int main()
{

myFunction(5, 10, 23, 6, 45, 9); // 5 shows that myFunction


// has 5 arguments.
printf("\n");
myFunction(3, 7, 4, 2); // this function has 3 arguments

return 0;
}

void myFunction(int num_args, ...) //... shows that myFunction takes a variable number
of args.
{
va_list args;

va_start(args, num_args);

for (int i = 0; i < num_args; i++)


{
int x = va_arg(args, int);
printf("%d ", x);
}

va_end(args);

Fig. 6.32 Output of the code

The following code takes some numbers and returns the maximum. Sample out-
put of this code is shown in Fig. 6.33.
6.21 Entering the Functions to Separate Files 117

#include <stdio.h>
#include <stdarg.h>

int max(int num_args, ...);

int main()
{

printf("max(10, 23, 6, 45, 9)= %d\n", max(5, 10, 23, 6, 45, 9));
printf("max(7, 4, 2)= %d\n", max(3, 7, 4, 2));

return 0;
}

int max(int num_args, ...) //maximum function with variable number of args.
{
va_list args;

va_start(args, num_args);

int max = 0;

for (int i = 0; i < num_args; i++)


{
int x = va_arg(args, int);
if (i == 0) max = x;
else if (x > max) max = x;
}

va_end(args);

return max;
}

Fig. 6.33 Output of the code

6.21 Entering the Functions to Separate Files

It is a good idea to write each function in a seperate file. Let’s study an example.
Consider the following code. In this code, all the required functions are placed in
one single file.
118 6 Functions

#include <stdio.h>

int add(int x, int y);


int sub(int x, int y);
int div(int x, int y);

int main()
{
int a =60;
int b = 22;

printf("a=60, b=22\n\n");

printf("a+b=%d \n", add(a, b));


printf("a-b=%d \n", sub(a, b));
printf("a/b=%d \n", div(a, b));
return 0;
}

int add(int x, int y)


{
return x + y;
}

int sub(int x, int y)


{
return x - y;
}

int div(int x, int y)


{
return x / y;
}

Let’s put the used functions in separate files. Right click on the Source Files
(Fig. 6.34) in the Solution Explorer window and select the Add>> New Item
(Fig. 6.35). Click the View> Solution Explorer (Fig. 6.36) if the Solution Explorer
window is not visible.
6.21 Entering the Functions to Separate Files 119

Fig. 6.34 Solution Explorer window

Fig. 6.35 Add> New Item

Fig. 6.36 View> Solution Explorer


120 6 Functions

After clicking the View> Solution Explorer, Add New Item window appears on
the screen. Select the C++ File (.cpp) and make the add.c file (Fig. 6.37). Now, add.c
is added to the Source Files (Fig. 6.38).

Fig. 6.37 Add New Item window

Fig. 6.38 Solution Explorer window


6.21 Entering the Functions to Separate Files 121

Double click the add.c file in the Solution Explorer window and write the code
for add function (Fig. 6.39).

Fig. 6.39 add.c

Add the other required functions to the Source Files (Fig. 6.40).

Fig. 6.40 Solution Explorer window


122 6 Functions

The code of sub and div functions (Fig. 6.40) are shown below:
//sub.c file
int sub(int x, int y)
{
return x - y;
}

//div.c file
int div(int x, int y)
{
return x / y;
}

Now all the functions are defined in separate files. Double click the main func-
tion and change it to:
#include <stdio.h>

int main()
{
int a =60;
int b = 22;

printf("a=60, b=22\n\n");

printf("a+b=%d \n", add(a, b));


printf("a-b=%d \n", sub(a, b));
printf("a/b=%d \n", div(a, b));
return 0;
}

Output of the previous code is shown in Fig. 6.41.

Fig. 6.41 Output of the code

6.22 extern Keyword

The extern keyword permits you to access variable defined in other files. It is impor-
tant to note that the extern keyword is used to only declare a variable and not define
a variable. Let’s study a simple example.
Further Reading 123

Double click the div.c function (Fig. 6.40) and change it to:
//div.c file
int z=125;

int div(int x, int y)


{
return x / y;
}

Now an integer variable is defined in div.c file. To use the variable z in the main.c
you need to use the extern keyword:
#include <stdio.h>

extern int z;

int main()
{
printf("z=%d", z);

return 0;
}

Fig. 6.42 Output of the code

Output of the previous code is shown in Fig. 6.42.

Further Reading

1. Deitel P, Deitel H (2022) C how to program: with case studies in applications and systems
programming, 9th edn. Pearson, London
Chapter 7
Some Useful Functions

7.1 Introduction

In Visual Studio, you have access to many ready to use functions. This chapter stud-
ies some of these functions.

7.2 Running an .exe File

You can use the system function to run .exe files. For instance, the following code
shows how to run the Adobe® Acrobat Reader®.
#include <stdio.h>
#include <stdlib.h>

int main()
{
// system("C:\\Program Files\\Adobe\\Acrobat DC\\Acrobat\\Acrobat.exe");
// if you get an error for above command see here: https://bit.ly/3GF7nbC

system("\"C:\\Program Files\\Adobe\\Acrobat DC\\Acrobat\\Acrobat.exe\"");


system("pause"); // waits until you press a key

return 0;
}

The following code runs the MS Paint®, Windows® calculator program,


Winword®, Power Point®, Excel®, and Notepad.

© The Author(s), under exclusive license to Springer Nature Switzerland AG 2023 125
F. Asadi, Essentials of C Programming with Microsoft® Visual Studio®,
https://doi.org/10.1007/978-3-031-35711-4_7
126 7 Some Useful Functions

#include <stdio.h>
#include <stdlib.h>

int main()
{

system("cmd /c mspaint"); // opens Ms Paint


system("cmd /c calc"); // opens the calculator
system("cmd /c start winword"); // opens the Ms Word
system("cmd /c start powerpnt"); // opens the Ms Powerpoint
system("cmd /c start excel"); // opens the Ms Excel
system("notepad.exe"); // opend the Notepad

return 0;
}

7.3 Playing a .wav File

The following code shows how to play a .wav file.


// see: https://bit.ly/3GiDLzy for more information

#include <Windows.h> // This needs to be included for PlaySound()


#pragma comment(lib,"winmm.lib") // This adds the static library
// "winmm.lib" to the project

int main()
{
PlaySound(TEXT("c:\\wave.wav"), NULL, SND_FILENAME|SND_SYNC);

return 0;
}

You can use the following code as well. You need to add the winmm library
manually if you use the following code.
// see: https://bit.ly/3GiDLzy for more information

#include <Windows.h> // This needs to be included for PlaySound()

int main()
{
PlaySound(TEXT("c:\\wave.wav"), NULL, SND_FILENAME|SND_SYNC);

return 0;
}

Click the Project> Project1 Properties (Fig. 7.1) and then add the winmm.lib to
Additional Dependencies (Fig. 7.2). This adds the winmm library to your project.
Fig. 7.1 Project> Project Properties

Fig. 7.2 Project Property Pages window


128 7 Some Useful Functions

7.4 main Arguments

Sometimes it is useful to pass some arguments to the main function. For example,
assume that you want to write a program to copy the files. In this case, it is useful to
take the source and destination paths from the command line.
The main function has two arguments traditionally called argc and argv: int main
(int argc, char *argv[]). The argument definitions are as follows:
argc: An integer that contains the count of arguments that follow in argv. The argc
parameter is always greater than or equal to 1.
argv: An array of null-terminated strings representing command-line arguments
entered by the user of the program. By convention, argv[0] is the command with
which the program is invoked. argv[1] is the first command-line argument. The
last argument from the command line is argv[argc - 1], and argv[argc] is
always NULL.
Let’s study an example. The following code prints the arguments passed to it
from the command line. Output of this code is shown in Fig. 7.3.
#include <stdio.h>

int main(int argc, char *argv[])


{
for (int i=0;i<argc;i++)
{
printf("arg[%d]= %s\n", i, argv[i]);
}
return 0;
}

Fig. 7.3 Output of the code

Let’s give more command line arguments to the previous code. Click the Project>
Project1 Properties (Fig. 7.4) and enter the arguments to the Command Arguments
(Fig. 7.5). If you run the program, you will receive the output shown in Fig. 7.6.
7.4 main Arguments 129

Fig. 7.4 Project> Project Properties

Fig. 7.5 Project Property Pages


130 7 Some Useful Functions

Fig. 7.6 Output of the code

You can pass the arguments to the main function using the command prompt.
Open the command line (Fig. 7.7) and enter the arguments after the .exe file path
(Fig. 7.8).

Fig. 7.7 Output of the code

Fig. 7.8 Output of the code

Let’s study another example. Here, we want to write a program to play a .wav
file. The path of the .wav file is given to the main function as an argument. Code is
shown below:
#include <stdio.h>
#include <Windows.h> // This needs to be included for PlaySound()
#pragma comment(lib,"winmm.lib") // This adds the static library
// "winmm.lib" to the project

int main(int argc, char *argv[])


{

PlaySound(argv[1], NULL, SND_FILENAME | SND_SYNC);

return 0;
}
7.4 main Arguments 131

Click the Project> Project1 Properties (Fig. 7.9) and select the Use Multi-Byte
Character Set (Fig. 7.10).

Fig. 7.9 Project> Project Properties


132 7 Some Useful Functions

Fig. 7.10 Project Property Pages window

Let’s test the program. Click the Project> Project1 Properties (Fig. 7.11) and give
the path of the file to the Command Arguments (Fig. 7.12). Press the F5 to run the
code and see the result.
Fig. 7.11 Project> Project Properties

Fig. 7.12 Project Property Pages window


134 7 Some Useful Functions

7.5 exit Function

The exit function terminates the program immediately. Any open file descriptors
belonging to the program are closed as well.
Let’s study an example. The following code terminates as soon as it reaches the
exit function. Output of this code is shown in Fig. 7.13.
#include <stdio.h>
#include <stdlib.h>

int main()
{
printf("Hello World!\n");
exit(EXIT_SUCCESS); // exit(EXIT_SUCCESS) is the same as exit(0)
// exit(EXIT_FAILURE) is the same as exit(1)
printf("C programming is fun...");
return 0;
}

Fig. 7.13 Output of the code

7.6 atexit Function

The atexit function causes the specified function to be called when the program
terminates. Let’s study an example. In the following code, cleanup function is called
once the code reaches the end of the main function, i.e., return 0 line. Output of this
code is shown in Fig. 7.14.

#include <stdio.h>
#include <stdlib.h>

void cleanup();

int main()
{
atexit(cleanup);
printf("Hello World!\n");
printf("main function finished here.\n");
return 0;
}

void cleanup()
{
printf("Hi. I am cleanup function...");
}
7.6 atexit Function 135

Fig. 7.14 Output of the code

Let’s study another example. In the following code, cleanup function is called
when the code reaches the exit function. Output of this code is shown in Fig. 7.15.

#include <stdio.h>
#include <stdlib.h>

void cleanup();

int main()
{
atexit(cleanup);
printf("Hello World!\n");
exit(EXIT_FAILURE);
printf("main function finished here.\n");
return 0;
}

void cleanup()
{
printf("Hi. I am cleanup function...");
}

Fig. 7.15 Output of the code

The following code calculates the amount of time that the code is run. A sample
output of this code is shown in Fig. 7.16.
136 7 Some Useful Functions

#define _CRT_SECURE_NO_WARNINGS

#include <stdio.h>
#include <stdlib.h>
#include <time.h>

void cleanup();
time_t start, end;

int main()
{
time(&start);
atexit(cleanup);

int a, b;
printf("please enter two numbers: ");
scanf("%d %d", &a, &b);
printf("Sum of entered numbers is: %d\n", a+b);

return 0;
}

void cleanup()
{
time(&end);
double diff = difftime(end, start);
printf("Execution time: %.2f sec\n", diff);
}

Fig. 7.16 Output of the code

7.7 Reading the Mouse Pointer Position

The following code can be used to read the mouse position. Origin of the screen is
shown in Fig. 7.17 (Fig. 7.18).
7.7 Reading the Mouse Pointer Position 137

#include <stdio.h>
#include <windows.h>

int main()
{
POINT Point;

while (1)
{
GetCursorPos(&Point);

printf("Mouse x: %d\n", Point.x);


printf("Mouse y: %d\n", Point.y);
printf("-----\n");

for (int i = 0; i < 500000000; i++) {}; // makes a simple delay


}

return 0;
}

Fig. 7.17 Output of the code


138 7 Some Useful Functions

Fig. 7.18 The top left


corner of the screen is the
origin

7.8 Timer

Timers are used to call a function at a specified interval of time repeatedly. In the
following code, function f is called repeatedly after 1000 ms.

#include <windows.h>
#include <stdio.h>

void CALLBACK f(HWND hwnd, UINT uMsg, UINT timerId, DWORD dwTime)
{
printf("Hello World!\n");
}

int main()
{
MSG msg;

SetTimer(NULL, 0, 1000, (TIMERPROC)&f); //Timer with 1000 ms interval


while (GetMessage(&msg, NULL, 0, 0)) {
TranslateMessage(&msg);
DispatchMessage(&msg);
}

return 0;
}

Let’s study another example. The following code calls the readMousePosition
function repeatedly every 1000 ms. This program prints the mouse pointer location
every 1 s.
Further Reading 139

#include <windows.h>
#include <stdio.h>

POINT Point;
void CALLBACK readMousePosition(HWND hwnd, UINT uMsg, UINT timerId, DWORD dwTime);

int main()
{
MSG msg;

SetTimer(NULL, 0, 1000, (TIMERPROC)&readMousePosition); //Timer with 1000 ms


interval
while (GetMessage(&msg, NULL, 0, 0)) {
TranslateMessage(&msg);
DispatchMessage(&msg);
}

return 0;
}

void CALLBACK readMousePosition(HWND hwnd, UINT uMsg, UINT timerId, DWORD dwTime)
{
GetCursorPos(&Point);

printf("Mouse x: %d\n", Point.x);


printf("Mouse y: %d\n", Point.y);
printf("-----\n");
}

7.9 Shutting Down the Computer

You can shut down the computer with the aid of the following code:
#include <stdio.h>

int main()
{
//see here: https://bit.ly/3vKnzlz
system("C:\\WINDOWS\\System32\\shutdown -s");
return 0;
}

Further Reading

1. Hart JM (2010) Windows system programming. Addison-Wesley


Chapter 8
Pointers

8.1 Introduction

A pointer is a variable whose value is the address of another variable, i.e., direct
address of the memory location. Like any variable or constant, you must declare a
pointer before using it to store any variable address.
The general form of a pointer variable declaration is: type* var-name. Here, the
type is the pointer’s base type; it must be a valid C data type, and var-name is the
name of the pointer variable. The asterisk (*) used to declare a pointer is the same
asterisk used for multiplication. However, in this statement the asterisk is being
used to designate a variable as a pointer. Take a look at some of the valid pointer
declarations:
int* ip; /* pointer to an integer */
double* dp; /* pointer to a double */
float* fp; /* pointer to a float */
char* ch; /* pointer to a character */

Some C programming tasks are performed more easily with pointers, and other
tasks, such as dynamic memory allocation, cannot be performed without using
pointers. So, it becomes necessary to learn pointers to become a perfect C
programmer.

8.2 Address-of (&) Operator

To access the address of a variable, we use the unary or address-of operator &
(ampersand) that returns the address of that variable. For example, &a gives us the
address of variable a. Following is an example. Sample output of this code is shown

© The Author(s), under exclusive license to Springer Nature Switzerland AG 2023 141
F. Asadi, Essentials of C Programming with Microsoft® Visual Studio®,
https://doi.org/10.1007/978-3-031-35711-4_8
142 8 Pointers

in Fig. 8.1 (you may receive a different output since the address of variables changes
from computer to computer).
#include <stdio.h>

int main()
{
int a = 42;

printf("address of variable a is %zu", &a);

return 0;
}

Fig. 8.1 Output of the code

8.3 Pointers

A pointer is a variable that stores the memory address of another variable as its
value. A pointer variable points to a data type (like int) of the same type, and is cre-
ated with the * operator. The address of the variable you are working with is assigned
to the pointer.
Following is an example. In this code, the address of variable a is saved in pointer
b. Sample output of this code is shown in Fig. 8.2 (you may receive a different
output since the address of variables changes from computer to computer).
#include <stdio.h>

int main()
{
int a = 42;
int* b;
b = &a;
printf("address of variable a is %p", b);

return 0;
}

Fig. 8.2 Output of the code


8.4 Dereferencing (*) Operator 143

It is a good idea to start the pointers name with a “ptr” to show that they are
pointer. Following is an example:
#include <stdio.h>

int main()
{
int a = 42;
int* ptrb;
ptrb = &a;
printf("address of variable a is %p", ptrb);

return 0;
}

8.4 Dereferencing (*) Operator

To access the value stored in the address, we use the unary operator * that returns the
value of the variable located at the address specified by its operand. This is also called
dereferencing. Following is an example. Output of this code is shown in Fig. 8.3.
#include <stdio.h>

int main()
{
int a = 42;
int* b;
b = &a;
printf("value stored in pointer b is %d\n", *b);

return 0;
}

Fig. 8.3 Output of the code

In the following code, dereferencing operator is used to change the value of a


variable. Output of this code is shown in Fig. 8.4.
#include <stdio.h>

int main()
{
int a = 42;
int* b;
b = &a;

*b = 50;
printf("a=%d", a);

return 0;
}
144 8 Pointers

Fig. 8.4 Output of the code

Let’s study another example. The following code studies the address of array
elements. Output of this code is shown in Fig. 8.5. Note that in C programming, the
name of the array is a pointer to the first element of the array, i.e., the element with
index 0.
#include <stdio.h>

int main()
{
int myArray[] = { 50,100,200 }; // myArray is a pointer to the
// first location of myArray.i.e. 50

printf("myArray=%zu\n", myArray);

//first method to take the addresses


printf("\naddress of myArray[0] is %zu\n", &myArray[0]);
printf("address of myArray[1] is %zu\n", &myArray[1]);
printf("address of myArray[2] is %zu\n", &myArray[2]);

//second method to take the addresses. Same as the first method.


printf("\naddress of myArray[0] is %zu\n", myArray);
printf("address of myArray[1] is %zu\n", myArray + 1);
printf("address of myArray[2] is %zu\n", myArray + 2);

//dereferencing
printf("\nvalue of myArray[0] is %zu\n", *myArray);
printf("value of myArray[1] is %zu\n", *(myArray + 1));
printf("value of myArray[2] is %zu\n", *(myArray + 2));

return 0;
}

Fig. 8.5 Output of the code


8.5 Pointer Arithmetic 145

8.5 Pointer Arithmetic

Sometimes we need to perform arithmetic operations on pointers. Table 8.1 shows


the arithmetic operators that you can apply to the pointers. Note that multiplication
and division operator cannot be used with pointers.

Table 8.1 Arithmetic operators which can be applied to pointers


Operation Description
Assignment (=) You can assign the value to the pointer or value to the address
which is pointed by the pointer
Addition (+) You can add integer value to the pointer to point the different
memory locations
Subtraction (-) You can subtract the integer value from the pointer to point the
different memory locations
comparison (==, !=, <, >, <=, This operation is valid only between two pointers that point to
and >=) the same array
Incrementing (++) You can use increment operators (pre and post) with the pointer
Decrementing (--) You can use decrement operators (pre and post) with the pointer

Note that when we increment or decrement the pointer, the pointer increases or
decreases a block of memory (block of memory depends on pointer data type).
Generally, people make mistakes when they calculate the next pointing address
of the pointer. Here is the technique to calculate the next pointing address of a
pointer when applying arithmetic operation on it. To understand this technique, let
us consider ptr is a pointer that has data type “T,” and “i” is the pointer offset.
address(ptr + i) = address(ptr) + (sizeof(T) * i);
address(ptr - i) = address(ptr) - (sizeof(T) * i);

Following is an example. Output of this code is shown in Fig. 8.6.


#include <stdio.h>

int main()
{
int array[] = { 0,1,2,3,4 }; //remember that int takes 4 Bytes.

printf("array = %zu\n", array); //array is a pointer to first element of the


array

printf("\narray+1= %zu\n", array + 1);


printf("*(array+1)= %zu\n", *(array + 1));

printf("\narray+2= %zu\n", array + 2);


printf("*(array+2)= %zu\n", *(array + 2));

printf("\narray+3= %zu\n", array + 3);


printf("*(array+3)= %zu\n", *(array + 3));

printf("\narray+3= %zu\n", array + 4);


printf("*(array+3)= %zu\n", *(array + 4));

return 0;
}
146 8 Pointers

Fig. 8.6 Output of the code

8.6 Call by Reference

The call by reference (or more exactly call by pointer) method of passing arguments
to a function copies the reference (address) of an argument into the formal param-
eter. Inside the function, the reference is used to access the actual argument used in
the call. This means that changes made to the parameter affect the passed argument.
Let’s study some examples. Consider the following code. Output of this code is
shown in Fig. 8.7. In this code, the address of variables a and b (remember that &
returns the address of variables) are passed to the scanf function. Therefore, scanf
function used call by reference.
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>

int main()
{
int a;
int b;
printf("please enter 2 numbers:");
scanf("%d %d", &a, &b);
printf("sum: %d", a+b);

return 0;
}
8.6 Call by Reference 147

Fig. 8.7 Output of the code

The swap function in the following code takes the address of variables a and b
and swaps their values. Sample output of this code is shown in Fig. 8.8.
#include <stdio.h>

void swap(int* a, int* b);

int main()
{
int x = 50;
int y = 60;

printf("before swap");
printf("value of x is: %d\n", x);
printf("value of x is: %d\n", y);
swap(&x, &y);

printf("\nafter swap");
printf("value of x is: %d\n", x);
printf("value of x is: %d\n", y);
return 0;
}

void swap(int* a, int* b)


{
int tmp;
tmp = *a;
*a = *b;
*b = tmp;
}

Fig. 8.8 Output of the code


148 8 Pointers

8.7 malloc Function

The malloc function (defined in stdlib.h header file) allocates the requested memory
and returns a pointer to it.
Following is an example. This code asks the user to enter a length and makes an
array with the length equal to what the user entered. Sample output of this code is
shown in Fig. 8.9.
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <stdlib.h>

int main()
{
int* ptra;
int N = 0;

printf("please enter N: ");


scanf("%d", &N);

ptra = malloc(N * sizeof(int)); //pointer to a block of memory to save N integer


numbers

for (int i = 0; i < N; i++)


ptra[i] = i;

for (int i = 0; i < N; i++)


printf("ptra[%d]=%d\n", i, ptra[i]);

free(ptra); //Don't forger to free the allocaed space

return 0;
}

Fig. 8.9 Output of the code


8.8 NULL Pointer 149

8.8 NULL Pointer

Here are the most common uses of a NULL pointer:


(a) To initialize a pointer variable when that pointer variable has not been assigned
any valid memory address yet.
(b) To check for a null pointer before accessing any pointer variable. By doing so,
we can perform error handling in pointer related code, e.g., dereference a
pointer variable only if it is not NULL.
(c) To pass a null pointer to a function argument when we do not want to pass any
valid memory address.
Let’s study some examples. The following is an example for part (a):
#include <stdio.h>

int main()
{
int* ptr=NULL;

return 0;
}

In the following code, we dereference a pointer if it is not NULL. Output of this


code is shown in Fig. 8.10.
#include <stdio.h>

int main()
{
int* ptr=NULL;
printf("ptr: %p\n", ptr);
if (ptr != NULL)
printf("*ptr: %d", *ptr);

return 0;
}

Fig. 8.10 Output of the code

Some functions (for instance, malloc) return the NULL pointer to show that an error
occurred. Let’s study an example. Consider the following code. Output of this code is
shown in Fig. 8.11. In this code, we used the malloc function to request 1015 blocks
(each block has 4 bytes length) to save integer data. Output of malloc function (ptr) is
checked to see whether it is NULL. The memory is not assigned when ptr is NULL.
150 8 Pointers

#include <stdio.h>
#include <stdlib.h>

int main()
{
int* ptr;
ptr = malloc(sizeof(int)*1000000000000000);

if (ptr != NULL)
{
printf("No error occured.");
}
else {
printf("Error: ptr is NULL!\n");
}

free(ptr);
return 0;
}

Fig. 8.11 Output of the code

If you request a small amount of memory, then ptr will not be NULL. Following
is an example. Output of this code is shown in Fig. 8.12.
#include <stdio.h>
#include <stdlib.h>

int main()
{
int* ptr;
ptr = malloc(sizeof(int) * 10);

if (ptr != NULL)
{
printf("No error occured.");
}
else {
printf("Error: ptr is NULL!\n");
}

free(ptr);
return 0;
}

Fig. 8.12 Output of the code


8.8 NULL Pointer 151

Let’s see what happens to the pointer (generated by the malloc function) after
calling the free function. Consider the following code. Output of this code is shown
in Fig. 8.13. According to Fig. 8.13, the pointer still points to the assigned mem-
ory block.
#include <stdio.h>
#include <stdlib.h>

int main()
{
int* ptr;
ptr = malloc(sizeof(int) * 10);

if (ptr != NULL)
{
printf("No error occured.\n");
printf("value of ptr=%d in the beginning of the code.\n", ptr);
}
else {
printf("Error: ptr is NULL!\n");
}

free(ptr);
printf("value of ptr=%d after running the free function.\n", ptr);

return 0;
}

Fig. 8.13 Output of the code

In the following code, the NULL is assigned to the ptr pointer after calling the
free function. Output of this code is shown in Fig. 8.14.
152 8 Pointers

#include <stdio.h>
#include <stdlib.h>

int main()
{
int* ptr;
ptr = malloc(sizeof(int) * 10);

if (ptr != NULL)
{
printf("No error occured.\n");
printf("value of ptr=%d in the beginning of the code.\n", ptr);
}
else {
printf("Error: ptr is NULL!\n");
}

free(ptr);
ptr = NULL;
printf("value of ptr=%d after running the free function.\n", ptr);

return 0;
}

Fig. 8.14 Output of the code

8.9 void Pointer

A void pointer is a pointer that has no associated data type with it. A void pointer
can hold the address of any type and can be type casted to any type.
Functions like malloc and calloc return void* type and this allows these func-
tions to be used to allocate memory of any data type (just because of void*). Void
pointers are used to implement generic functions as well. For instance, prototype of
memcmp is int memcmp (const void* str1, const void* str2, size_t n). Therefore,
memcmp can work with int*, double*, char*, … .
Let’s study an example. In the following code, a void pointer is defined and took
the address of an integer and a character variable. Output of this code is shown in
Fig. 8.15.
Further Reading 153

#include <stdio.h>

int main() {
int a=10;
char b = 'x';

void* ptr; //ptr is a void pointer.


ptr= &a;
printf("ptr= &a = %p\n",ptr);

ptr = &b;
printf("ptr= &b = %p\n",ptr);

return(0);
}

Fig. 8.15 Output of the code

Void pointers cannot be dereferenced. For example, the following program does
not compile.
#include <stdio.h>

int main()
{
int a = 10;
void* ptr = &a;
printf("%d", *ptr);

return 0;
}

Further Reading

1. Deitel P, Deitel H (2022) C How to program: with case studies in applications and systems
programming, 9th edn. Pearson, Boston
Chapter 9
Structures and Unions

9.1 Introduction

Structures are a way to group several related variables into one place. Each variable
in the structure is known as a member of the structure. Unlike an array, a structure
can contain many different data types (int, float, char, etc.). This chapter studies the
structures and unions and their applications in C programming.

9.2 Defining a Structure

You can create a structure by using the struct keyword and declare each of its mem-
bers inside curly braces. Let’s study an example. In the following code, Student
structure is defined and a structure variable of Student called s1 is created. Note that
to access members of a structure, use the dot syntax. Output of this code is shown
in Fig. 9.1.

© The Author(s), under exclusive license to Springer Nature Switzerland AG 2023 155
F. Asadi, Essentials of C Programming with Microsoft® Visual Studio®,
https://doi.org/10.1007/978-3-031-35711-4_9
156 9 Structures and Unions

#include<stdio.h>
#include<string.h>

struct Student
{
char name[50];
char id[10];
int age;
int grades[5];
};

int main()
{
struct Student s1;
strcpy(s1.name, "John");
strcpy(s1.id, "231708457");
s1.age = 18;
s1.grades[0] = 70;
s1.grades[1] = 63;
s1.grades[2] = 40;
s1.grades[3] = 90;
s1.grades[4] = 86;

printf("s1.name= %s\n", s1.name);


printf("s1.id= %s\n", s1.id);
printf("s1.age= %d\n", s1.age);
printf("s1.grades[0]= %d\n", s1.grades[0]); //only first mark is printed
//to keep the code short
return 0;
}

You can initialize a structure in the following way as well. Output of this code is
shown in Fig. 9.2.

Fig. 9.1 Output of the code

#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<string.h>

typedef struct
{
char name[50];
char id[10];
int age;
int grades[5];
} student;

int main()
{
student s1 = { "John", "231708457", 18, {70,63,40,90,86} };

printf("s1.name= %s\n", s1.name);


printf("s1.id= %s\n", s1.id);
printf("s1.age= %d\n", s1.age);
printf("s1.grades[0]= %d\n", s1.grades[0]);
return 0;
}
9.3 typedef Keyword 157

Fig. 9.2 Output of the code

9.3 typedef Keyword

The typedef keyword allows the user to provide alternative name for the primitive
(e.g.,​int) and user-defined​(e.g., struct) data types. This keyword adds a new name
to some existing data type but does not create a new type. Using typedef struct
results in a cleaner, more readable code, and saves the programmer keystrokes​.
Let’s study an example. In the following code, the keyword struct is removed
when structure s1 is created (compare this code with the previous ones). Output of
this code is shown in Fig. 9.3.
#include<stdio.h>
#include<string.h>

typedef struct
{
char name[50];
char id[10];
int age;
int grades[5];
} student;

int main()
{
student s1;
strcpy(s1.name, "John");
strcpy(s1.id, "231708457");
s1.age = 18;
s1.grades[0] = 70;
s1.grades[1] = 63;
s1.grades[2] = 40;
s1.grades[3] = 90;
s1.grades[4] = 86;

printf("s1.name= %s\n", s1.name);


printf("s1.id= %s\n", s1.id);
printf("s1.age= %d\n", s1.age);
printf("s1.grades[0]= %d\n", s1.grades[0]);
return 0;
}

Fig. 9.3 Output of the code


158 9 Structures and Unions

9.4 Copying the Content of a Structure Variable Into


Another Structure Variable

You can copy the content of a structure into another structure with the aid of equal-
ity operator. In the following code, two struct variables are defined with two differ-
ent values. After calling s2=s1, content of s1 is copied into s2. Output of this code
is shown in Fig. 9.4.
#include<stdio.h>
#include<string.h>

typedef struct
{
char name[50];
char id[10];
int age;
int grades[5];
} student;

int main()
{
student s1, s2;

strcpy(s1.name, "John");
strcpy(s1.id, "231708457");
s1.age = 18;
s1.grades[0] = 70;
s1.grades[1] = 63;
s1.grades[2] = 40;
s1.grades[3] = 90;
s1.grades[4] = 86;

strcpy(s2.name, "Mary");
strcpy(s2.id, "231708458");
s2.age = 18;
s2.grades[0] = 30;
s2.grades[1] = 70;
s2.grades[2] = 75;
s2.grades[3] = 50;
s2.grades[4] = 95;

s2 = s1;

printf("s1.name= %s\n", s1.name);


printf("s1.id= %s\n", s1.id);
printf("s1.age= %d\n", s1.age);
printf("s1.grades[0]= %d\n", s1.grades[0]);

printf("\ns2.name= %s\n", s2.name);


printf("s2.id= %s\n", s2.id);
printf("s2.age= %d\n", s2.age);
printf("s2.grades[0]= %d\n", s2.grades[0]);

return 0;
}
9.5 Functions with Structure Arguments 159

Fig. 9.4 Output of the code

9.5 Functions with Structure Arguments

Functions can take structure variables as argument. For instance, in the following
code, print_student function takes a structure variable and prints its contents.
Output of this code is shown in Fig. 9.5.
160 9 Structures and Unions

#include<stdio.h>
#include<string.h>

typedef struct
{
char name[50];
char id[10];
int age;
int grades[5];
} student;

void print_student(student s);

int main()
{
student s1;
strcpy(s1.name, "John");
strcpy(s1.id, "231708457");
s1.age = 18;
s1.grades[0] = 70;
s1.grades[1] = 63;
s1.grades[2] = 40;
s1.grades[3] = 90;
s1.grades[4] = 86;

print_student(s1);

return 0;
}

void print_student(student s)
{
printf("name= %s\n", s.name);
printf("id= %s\n", s.id);
printf("age= %d\n", s.age);
printf("grades[0]= %d\n", s.grades[0]);
printf("grades[1]= %d\n", s.grades[1]);
printf("grades[2]= %d\n", s.grades[2]);
printf("grades[3]= %d\n", s.grades[3]);
printf("grades[4]= %d\n", s.grades[4]);
}

Fig. 9.5 Output of the code


9.6 Array of Structures 161

9.6 Array of Structures

You can define an array of structures. In the following code, an array of structures is
defined. Output of this code is shown in Fig. 9.6.
#include<stdio.h>
#include<string.h>

typedef struct
{
char name[50];
char id[10];
int age;
int grades[5];
} student;

int main()
{
student s[2];

strcpy(s[0].name, "John");
strcpy(s[0].id, "231708457");
s[0].age = 18;
s[0].grades[0] = 70;
s[0].grades[1] = 63;
s[0].grades[2] = 40;
s[0].grades[3] = 90;
s[0].grades[4] = 86;

printf("s[0].name= %s\n", s[0].name);


printf("s[0].id= %s\n", s[0].id);
printf("s[0].age= %d\n", s[0].age);
printf("s[0].grades[0]= %d\n", s[0].grades[0]);

strcpy(s[1].name, "Mary");
strcpy(s[1].id, "231708458");
s[1].age = 18;
s[1].grades[0] = 30;
s[1].grades[1] = 70;
s[1].grades[2] = 75;
s[1].grades[3] = 50;
s[1].grades[4] = 95;

printf("\ns[1].name= %s\n", s[1].name);


printf("s[1].id= %s\n", s[1].id);
printf("s[1].age= %d\n", s[1].age);
printf("s[1].grades[0]= %d\n", s[1].grades[0]);

return 0;
}
162 9 Structures and Unions

Fig. 9.6 Output of the code

You can define functions which get an array of structures as argument. The
print_student in the following code prints the contents of each structure vari-
able. Output of this code is shown in Fig. 9.7.
9.6 Array of Structures 163

#include<stdio.h>
#include<string.h>

typedef struct
{
char name[50];
char id[10];
int age;
int grades[5];
} student;

void print_student(student s[], int N);

int main()
{
student s[2];

strcpy(s[0].name, "John");
strcpy(s[0].id, "231708457");
s[0].age = 18;
s[0].grades[0] = 70;
s[0].grades[1] = 63;
s[0].grades[2] = 40;
s[0].grades[3] = 90;
s[0].grades[4] = 86;

strcpy(s[1].name, "Mary");
strcpy(s[1].id, "231708458");
s[1].age = 18;
s[1].grades[0] = 30;
s[1].grades[1] = 70;
s[1].grades[2] = 75;
s[1].grades[3] = 50;
s[1].grades[4] = 95;

print_student(s, sizeof(s) / sizeof(s[0]));//sizeofs calculate the length of array

return 0;
}

void print_student(student s[], int N)


{
for (int i = 0; i < N; i++)
{
printf("s[%d].name= %s\n", i , s[i].name);
printf("s[%d].id= %s\n", i , s[i].id);
printf("s[%d].age= %d\n", i , s[i].age);
printf("s[%d].grades[0]= %d\n\n", i , s[i].grades[0]);
}
}
164 9 Structures and Unions

Fig. 9.7 Output of the code

9.7 Arrow Operator

The dot (.) operator is used to normally access members of a structure (or union).
The arrow (->) operator is used to access the members of the structure (or union)
using pointers. In the following code, values stored in structure variable s1 are
manipulated with the aid of s2 pointer. Output of this code is shown in Fig. 9.8.
9.7 Arrow Operator 165

#include<stdio.h>
#include<string.h>

typedef struct
{
char name[50];
char id[10];
int age;
int grades[5];
} student;

int main()
{
student s1;
strcpy(s1.name, "John");
strcpy(s1.id, "231708457");
s1.age = 18;
s1.grades[0] = 70;
s1.grades[1] = 63;
s1.grades[2] = 40;
s1.grades[3] = 90;
s1.grades[4] = 86;

printf("s1 as defined in the begining of the code:");


printf("s1.name= %s\n", s1.name);
printf("s1.id= %s\n", s1.id);
printf("s1.age= %d\n", s1.age);
printf("s1.grades[0]= %d\n", s1.grades[0]);

student* s2;
s2 = &s1;
strcpy(s2->name, "David");
strcpy(s2->id, "231708480");
s2->age = 19;
s2->grades[0] = 0;

printf("\n\ns1 as after manipulation:");


printf("s1.name= %s\n", s1.name);
printf("s1.id= %s\n", s1.id);
printf("s1.age= %d\n", s1.age);
printf("s1.grades[0]= %d\n", s1.grades[0]);

return 0;
}

Fig. 9.8 Output of the code


166 9 Structures and Unions

9.8 Dereferencing a Pointer to a Structure

In the following code, arrow operator is used to access the variables in the pointer
s3. Output of this code is shown in Fig. 9.9. Note that this code uses the dynamic
memory allocation (see Sect. 8.7 in Chap. 8) to assign a value to pointer s3.
#include<stdio.h>

#include<string.h>

typedef struct
{
char name[50];
char id[10];
int age;
int grades[5];
} student;

int main()
{
student* s3;
s3 = malloc(sizeof(student)); //allocates memory for one student struct variable
strcpy(s3->name, "Lisa");
strcpy(s3->id, "231708488");
s3->age = 18;
s3->grades[0] = 85;
s3->grades[1] = 90;
s3->grades[2] = 70;
s3->grades[3] = 70;
s3->grades[4] = 85;

printf("s3.name= %s\n", (*s3).name);


printf("s3.id= %s\n", (*s3).id);
printf("s3.age= %d\n", (*s3).age);
printf("s3.grades[0]= %d\n", (*s3).grades[0]); //only first mark is printed
//to keep the code short

return 0;
}

Fig. 9.9 Output of the code


9.8 Dereferencing a Pointer to a Structure 167

The previous code can be written as follows as well. Output of this code is shown
in Fig. 9.10.
#include<stdio.h>
#include<string.h>

typedef struct
{
char name[50];
char id[10];
int age;
int grades[5];
} student;

int main()
{
student* s3;
s3 = malloc(1*sizeof(student)); //allocates memory for one student struct variable
strcpy((*s3).name, "Lisa"); //parantheses are necessary. Don’t write *s3.name
strcpy((*s3).id, "231708488");
(*s3).age = 18;
(*s3).grades[0] = 85;
(*s3).grades[1] = 90;
(*s3).grades[2] = 70;
(*s3).grades[3] = 70;
(*s3).grades[4] = 85;

printf("s3.name= %s\n", (*s3).name);


printf("s3.id= %s\n", (*s3).id);
printf("s3.age= %d\n", (*s3).age);
printf("s3.grades[0]= %d\n", (*s3).grades[0]); //only first mark is printed
//to keep the code short

return 0;
}

Fig. 9.10 Output of the code


168 9 Structures and Unions

9.9 Unions

A union is a user-defined type similar to structures except for one key difference.
Structures allocate enough space to store all their members, whereas unions can
only hold one-member value at a time.
Let’s study an example. In the following code, a union with three data types: int,
double, and a character array with 32 elements is defined. Integer requires 4 bytes,
double requires 8 bytes and a character array with 32 elements requires 32 bytes.
The union will take max(4, 8, 32)=32 bytes. Output of the following code is shown
in Fig. 9.11. Note that values shown for x and y are wrong but value of z is shown
correctly. The reason is that character data is the last data written to the union and a
union always store the last data written to it.
#define _CRT_SECURE_NO_WARNINGS

#include <stdio.h>
#include <string.h>

union Data
{
int x;
double y;
char z[32];
};

int main()
{
union Data mydata;
mydata.x = 10;
mydata.y = 20.5;
strcpy(mydata.z, "test 123");

printf("mydata.x=%d\n", mydata.x);
printf("mydata.y=%f\n", mydata.y);
printf("mydata.z=%s\n\n", mydata.z);

printf("size of mydata union: %d Bytes", sizeof(mydata));

return 0;
}

Fig. 9.11 Output of the code


9.10 Pointer to a Union 169

Let’s change the previous code to what is shown below. Output of this code is
shown in Fig. 9.12. This time, the value of y is shown correctly since y is the last
variable written to the union.
#define _CRT_SECURE_NO_WARNINGS

#include <stdio.h>
#include <string.h>

union Data
{
int x;
double y;
char z[32];
};

int main()
{
union Data mydata;
strcpy(mydata.z, "test 123");
mydata.x = 10;
mydata.y = 20.5;

printf("mydata.x=%d\n", mydata.x);
printf("mydata.y=%f\n", mydata.y);
printf("mydata.z=%s\n\n", mydata.z);

printf("size of mydata union: %d Bytes", sizeof(mydata));

return 0;
}

Fig. 9.12 Output of the code

9.10 Pointer to a Union

Similar to structures, you can use the arrow operator to access the data of a pointer
to a union. Following is an example. Output of this code is shown in Fig. 9.13.
170 9 Structures and Unions

#define _CRT_SECURE_NO_WARNINGS

#include <stdio.h>
#include <string.h>

union Data
{
int x;
double y;
char z[32];
};

int main()
{
union Data mydata;
strcpy(mydata.z, "test 123");

union Data* ptr = &mydata;


printf("ptr->z=%s\n", ptr->z);

return 0;
}

Fig. 9.13 Output of the code

Further Reading

1. Deitel P, Deitel H (2022) C how to program: with case studies in applications and systems
programming, 9th edn. Pearson, London
Chapter 10
Mathematical Functions

10.1 Introduction

This chapter introduces ready-to-use mathematical functions available in the math.h


header file.

10.2 Precedence of Operators

Operator precedence determines the grouping of terms in an expression and decides


how an expression is evaluated. Certain operators have higher precedence than oth-
ers. For instance, the multiplication operator has a higher precedence than the addi-
tion operator. For example, x = 7 + 3 * 2; here, x is assigned 13, not 20 because
operator * has a higher precedence than +, so it first gets multiplied with 3*2 and
then adds into 7.
Table 10.1 shows the precedence of operators. In this table, operators are listed
top to bottom, in descending precedence.

© The Author(s), under exclusive license to Springer Nature Switzerland AG 2023 171
F. Asadi, Essentials of C Programming with Microsoft® Visual Studio®,
https://doi.org/10.1007/978-3-031-35711-4_10
172 10 Mathematical Functions

Table 10.1 Precedence of operators


Precedence Operator Description Associativity
1 ++ -- Suffix/postfix increment and decrement Left-to-right
() Function call
[] Array subscripting
. Structure and union member access
-> Structure and union member access through pointer
2 ++ -- Prefix increment and decrement Right-to-left
+ - Unary plus and minus
! ~ Logical NOT and bitwise NOT
* Indirection (dereference)
& Address-of
sizeof Size-of
3 * / % Multiplication, division, and remainder Left-to-right
4 + - Addition and subtraction
5 << >> Bitwise left shift and right shift
6 < <= For relational operators < and ≤, respectively
> >= For relational operators > and ≥ respectively
7 == != For relational = and ≠ respectively
8 & Bitwise AND
9 ^ Bitwise XOR (exclusive or)
10 | Bitwise OR (inclusive or)
11 && Logical AND
12 || Logical OR
13 ?: Ternary conditional Right-to-left
14 = Simple assignment
+= -= Assignment by sum and difference
*= /= Assignment by product, quotient, and remainder
%=
<<= >>= Assignment by bitwise left shift and right shift
&= ^= Assignment by bitwise AND, XOR, and OR
|=
15 , Comma Left-to-right

Let’s study an example. In the following code, multiplication is done first, then
division, subtraction, and addition are done. Output of this code is shown in
Fig. 10.1.
#include <stdio.h>

int main()
{
int n = 1 - 5 + 3 * 4 / 2;
printf("%d",n);
return 0;
}
10.2 Precedence of Operators 173

Fig. 10.1 Output of the code

In the following code, addition is done first, then multiplication and division are
done. Output of this code is shown in Fig. 10.2.
#include <stdio.h>

int main()
{
int n = 1 - (5 + 3) * 4 / 2;
printf("%d",n);
return 0;
}

Fig. 10.2 Output of the code

The following code compares the precedence of remainder, multiplication, and


addition operators. Output of this code is shown in Fig. 10.3.
#include <stdio.h>

int main()
{
printf("15%%4+6*2=%d\n", 15 % 4 + 6 * 2);
printf("15%%4*6+2=%d\n", 15 % 4 * 6 + 2);
return 0;
}

Fig. 10.3 Output of the code


174 10 Mathematical Functions

10.3 Remainder of Division

The modulo operator % computes the remainder of integer division. For instance,
9%4 returns 1 since 9 = 4 × 2 + 1. In the following code, modulo operator is used to
calculate the greatest common divisor of two numbers. Output of this code is shown
in Fig. 10.4.
#define _CRT_SECURE_NO_WARNINGS // put this line otherwise
// the scanf command doesn't work
#include <stdio.h>

int main()
{
int n1, n2, i, gcd;

printf("Enter two integers: ");


scanf("%d %d", &n1, &n2);

for (i = 1; i <= n1 && i <= n2; ++i)


{
// Checks if i is factor of both integers
if (n1 % i == 0 && n2 % i == 0)
gcd = i;
}

printf("G.C.D of %d and %d is %d", n1, n2, gcd);

return 0;
}

Fig. 10.4 Output of the code

The fmod(x,y) calculates the floating-point remainder of x/y. Following is an


example. Output of this code is shown in Fig. 10.5.
#include <stdio.h>
#include <math.h>

int main()
{
// 12.4 / 2.3 = 5.3913
// 12.4 - ( 2.3 * [5.3913] ) = 12.4 - (2.3*5) = 12.4 - 11.5 = 0.9

double num = 12.4;


double den = 2.3;
double reminder = fmod(num, den);
printf("reminder of 12.4/2.3= %.2f", reminder);

return 0;
}
10.4 sizeof Operator 175

Fig. 10.5 Output of the code

10.4 sizeof Operator

sizeof is a much-used operator in C programming. It is a compile-time unary opera-


tor which can be used to compute the size of its operand. The sizeof can be applied
to any data type, including primitive types such as integer and floating-point types,
pointer types, or compound datatypes such as structure, union, etc.
Following is an example. Output of this code is shown in Fig. 10.6.
#define _CRT_SECURE_NO_WARNINGS // put this line otherwise
// the scanf command doesn't work
#include <stdio.h>

int main(){
float x=1.2;
int s1 = sizeof(x);
int s2 = sizeof(double);
int s3 = sizeof(int);

printf("sizeof(x)=%d Bytes\n",s1);
printf("sizeof(double)= %d Bytes\n", s2);
printf("sizeof(int) = %d Bytes\n", s3);
return 0;
}

Fig. 10.6 Output of the code

In the following code, sizeof operator is used to calculate the number of elements
in an array. Output of this code is shown in Fig. 10.7.
#include <stdio.h>

int main()
{
int arr[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
printf("Number of elements:%lu ", sizeof(arr)/sizeof(arr[0]));

return 0;
}
176 10 Mathematical Functions

Fig. 10.7 Output of the code

The sizeof operator is used in dynamic memory allocation as well. For instance,
int* ptr = (int*)malloc(10 * sizeof(int)); allocates a memory block on the heap to
save ten integers.

10.5 Type Casting

Converting one data type into another is known as type-conversion. Figure 10.8
helps you understand the nature of data conversion. For instance, when 5.8 (a float
value) is converted to integer, its value will be 5. Therefore, we lose 0.8 in this
conversion.

Fig. 10.8 Comparison of


different data types
10.5 Type Casting 177

Let’s study some examples. Consider the following code. In this code, variable a
is automatically converted into an integer by using the ASCII code of character 5
(when compiler sees int+char, it converts the lower data type, i.e., char, to a higher
one, i.e., int; thus, operation is converted to int+int). Output of this code is shown in
Fig. 10.9.
#include <stdio.h>

int main()
{
char a = '5';
int b = 9;
int result = a + b; //ASCII of '5' id 53.
printf("result= %d", result);

return 0;
}

Fig. 10.9 Output of the code

Consider the following code. In this code, b is converted to double automatically


and then a+b=5.8+9.0=14.8, which is a double value, is calculated. The obtained
value is converted into integer automatically since variable result is an integer vari-
able. Output of this code is shown in Fig. 10.10.
#include <stdio.h>

int main()
{
double a = 5.8;
int b = 9;
int result = a + b; //result=5.8+9.0=14.8-->14
printf("result= %d", result);

return 0;
}

Fig. 10.10 Output of the code


178 10 Mathematical Functions

In the following code, the variable result is double. Output of this code is shown
in Fig. 10.11. Output shows that integer variable b is converted to double automati-
cally and then a+b=5.8+9.0=14.8 is calculated.
#include <stdio.h>

int main()
{
double a = 5.8;
int b = 9;
double result = a + b; //result=5.8+9.0=14.8
printf("result= %f", result);

return 0;
}

Fig. 10.11 Output of the code

In the following code, a decimal number is assigned to integer variable a. Output


of this code is shown in Fig. 10.12. Note that conversion of decimal number to inte-
ger is done automatically.
#include <stdio.h>

int main()
{
int a = 5.67; //implicit type conversion
printf("a= %d", a);

return 0;
}

Fig. 10.12 Output of the code

In the previous examples, data type conversions were done automatically. This
type of cast is called implicit cast.
The programmer can also force the code to do the conversion at the desired point
as well. This type of casts is called explicit cast. Let’s study an example of explicit
cast. Consider the following code.
10.5 Type Casting 179

#define _CRT_SECURE_NO_WARNINGS // put this line otherwise


// the scanf command doesn't work

#include <stdio.h>

int main()
{
int num1, num2, num3;
float average;

printf("Enter three numbers: ");


scanf("%d%d%d",&num1,&num2,&num3);

int sum = num1 + num2 + num3;


average = sum / 3;
printf("Average=%f", average);

return 0;
}

In the previous code, three numbers are taken from the user and their average is
printed. Sample output of this code is shown in Fig. 10.13. Note that sum is an inte-
ger variable. The variable sum is divided by 3. Dividing an integer number by
another integer number leads to an integer number. Therefore, numbers after the
decimal point are not shown in Fig. 10.13.

Fig. 10.13 Output of the code

Consider the following example where the cast operator causes the division of
one integer variable by another to be performed as a floating-point operation.
Sample output of this code is shown in Fig. 10.14. Note that digits after decimal
points are shown.
#define _CRT_SECURE_NO_WARNINGS // put this line otherwise
// the scanf command doesn't work
// this is a sample code for type casting

#include <stdio.h>

int main()
{
int num1, num2, num3;
float average;

printf("Enter three numbers: ");


scanf("%d%d%d",&num1,&num2,&num3);

int sum = num1 + num2 + num3;


average = (float)sum / 3; // type casting has a higher priority
// than division
printf("Average=%f", average);

return 0;
}
180 10 Mathematical Functions

Fig. 10.14 Output of the code

10.6 Mathematical Constants

Table 10.2 shows the mathematical constants available in Microsoft Visual Studio.

Table 10.2 Defined Symbol Expression Value


mathematical constants M_E e 2.71828182845904523536
available in Microsoft
Visual Studio. M_LOG2E log2(e) 1.44269504088896340736
M_LOG10E log10(e) 0.43429448190325182765
M_LN2 ln(2) 0.69314718055994530942
M_LN10 ln(10) 2.30258509299404568402
M_PI pi 3.14159265358979323846
M_PI_2 pi/2 1.57079632679489661923
M_PI_4 pi/4 0.78539816339744830962
M_1_PI 1/pi 0.31830988618379067154
M_2_PI 2/pi 0.63661977236758134308
M_2_SQRTPI 2/sqrt(pi) 1.12837916709551257390
M_SQRT2 sqrt(2) 1.41421356237309504880
M_SQRT1_2 1/sqrt(2) 0.70710678118654752440

Let’s study some examples. The following code prints the values of Euler’s and
pi numbers. Output of this code is shown in Fig. 10.15.
#define _USE_MATH_DEFINES // This line must be added if you want to use the
// defined constants. Otherwise you will receive
// an error.
#include <stdio.h>
#include <math.h> // Mathematical functions are here.

int main() {
printf("Value of e=M_E=%f\n\n",M_E); // Prints the Euler’s number
printf("Value of pi=M_PI=%f\n\n",M_PI); // Prints the pi number
return 0;
}
10.7 Power Function 181

Fig. 10.15 Output of the code

The following code calculates the area of a circle. Sample output of this code is
shown in Fig. 10.16.
#define _CRT_SECURE_NO_WARNINGS // put this line otherwise
// the scanf command doesn't work

#define _USE_MATH_DEFINES // This line must be added if you want to use the
// defined constants. Otherwise you will receive
// an error.

#include <stdio.h>
#include <math.h> // Mathematical functions are here.

int main() {
float r = 0.0;

printf("please enter the radiuce of circle: ");


scanf("%f", &r);

printf("Area= %.2f\n", M_PI*r*r);

return 0;
}

Fig. 10.16 Output of the code

10.7 Power Function

The pow function computes the power of a number. Following is an example.


Output of this code is shown in Fig. 10.17.
#include <stdio.h>
#include <math.h> // Mathematical functions are here.

int main() {
float x = 5.25;

printf("x^4.5=%.3f\n\n", pow(x,4.5));
printf("x^2=%.3f\n\n", pow(x,2));

return 0;
}
182 10 Mathematical Functions

Fig. 10.17 Output of the code

10.8 Square Root Function

The square root of a number can be calculated with the aid of sqrt function.
Following is an example. Output of this code is shown in Fig. 10.18.
#include <stdio.h>
#include <math.h>

int main()
{
// sqrtf takes float inputs and returns float values
// sqrtl takes long double inputs and returns long double values
// sqrt takes double inputs and returns double values

// you can simply use sqrt with different data types

float x =2.0;
float result1 = sqrtf(x);
printf("sqrtf(x)=%f\n\n", result1);

double y = 2.0;
double result2 = sqrt(y);
printf("sqrt(y)=%f\n\n", result2);

long double z = 2.0;


long double result3 = sqrtl(z);
printf("sqrtl(z)=%Lf\n\n", result3);

return 0;
}

Fig. 10.18 Output of the code


10.10 Logarithm Function 183

10.9 Cubic Root Function

You can use the cbrt function to calculate the cubic root of a number. Following is
an example. Output of this code is shown in Fig. 10.19.
#include <stdio.h>
#include <math.h> // Mathematical functions are here.

int main() {
printf("cbrt(28)=%.3f\n", cbrt(28));

return 0;
}

Fig. 10.19 Output of the code

10.10 Logarithm Function

You can use the log and log10 functions to calculate the natural logarithm (ln) and
decimal logarithm, respectively. Following is an example. Output of this code is
shown in Fig. 10.20.
#include <stdio.h>
#include <math.h> // Mathematical functions are here.

int main() {
float x = 5.25;

printf("ln(x)=%.3f\n\n", log(x));
printf("log10(x)=%.3f\n\n", log10(x));

return 0;
}

Fig. 10.20 Output of the code


184 10 Mathematical Functions

10.11 Trigonometric Functions

Trigonometric functions can be calculated with the aid of sin, cos, and tan functions.
Cotangent is calculated with the aid of tan function (remember that tan(x).cot(x)=1).
Following is an example. Output of this code is shown in Fig. 10.21.
#define _USE_MATH_DEFINES // This line must be added if you want to use the
// defined constants. Otherwise you will receive
// an error.

#include <stdio.h>
#include <math.h> // Mathematical functions are here.

int main() {
float x = M_PI/3; // x is in Radyans

printf("sin(x)=%.3f\n\n", sin(x));
printf("cos(x)=%.3f\n\n", cos(x));
printf("tan(x)=%.3f\n\n", tan(x));
printf("cot(x)=%.3f\n\n", 1/tan(x));
return 0;
}

Fig. 10.21 Output of the code

10.12 Inverse Trigonometric Functions

Inverse of trigonometric functions can be calculated with the aid of asin, acos, and
atan functions. Arc cotangent can be calculated with the aid of atan function. Note
that the outputs of these functions are in Radians.
Following is an example. The two methods for calculation of arc cotangent are
shown below. Output of this code is shown in Fig. 10.22.
10.13 Hyperbolic Functions 185

#define _USE_MATH_DEFINES // This line must be added if you want to use the
// defined constants. Otherwise you will receive
// an error.

#include <stdio.h>
#include <math.h> // Mathematical functions are here.

int main() {
float x = 0.8;

printf("asin(x)=%.3f\n\n", asin(x));
printf("acos(x)=%.3f\n\n", acos(x));
printf("atan(x)=%.3f\n\n", atan(x));
//two methods to calculate arccot:
printf("acot(x)=%.3f\n\n", atan(1/x)); // remember acot(x)=atan(1/x)
printf("acot(x)=%.3f\n\n", M_PI_2-atan(x)); // remember acot(x)+atan(x)=pi/2
return 0;
}

Fig. 10.22 Output of the code

10.13 Hyperbolic Functions

Hyperbolic functions can be calculated with the aid of sinh, cosh, and tanh func-
tions. Hyperbolic cotangent is calculated with the aid of tanh function.
Following is a sample code. Output of this code is shown in Fig. 10.23.
#define _USE_MATH_DEFINES // This line must be added if you want to use the
// defined constants. Otherwise you will receive
// an error.

#include <stdio.h>
#include <math.h> // Mathematical functions are here.

int main() {
float x = 0.8;

printf("sinh(x)=%.3f\n\n", sinh(x));
printf("cosh(x)=%.3f\n\n", cosh(x));
printf("tanh(x)=%.3f\n\n", tanh(x));
printf("coth(x)=%.3f\n\n", 1/tanh(x));
return 0;
}
186 10 Mathematical Functions

Fig. 10.23 Output of the code

10.14 Inverse Hyperbolic Functions

Inverse of hyperbolic functions can be calculated with the aid of asinh, acosh, and
atanh functions. Inverse hyperbolic cotangent can be calculated with the aid of
1  x 1
acoth  x   ln  formula.
2  x  1 
Following is a sample code. Output of this code is shown in Fig. 10.24.
#define _USE_MATH_DEFINES // This line must be added if you want to use the
// defined constants. Otherwise you will receive
// an error.

#include <stdio.h>
#include <math.h> // Mathematical functions are here.

int main() {
float x = 1.8;

printf("asinh(x)=%.3f\n\n", asinh(x));
printf("acosh(x)=%.3f\n\n", acosh(x));
printf("atanh(x)=%.3f\n\n", atanh(x));
printf("acoth(x)=%.3f\n\n", 0.5*log((x+1)/(x-1)));
return 0;
}

Fig. 10.24 Output of the code


10.16 Rounding and Truncating Numbers 187

10.15 Exponential Function

The exp function computes e (2.71828) raised to the power of the given argument.
Following is a sample code. Output of this code is shown in Fig. 10.25.
#include <stdio.h>
#include <math.h>

int main()
{
float x = 2;
float y = exp(x);

printf("exp(%.2f)=%.2f", x, y);
return 0;
}

Fig. 10.25 Output of the code

10.16 Rounding and Truncating Numbers

Round function returns the nearest integer value of the float/double/long double argu-
ment passed to this function. If the decimal value is from ".1 to .5", it returns an inte-
ger value which is less than the argument we passed, and if the decimal value is from
".6 to .9", the function returns an integer value greater than the argument we passed.
In short the round function returns an integer value nearest to the argument we passed.
The trunc function allows to truncate (remove) the decimal value from a floating
number and return an integer value.
Following is an example. Output of this code is shown in Fig. 10.26.
#include <stdio.h>
#include <math.h>

int main()
{
double x = 6.5;
printf("round(%.2f) = %.2f\n", x, round(x)); //returns the nearest integer value
//(rounded value) of the given
float,
//integer, or double number based
on
//the decimal part of the number

printf("trunc(%.2f) = %.2f\n", x, trunc(x)); // always ignore the decimal point


// trunc(6.1)=6
// trunc(6.9)=6
return 0;
}
188 10 Mathematical Functions

Fig. 10.26 Output of the code

10.17 floor and ceil Functions

The floor function calculates the nearest integer less than or equal to the argument
passed. The ceil function computes the nearest integer greater than the argu-
ment passed.
Following is an example. Output of this code is shown in Fig. 10.27.
#include <stdio.h>
#include <math.h> // Mathematical functions are here.

int main() {
printf("floor(+3.6)=%f\n\n", floor(3.6));
printf("floor(-3.6)=%f\n\n", floor(-3.6));

printf("ceil(3.6)=%f\n\n", ceil(3.6));
printf("ceil(-3.6)=%f\n\n", ceil(-3.6));
return 0;
}

Fig. 10.27 Output of the code


10.19 Generation of Random Numbers 189

10.18 fabs and hypot Functions

The fabs function returns the absolute value of a number. The hypotenuse is the
longest side of a right-angled triangle. The hypot function is used to find hypotenuse
when other two sides are provided ( hypot  x,y   x 2  y 2 ).
Following is an example. Output of this example is shown in Fig. 10.28.
#include <stdio.h>
#include <math.h> // Mathematical functions are here.

int main() {
printf("fabs(+3.6)=%.3f\n\n", fabs(3.6));
printf("fabs(-3.6)=%.3f\n\n", fabs(-3.6));

printf("hypot(3,4)=%.3f\n\n", hypot(3,4));

return 0;
}

Fig. 10.28 Output of the code

10.19 Generation of Random Numbers

The function rand is used to generate pseudo random numbers. It returns an integer
value and its range is from 0 to RAND_MAX, i.e., 32767. The function srand does
not return anything and is used to initialize the generated pseudo random number by
rand function. If random numbers are generated with rand without first calling
srand, your program will create the same sequence of numbers each time it runs
(Fig. 10.29). The rand and srand functions are defined in cstdlib.h header file.

Fig. 10.29 rand and srand


functions
190 10 Mathematical Functions

Let’s study some examples. The following code prints the maximum value that
may be generated by the rand function. Output of this code is shown in Fig. 10.30.
#include <stdio.h>
#include <stdlib.h>

int main()
{
printf("%d", RAND_MAX);
return 0;
}

Fig. 10.30 Output of the code

The following code generates ten random values from 1 to 6. Output of this code
is shown in Fig. 10.31.
#include <stdio.h>
#include <stdlib.h>
#include <time.h>

int main()
{
srand(time(NULL)); //random generator is feed with current time
int randomNumber = 0;
printf("Generated Random Numbers:\n");
for (int i=0;i<10;i++)
{
randomNumber = rand() % 6 + 1; // rand()%6 gives a random integer number
from 0 to 5.
printf("%d\n", randomNumber);
}
return 0;
}

Fig. 10.31 Output of the code


10.19 Generation of Random Numbers 191

The following code generates ten random values from 20 to 100. Output of this
code is shown in Fig. 10.32.
#include <stdio.h>
#include <stdlib.h>
#include <time.h>

int main()
{
srand(time(NULL)); //random generator is feed with current time
int randomNumber = 0;
int ub = 100;
int lb = 20;

printf("Generated Random Numbers (from 20 to 100):\n");


for (int i = 0; i < 10; i++)
{
randomNumber = (rand() % (ub-lb+1)) + lb;
printf("%d\n", randomNumber);
}
return 0;
}

Fig. 10.32 Output of the code

The rand_s function in Visual Studio is the secure version of rand function. The
following example shows how to use the rand_s function to generate a random inte-
ger value from 1 to 6. Sample output of this code is shown in Fig. 10.33. There is no
need to call the srand function when you use the rand_s function since the algorithm
used by rand_s is not the same as the algorithm used by the rand function.
192 10 Mathematical Functions

#define _CRT_RAND_S //Remember to define CRT_RAND_S prior to


//inclusion statement.

#include <stdio.h>
#include <stdlib.h>
#include <limits.h>

int main() {
unsigned int number;

//following three line generates a random integre number in the [1,maximum]


range
double maximum = 6.0;
rand_s(&number);
printf("%u\n", (unsigned int)((double)number / ((double)UINT_MAX + 1) * maximum)
+ 1);

return 0;
}

Fig. 10.33 Output of the code

The rand_s function generates a random integer in the range of 0 to UINT_


MAX. You can use the following code to see the value of UINT_MAX. Output of
following code is shown in Fig. 10.34.
#include <stdio.h>
#include <limits.h>

int main() {
printf("UINT_MAX= %u\n", UINT_MAX);
return 0;
}

Fig. 10.34 Output of the code

The following code generates a random double value from [1, 6] interval. Note
that the output of following code is not an integer number, it is a double value.
Sample output of this code is shown in Fig. 10.35.
10.19 Generation of Random Numbers 193

#define _CRT_RAND_S //Remember to define CRT_RAND_S prior to


//inclusion statement.

#include <stdio.h>
#include <stdlib.h>
#include <limits.h>

int main() {
//following three line generates a random double number in the
// [1,maximum] range and save it in number variable

unsigned int number;


double maximum = 6.0;
rand_s(&number);
printf("%g\n", (double)number / ((double)UINT_MAX + 1) * maximum);

return 0;
}

Fig. 10.35 Output of the code

The following code takes an array and fills it with random integers. Sample out-
put for this code is shown in Fig. 10.36.
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <stdbool.h>

void generateRandomVector(int array[], int length, int min, int max);

int main()
{
srand(time(NULL)*getpid());
int a[10];
generateRandomVector(a, sizeof(a) / sizeof(a[0]), 1, 50);

for (int i = 0; i < (sizeof(a) / sizeof(a[0])); i++) {


printf("%d ", a[i]);
}
return 0;
}

void generateRandomVector(int array[], int length, int min, int max)


{
int new_random;
bool unique = false;

for (int i = 0; i < length; i++)


{
do
{
new_random = (rand() % (max - min + 1)) + min;
unique = true;
for (int j = 0; j < i; j++)
if (array[j]== new_random) unique = false;
} while (!unique);
array[i] = new_random;
}
}
194 10 Mathematical Functions

Fig. 10.36 Output of the code

10.20 Floating Point Numbers

The following code introduces some of the functions that help you see whether a
floating-point number is finite or infinite. Output of this code is shown in Fig. 10.37.
//isnan returns a non-zero value if x is a NaN value; and 0 otherwise
//signbit return 1 for negative values and 0 for others

#include <stdio.h>
#include <math.h>
#include <float.h>

int main()
{
printf("Minimum normalized positive value: %e. \n", FLT_MIN);
printf("Maximum normalized positive value: %e. \n", FLT_MAX);

float finite = 5.0;


if (isfinite(finite))
printf("%f is finite.\n", finite);

float a = 1.0, b = 0.0;


float infinite = a / b;
if (isinf(infinite))
printf("%f is infinite.\n", infinite);

float c = -1.0, d = 0.0;


float negative_infinite = c / d;
if (signbit(negative_infinite) && isinf(infinite))
printf("%f is negative.\n", negative_infinite);

float not_a_number = d / b;
if (isnan(not_a_number))
printf("%f is not a number.\n", not_a_number);
return 0;
}

Fig. 10.37 Output of the code


10.20 Floating Point Numbers 195

The following code introduces the fpclassify function. The fpclassify returns a
value of type int that matches one of the classification macro constants shown in
Table 10.3.

Table 10.3 Values returned Value Description


from fpclassify FP_INFINITE Positive or negative infinity (overflow)
FP_NAN Not-A-Number
FP_ZERO Value of zero
FP_SUBNORMAL Sub-normal value (underflow)
FP_NORMAL Normal value (none of the above)

The following simple code takes three floating point numbers from the user and
classifies them. Sample output of this code is code is shown in Fig. 10.38.
#define _CRT_SECURE_NO_WARNINGS

#include <stdio.h>
#include <math.h>
#include <float.h>

int main()
{
float a;

for (int i = 0; i < 3; i++)


{
printf("please enter a floating point number: ");
scanf("%f", &a);
switch (fpclassify(a))
{
case FP_INFINITE:
printf("%f is infinite\n\n", a);
break;

case FP_NAN:
printf("%f is not a number (NaN=0/0)\n\n", a);
break;

case FP_NORMAL:
printf("%f is normal\n\n", a);
break;
}
}

return 0;
}
196 10 Mathematical Functions

Fig. 10.38 Output of the code

10.21 Complex Functions

The complex library permits you to do calculation with complex numbers. Following
code is an example. Output of this code is shown in Fig. 10.39.
10.21 Complex Functions 197

#include <stdio.h>
#include <complex.h>

int main()
{
//list of complex.h functions are given here:https://bit.ly/3IqxKnf
//use the _Dcomplex for double complex numbers.
//use the _Fcomplex for float complex numbers.
//use the _Lcomplex for long double complex numbers.

_Dcomplex C1 = { 1 , 2 }; //C1=1+2i
_Dcomplex C2 = { 3 , 4 }; //C2=3+4i

_Dcomplex C3 = _Cmulcc(C1,C2); //C3=C1*C2


_Dcomplex C4 = conj(C1);

_Dcomplex C5 = csin(C1);
_Dcomplex C6 = ccos(C1);
_Dcomplex C7 = ctan(C1);

_Dcomplex C8 = cexp(C1);
_Dcomplex C9 = cpow(C1,C2); //C9=C1^C2
_Dcomplex C10 = csqrt(C1);
_Dcomplex C11 = casin(C1);
_Dcomplex C12 = cacos(C1);
_Dcomplex C13 = catan(C1);

printf("Real part of C1 is %.2f\n\n", creal(C1));


printf("Imaginary part of C1 is %.2f\n\n", cimag(C1));

printf("C3 equals to %.2f+%.2fi\n\n", creal(C3),cimag(C3));

printf("C4 equals to %.2f+%.2fi\n\n", creal(C4), cimag(C4));

printf("C5=sin(1+2*i) equals to %.2f+%.2fi\n\n", creal(C5), cimag(C5));


printf("C6=cos(1+2*i) equals to %.2f+%.2fi\n\n", creal(C6), cimag(C6));
printf("C7=tan(1+2*i) equals to %.2f+%.2fi\n\n", creal(C7), cimag(C7));
printf("C8=exp(1+2*i) equals to %.2f+%.2fi\n\n", creal(C8), cimag(C8));
printf("C9=cpow(1+2*i,3+4*i) equals to %.2f+%.2fi\n\n", creal(C9), cimag(C9));
printf("C10=csqrt(1+2*i) equals to %.2f+%.2fi\n\n", creal(C10), cimag(C10));
printf("C11=asin(1+2*i) equals to %.2f+%.2fi\n\n", creal(C11), cimag(C11));
printf("C12=acos(1+2*i) equals to %.2f+%.2fi\n\n", creal(C12), cimag(C12));
printf("C13=atan(1+2*i) equals to %.2f+%.2fi\n\n", creal(C13), cimag(C13));
printf("arg(1+2*i) equals to %.2f\n\n", carg(C1));

return 0;
}
198 10 Mathematical Functions

Fig. 10.39 Output of the code

10.22 Binary and Hexadecimal Numbers

Binary and hexadecimal numbers can be defined in C. Binary and hexadecimal


numbers are entered with 0b and 0x prefixes, respectively. Following code is an
example. Output of this code is shown in Fig. 10.40.
#include <stdio.h>

int main()
{
int a = 0b101; //a=101 in binary which equals to 5 in decimal
int b = 0xFE5; //b=0xFE5 in hexadeciimal which equals to 4069 in decimal

printf("%d", a * b); //20345 is expected


return 0;
}
10.23 Bitwise Operation 199

Fig. 10.40 Output of the code

10.23 Bitwise Operation

The following six operators are bitwise operators (work at bit-level):


1. The & (bitwise AND) takes two numbers as operands and does AND on every
bit of two numbers. The result of AND is 1 only if both bits are 1.
2. The | (bitwise OR) takes two numbers as operands and does OR on every bit of
two numbers. The result of OR is 1 if any of the two bits is 1.
3. The ^ (bitwise XOR) takes two numbers as operands and does XOR on every bit
of two numbers. The result of XOR is 1 if the two bits are different.
4. The << (left shift) takes two numbers, left shifts the bits of the first operand, the
second operand decides the number of places to shift.
5. The >> (right shift) takes two numbers, right shifts the bits of the first operand,
the second operand decides the number of places to shift.
6. The ~ (bitwise NOT) takes one number and inverts all bits of it.
The following is a sample code for bitwise AND, OR, NOT, and XOR. Output of
this code is shown in Fig. 10.41.
#include <stdio.h>

int main()
{
int a = 0b00111011;
int b = 0b00101110;

printf("a=%d\n", a);
printf("b=%d\n", b);

printf("\na&b=%d\n",a&b); //Bitwise AND;


//00101010 or 42 in decimal is expected

printf("\na or b=%d\n",a|b); //Bitwise OR;


//00111111 or 63 in decimal is expected

printf("\nnot(a)=%d\n",~a); //Bitwise NOT


//11000100 or -60
//use two's complement to see why 11000100
//equals to -60; note that 11000100 starts
//with 1 therefore it is a negative number

printf("\na xor b=%d\n", a ^ b); //Bitwise XOR;


//00010101 in decimal is expected

return 0;
}
200 10 Mathematical Functions

Fig. 10.41 Output of the code

The following is a sample code for shift operator. Output of this code is shown in
Fig. 10.42.
#include <stdio.h>

int main()
{
//apply bitwise shift operations to int and char types only.
int a = 7; //a=00000000 00000000 00000000 00000111 in binary
//simply take a=111

printf("a=7\n");
printf("a>>2=%d\n", a >> 2); // expected value is a>>2=1 or 1 in decimal
printf("a<<2=%d\n", a << 2); // expected value is a<<2=11100 or 28 in decimal
return 0;
}

Fig. 10.42 Output of the code

10.24 GNU Scientific Library

The GNU Scientific Library (GSL) is a numerical library for C and C++ program-
mers. It is a free software under the GNU General Public License.
The library provides a wide range of mathematical routines such as random num-
ber generators, special functions, and least-squares fitting. There are over 1000
functions in total with an extensive test suite.
Further Readings 201

Latest version of GSL can be downloaded from https://www.gnu.org/software/


gsl/. You can install the package with the aid of instructions shown in https://bit.
ly/3wRx2sd or https://bit.ly/3HeVPuM. The following sample code solves the
1 2 3   x  11 
linear system 6 1 1   y   20  . Output of this code is shown in Fig. 10.43.
2 1 7   z  13 

#include <stdio.h>
#include <gsl/gsl_linalg.h>

main(void)
{
int n = 3;

double A_data[] = { 1,2,3,


6,1,1,
2,1,7};

double b_data[] = { 11,20,13 };

gsl_matrix_view A = gsl_matrix_view_array(A_data, n, n);


gsl_vector_view b = gsl_vector_view_array(b_data, n);

gsl_vector* x = gsl_vector_alloc(n);
gsl_permutation* perm = gsl_permutation_alloc(n);
int signum;
gsl_linalg_LU_decomp(&A.matrix, perm, &signum);
gsl_linalg_LU_solve(&A.matrix, perm, &b.vector, x);
printf("solution is:\n");
gsl_vector_fprintf(stdout, x, "%lf");

return 0;
}

Fig. 10.43 Output of the code

Further Readings

1. Deitel P, Deitel H (2022) C how to program: with case studies in applications and systems
programming, 9th edn. Pearson, London
2. https://bit.ly/2u8ywhE
3. https://bit.ly/3H7qprc
4. https://bit.ly/41R6DIc
Chapter 11
String Processing

11.1 Introduction

In C programming, string is a sequence of characters terminated with a null charac-


ter “\0”. This chapter introduces some of the ready-to-use functions to work with
strings. The functions studied here are defined in the string.h header file.

11.2 Defining a String

Strings are defined as an array of characters. The difference between a character


array and a string is the string is terminated with a unique character “\0”.
Let’s study an example. The following code defines a string with the name str.
Output of this code is shown in Fig. 11.1.
#include <stdio.h>

int main()
{
char str[5];
str[0] = 't';
str[1] = 'e';
str[2] = 's';
str[3] = 't';
str[4] = '\0'; //Non-printable char. \0 shows the end of string.
//Unused locations are filled with \0 as well.
printf("%s", str);

return 0;
}

© The Author(s), under exclusive license to Springer Nature Switzerland AG 2023 203
F. Asadi, Essentials of C Programming with Microsoft® Visual Studio®,
https://doi.org/10.1007/978-3-031-35711-4_11
204 11 String Processing

Fig. 11.1 Output of the code

You can write the previous code as follows:


#include <stdio.h>

int main()
{
char str[5]="test";

printf("%s", str);

return 0;
}

You do not need to write the size of character array as well. Therefore, the previ-
ous code can be simplified to:
#include <stdio.h>

int main()
{
char str[]="test";

printf("%s", str);

return 0;
}

11.3 String Inputs

The scanf function can be used to take a string from the user. The character array
which stores the user string must be defined big enough to store the worst case, i.e.,
the longest string.
Let’s study an example. In the following code, a character array with length of
100 is defined to store the user string. The scanf with %s is used to read the user
string. When you use the scanf function with %s, it returns the string up to the first
white space. Sample output of this code is shown in Fig. 11.2.
11.3 String Inputs 205

#define _CRT_SECURE_NO_WARNINGS

#include <stdio.h>

int main()
{
char buffer[100];

printf("Enter a string: ");


scanf("%s", buffer);
printf("buffer: %s\n", buffer); //& is not used since buffer is a pointer.

return 0;
}

Fig. 11.2 Output of the code

According to Fig. 11.2, the section after white space, i.e., World, is not copied
into the buffer. To read a whole line, you need to use %[^\n]%*c with the scanf
function. The following code reads the whole line entered by the user. Sample out-
put of this code is shown in Fig. 11.3.
#define _CRT_SECURE_NO_WARNINGS

#include <stdio.h>

int main()
{
char buffer[100];

printf("Enter a string: ");


scanf("%[^\n]%*c", buffer);
printf("buffer: %s\n", buffer);

return 0;
}

Fig. 11.3 Output of the code


206 11 String Processing

There is another way to read the whole line as well: using the fgets function. The
following code shows this method. Sample output of this code is shown in Fig. 11.4.
#define _CRT_SECURE_NO_WARNINGS

#include <stdio.h>

int main()
{
char buffer[100];

printf("Enter a string: ");


fgets(buffer, 100, stdin); //reads up to 100 characters from the keyboard
printf("buffer: %s", buffer);
return 0;
}

Fig. 11.4 Output of the code

11.4 strlen Function

The strlen is defined in the string.h header file and returns the length of a string.
Note that the strlen function does not count the “\0” character at the end of the
strings.
Let’s study an example. In the following code, strlen is used to obtain the length
of a string. Then a for loop is used to count the number of letter o in the test string.
Output of this code is shown in Fig. 11.5.
#define _CRT_SECURE_NO_WARNINGS

#include <stdio.h>
#include <string.h>

int main()
{
char test[]="Hello World!";

int length = strlen(test);


printf("Length of \"%s\" is %d.",test, length);

int numberOfO = 0;
for (int i = 0; i < length; i++)
{
if (test[i] == 'o' || test[i] == 'O') numberOfO++;
}
printf("\nnumber of o in the string: %d", numberOfO);
return 0;
}
11.6 strncpy Function 207

Fig. 11.5 Output of the code

11.5 strcpy Function

The strcpy is defined in the string.h header file and copies one string into another
string. When you use strcpy(), the size of the destination string should be large
enough to store the copied string. Otherwise, it may result in undefined behavior.
Prototype of this function is char* strcpy(char* destination, const char* source).
Let’s study an example. The following code copies the source string into the
destination string. Output of this code is shown in Fig. 11.6.
#define _CRT_SECURE_NO_WARNINGS

#include <stdio.h>
#include <string.h>

int main()
{
char source[]="Hello World!";
char destination[50];
strcpy(destination, source);
printf("%s\n", destination);
return 0;
}

Fig. 11.6 Output of the code

11.6 strncpy Function

The strncpy is defined in the string.h header. The prototype of this function is char*
strncpy(char* dest, const char* src, size_t n) and it copies up to n characters from
the string pointed to, by src to dest. In a case where the length of src is less than that
of n, the remainder of dest will be padded with null bytes.
Let’s study an example. The following code copies the first five characters of
source string into the destination array. Output of this code is shown in Fig. 11.7.
208 11 String Processing

#define _CRT_SECURE_NO_WARNINGS

#include <stdio.h>
#include <string.h>

int main()
{
char source[] = "Hello World!";
char destination[10];
memset(destination, '\0',sizeof(destination)); //fills the destination with '\0'

strncpy(destination, source,5); // first 5 characters of source is copied into


// destination

printf("%s\n", destination);
return 0;
}

Fig. 11.7 Output of the code

11.7 memset Function

The memset function is defined in the string.h header file. The prototype of this
function is void* memset(void* str, int c, size_t n) and it copies the character c (an
unsigned char) to the first n characters of the string pointed to, by the argument str.
Let’s study an example. In the following code, two arrays are initialized with the
aid of memset function. Output of this code is shown in Fig. 11.8.
#include <stdio.h>
#include <string.h>

int main()
{
int a[15];
char b[15];
memset(a, 0, sizeof(a));
memset(b, '$', sizeof(b));

printf("array a: ");
for (int i = 0; i < 15; i++)
printf("%d ", a[i]);

printf("\narray b: ");
for (int i = 0; i < 15; i++)
printf("%c ", b[i]);

return 0;
}
11.9 memmove Function 209

Fig. 11.8 Output of the code

11.8 memcpy Function

The memcpy function is defined in the string.h header file. The prototype of this
function is void* memcpy(void* dest, const void* src, size_t n) and it copies n
characters from memory area src to memory area dest.
Let’s study an example. The following code copies the first five characters of
source array into the destination array. Output of this code is shown in Fig. 11.9.
#define _CRT_SECURE_NO_WARNINGS

#include <stdio.h>
#include <string.h>

int main()
{
char source[] = "Hello World!";
char destination[10];
memset(destination, '\0', sizeof(destination)); //fills the destination with '\0'

memcpy(destination, source, 5); // first 5 characters of source is copied into


// destination

printf("%s\n", destination);
return 0;
}

Fig. 11.9 Output of the code

11.9 memmove Function

The memmove function is defined in the string.h header file. The prototype of this
function is void* memmove(void* dest, const void* src, size_t n) and it copies n
characters from src array to dest array. The memmove do the same job as memcpy
function. However, with memcpy, the destination cannot overlap the source at all.
With memmove it can.
210 11 String Processing

Let’s study an example. In the following code, ten elements of source array are
copied into the destination array. Output of this code is shown in Fig. 11.10.
#include <stdio.h>
#include <string.h>

int main()
{
int source[10] = { 1,2,3,4,5,6,7,8,9,10 };
int destination[10];
memmove(destination, source, 10 * sizeof(int));

printf("destination array:\n");
for (int i = 0; i < 10; i++)
printf("%d ", destination[i]);

return 0;
}

Fig. 11.10 Output of the code

Let’s study another example. In the following code, fourth, fifth, sixth… thir-
teenth elements of source array are copied into the destination array. Output of this
code is shown in Fig. 11.11.
#include <stdio.h>
#include <string.h>

int main()
{
int source[15] = { 1,2,3,4,5,6,7,8,9,10,11,12,13,14,15 };
int destination[10];
memmove(destination, source + 3, 10 * sizeof(int));

printf("destination array:\n");
for (int i = 0; i < 10; i++)
printf("%d ", destination[i]);

return 0;
}

Fig. 11.11 Output of the code


11.10 strcmp Function 211

11.10 strcmp Function

The strcmp function is defined in the string.h header file and is used to compare two
strings together. The prototype of this function is int strcmp(const char* str1, const
char* str2). Table 11.1 summarizes the return value from the strcmp function.

Table 11.1: Return value from strcmp


Return value Remarks
0 if strings are equal
>0 if the first non-matching character in str1 is greater (in ASCII)
than that of str2
<0 if the first non-matching character in str1 is lower (in ASCII)
than that of str2

Let’s study an example. In the following code, str1 and str2 strings are not equal.
Hence, the result is a non-zero integer (Fig. 11.12). str1 and str3 are equal. Hence,
the result is 0 (Fig. 11.12).
#include <stdio.h>
#include <string.h>

int main()
{
char str1[] = "abcd", str2[] = "AbCd", str3[] = "abcd";
int result;

// comparison of str1 and str2


result = strcmp(str1,str2);
printf("strcmp(str1,str2)=%d\n", result);

// comparison of str1 and str3


result = strcmp(str1, str3);
printf("strcmp(str1,str3)=%d\n", result);
return 0;
}

Fig. 11.12 Output of the code


212 11 String Processing

11.11 strncmp Function

The strncmp function is defined in the string.h header file. The prototype of this
function is int strncmp(const char* str1, const char* str2, size_t n) and it compares
at most the first n bytes of str1 and str2. Table 11.2 summarizes the return value
from the strncmp function.

Table 11.2: Return value from strncmp


Return value Remarks
0 if strings are equal
>0 if the first non-matching character in str1 is greater (in ASCII)
than that of str2
<0 if the first non-matching character in str1 is lower (in ASCII)
than that of str2

Let’s study an example. In the following code, str1 and str2 strings are compared
to each other up to the five and seven characters. Output of this code is shown in
Fig. 11.13.
#include <stdio.h>
#include <string.h>

int main()
{
char str1[] = "abcdeFghij", str2[] = "abcdefghij";
int result;

// comparison of str1 and str2 upto 5 Bytes


result = strncmp(str1, str2, 5);
printf("strcmp(str1,str2,5)=%d\n", result);

// comparison of str1 and str2 up to 7 Bytes


result = strncmp(str1, str2, 7);
printf("strcmp(str1,str2,7)=%d\n", result);
return 0;
}

Fig. 11.13 Output of the code


11.12 memcmp Function 213

11.12 memcmp Function

The memcmp function is defined in the string.h header file. The prototype of this
function is int memcmp(const void* str1, const void* str2, size_t n) and it compares
the first n bytes of memory area str1 and str2.
Let’s study an example. In the following code, two strings are compared to the
other up to the fifth character. Output of this code is shown in Fig. 11.14.
#include <stdio.h>
#include <string.h>

int main() {
char str1[10] = "abcdefgh";
char str2[10] = "abcdeFgh";
int result;

result = memcmp(str1, str2, 5);

if (result > 0) {
printf("str2 is less than str1");
}
else if (result < 0) {
printf("str1 is less than str2");
}
else {
printf("str1 is equal to str2");
}

return(0);
}

Fig. 11.14 Output of the code

Let’s study another example. In the following code, two integer arrays are com-
pared to each other up to the fifth element. Output of this code is shown in Fig. 11.15.
214 11 String Processing

#include <stdio.h>
#include <string.h>

int main() {
int a[] = {0,1,2,3,4,5};
int b[] = {0,1,2,3,5,7};
int result;

result = memcmp(a, b, 5*sizeof(int));

if (result > 0) {
printf("b is less than a");
}
else if (result < 0) {
printf("a is less than b");
}
else {
printf("a is equal to b");
}

return(0);
}

Fig. 11.15 Output of the code

11.13 strcat Function

The strcat function is defined in the string.h header file and concatenates (joins) two
strings. The prototype of this function is char* strcat(char* destination, const char*
source). The strcat() function concatenates the destination string and the source
string, and the result is stored in the destination string.
Let’s study an example. In the following code, three strings are concatenated
together. Output of this code is shown in Fig. 11.16.
#define _CRT_SECURE_NO_WARNINGS

#include <stdio.h>
#include <string.h>

int main()
{
char str1[30] = "Hello ", str2[] = "World", str3[] = "!";
strcat(str1, str2); //result is stored in str1
strcat(str1, str3); //result is stored in str1
printf("%s", str1);

return 0;
}
11.15 strtok Function 215

Fig. 11.16 Output of the code

11.14 strncat Function

The strncat function is defined in the string.h header file. The prototype of this func-
tion is char* strncat(char *destination, const char *source, size_t n) and it appends
the string pointed to by source to the end of the string pointed to by destination up
to n characters long.
Let’s study an example. The following code adds the first three character of str2
to str1. Output of this code is shown in Fig. 11.17.
#define _CRT_SECURE_NO_WARNINGS

#include <stdio.h>
#include <string.h>

int main()
{
char str1[10] = "Hello ", str2[] = "World!!!";
strncat(str1, str2, 3); //result is stored in str1.
//only 3 characters of str2 are
//copied to str1.
printf("%s", str1);

return 0;
}

Fig. 11.17 Output of the code

11.15 strtok Function

The strtok function is defined in the string.h header file. The prototype of this func-
tion is char* strtok(char* str, const char* delim) and it breaks string str into a series
of tokens using the delimiter delim.
Let’s study an example. In the following, strtok function is used with space
delimiter. Output of this code is shown in Fig. 11.18.
216 11 String Processing

#define _CRT_SECURE_NO_WARNINGS

#include <stdio.h>
#include <string.h>

int main()
{
char str[] = "Learnig C is fun."; // our string
char delim[] = " "; // space is the delimiter

char* portion1 = strtok(str, delim);


printf("%s\n", portion1);

char* portion2 = strtok(NULL, delim);


printf("%s\n", portion2);

char* portion3 = strtok(NULL, delim);


printf("%s\n", portion3);

char* portion4 = strtok(NULL, delim);


printf("%s\n", portion4);

return 0;
}

Fig. 11.18 Output of the code

The following code do the same job as the previous code. However, this code
uses a while loop instead of calling strtok manually. Note that the strtok returns
NULL when no token (portion) remains. Output of this code is shown in Fig. 11.19.
#define _CRT_SECURE_NO_WARNINGS

#include <stdio.h>
#include <string.h>

int main()
{
char str[] = "Learnig C is fun."; // our string
char delim[] = " "; // we entered the space as delimiter

char* portion = strtok(str, delim);


while (portion != NULL)
{
printf("%s\n", portion);
portion = strtok(NULL, delim);
}

return 0;
}
11.15 strtok Function 217

Fig. 11.19 Output of the code

The strtok function parses the string up to the first instance of the delimiter char-
acter, replaces the character in place with “\0,” and returns the address of the first
character in the token. Subsequent calls to strtok begin parsing immediately after
the most recently placed null character. The following code shows what happens to
the string when strtok function is called. Output of this code is shown in Fig. 11.20.
218 11 String Processing

#define _CRT_SECURE_NO_WARNINGS

#include <stdio.h>
#include <string.h>

int main()
{
char str[] = "Learnig C is fun."; // our string
char delim[] = " "; // space is entered as delimiters
int n = strlen(str);

printf("original string:");
for (int i = 0; i <= n; i++)
{
if (str[i] == '\0')
printf("\\0");
else
printf("%c", str[i]);
}

char* portion1 = strtok(str, delim);


printf("\nafter calling the strtok for 1st time:");
for (int i = 0; i <= n; i++)
{
if (str[i] == '\0')
printf("\\0");
else
printf("%c", str[i]);
}

char* portion2 = strtok(NULL, delim);


printf("\nafter calling the strtok for 2nd time:");
for (int i = 0; i <= n; i++)
{
if (str[i] == '\0')
printf("\\0");
else
printf("%c", str[i]);
}

char* portion3 = strtok(NULL, delim);


printf("\nafter calling the strtok for 3rd time:");
for (int i = 0; i <= n; i++)
{
if (str[i] == '\0')
printf("\\0");
else
printf("%c", str[i]);
}
return 0;
}

Fig. 11.20 Output of the code


11.16 strcspn Function 219

11.16 strcspn Function

The strcspn is defined in the string.h header file. The prototype of this function is
size_t strcspn(const char* str1, const char* str2) and it calculates the length of the
initial segment of str1, which consists entirely of characters not in str2.
Let’s study an example. Assume that we have a serial number (label) which is
composed of an alphabetic section followed by a number. The following code
calculates the length of alphabetic section. Output of this code is shown in Fig. 11.21.
#include <stdio.h>
#include <string.h>

int main()
{
char string[] = "CZCASDETRY62580";
char num[] = "0123456789"; //order is not important

int n = strcspn(string, num);


printf("Number of alphabetic characters in the label: %d\n",n);
return 0;
}

Fig. 11.21 Output of the code

The following code extracts the numeric section of the label. Output of this code
is shown in Fig. 11.22.
#include <stdio.h>
#include <string.h>

int main()
{
char string[] = "CZCASDETRY62580";
char num[] = "0123456789"; //order is not important

int n = strcspn(string, num);

char *numberCode = string + n;


printf("%s\n", numberCode);

return 0;
}

Fig. 11.22 Output of the code


220 11 String Processing

11.17 strspn Function

The strspn function is defined in the string.h header file. Prototype of this function
is size_t strspn(const char* str1, const char* str2) and it returns the number of
characters in the initial segment of str1 which consist only of characters from str2.
Let’s study an example. Assume that we have a serial number (label) which is
composed of an alphabetic section followed by a number. The following code
calculates the length of alphabetic section. Output of this code is shown in Fig. 11.23.
#include <stdio.h>
#include <string.h>

int main()
{
char string[] = "CZCASDETRY62580";
char letter[] = "abcdefghijklmnopqrstuvwxyz"
"ABCDEFGHIJKLMNOPQRSTUVWXYZ"; //order is not important
//2 "" are used to break the line

int n = strspn(string, letter);


printf("Number of alphabetic characters in the label: %d\n", n);
return 0;
}

Fig. 11.23 Output of the code

The following code extracts the numeric section of the label. Output of this code
is shown in Fig. 11.24.
#include <stdio.h>

#include <string.h>

int main()
{
char string[] = "CZCASDETRY62580";
char letter[] = "abcdefghijklmnopqrstuvwxyz"
"ABCDEFGHIJKLMNOPQRSTUVWXYZ"; //order is not important
//2 "" are used to break the line

int n = strspn(string, letter);

char* numberCode = string + n;


printf("%s\n", numberCode);

return 0;
}
11.19 atof Function 221

Fig. 11.24 Output of the code

11.18 atoi Function

The atoi function is defined in the string.h header file. The prototype of this function
is int atoi (const char* str) and it converts the string argument str to an integer (type
int). If no valid conversion could be performed, it returns zero.
Let’s study an example. In the following code, a number (in the form of a string)
is taken from the user, ten units are added to it, and the obtained result is printed on
the screen. Output of this code is shown in Fig. 11.25.
#define _CRT_SECURE_NO_WARNINGS

#include <stdio.h>
#include <string.h>

int main()
{
char str[10];
printf("please enter a number: ");
scanf("%s", str);

int N = atoi(str); //conversion of entered string into an int


printf("Entered value +10 = %d\n", N + 10);
return 0;
}

Fig. 11.25 Output of the code

11.19 atof Function

The atof function is defined in the string.h header file. The prototype of this function
is double atof(const char* str) and it converts the string argument str to a floating-­
point number (type double). If no valid conversion could be performed, it
returns zero.
222 11 String Processing

Let’s study an example. In the following code, a number (in the form of a string)
is taken from the user, ten units are added to it, and the obtained result is printed on
the screen. Output of this code is shown in Fig. 11.26.
#define _CRT_SECURE_NO_WARNINGS

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int main()
{
char str[10];
printf("please enter a number: ");
scanf("%s", str);

float N = atof(str);
N = N + 10.0;
printf("Entered value +10 = %f\n", N);

return 0;
}

Fig. 11.26 Output of the code

11.20 sscanf Function

The sscanf function is defined in the stdio.h header file. The prototype of this func-
tion is int sscanf (const char* str, const char* format, ...) and it reads data from str
and stores them according to parameter format into the locations given by the addi-
tional arguments, as if scanf was used, but reading from str instead of the standard
input (keyboard).
The sscanf function returns the number of variables filled on success. In the case
of an input failure before any data could be successfully read, EOF is returned.
Let’s study an example. The following code shows how to read integer and string
values with sscanf function. Output of this code is shown in Fig. 11.27.
11.20 sscanf Function 223

#define _CRT_SECURE_NO_WARNINGS

#include <stdio.h>

int main() {
int day, year;
char weekday[20], month[20], dtm[100];

strcpy(dtm, "Saturday March 25 1989");


sscanf(dtm, "%s %s %d %d", weekday, month, &day, &year);

printf("%s %d, %d = %s\n", month, day, year, weekday);

return(0);
}

Fig. 11.27 Output of the code

Let’s study another example. The following code shows how to read characters
and floating-point values with sscanf function. Output of this code is shown in
Fig. 11.28.
#define _CRT_SECURE_NO_WARNINGS

#include <stdio.h>

int main() {
float temp;
char sign, unit;

char todayTemp[20];

strcpy(todayTemp, "+ 25.756 C");


sscanf(todayTemp, "%c %f %c", &sign, &temp, &unit);

printf("Temperature is %c%.2f %c.\n", sign, temp, unit);

return(0);
}

Fig. 11.28 Output of the code


224 11 String Processing

11.21 sprintf Function

The sprintf function is defined in the stdio.h header file. The prototype of this func-
tion is int sprintf (char* str, const char* format, ...) and it sends formatted output to
a string pointed to by str.
The sprint returns the total number of characters written excluding the null-­
character appended at the end of the string if successful. Otherwise a negative num-
ber is returned in case of failure.
Let’s study an example. The following code sends a formatted output to the buf-
fer array. Output of this code is shown in Fig. 11.29.
#define _CRT_SECURE_NO_WARNINGS

#include <stdio.h>

int main()
{
char buffer[50];
int a = 10;
float b = 20.76, c;
c = a + b;
sprintf(buffer, "Sum of %d and %.2f is %.2f", a, b, c);
// The string "sum of 10 and 20 is 30" is stored
// into buffer instead of printing on screen

printf("%s", buffer); //prints on the screen

return 0;
}

Fig. 11.29 Output of the code

11.22 strchr Function

The strchr function is defined in the string.h header file. The prototype of this func-
tion is char* strchr(const char* str, int c) and it searches for the first occurrence of
the character c (an unsigned char) in the string pointed by the argument str.
Let’s study an example. In the following code, strchr function searches a string
for “u” and “@.” Output of this code is shown in Fig. 11.30.
11.22 strchr Function 225

#include <stdio.h>
#include <string.h>

int main()
{
char string[] = "Computer";
char* result= strchr(string, 'u');
printf("%s\n", result);

if (strchr(string, '@') == NULL) //returns NULL when it doesn't find the character
printf("No such character exists!");

return 0;
}

Fig. 11.30 Output of the code

Let’s study another example. In the following code, found “u” character is
replaced with a “*.” Output of this code is shown in Fig. 11.31.
#include <stdio.h>
#include <string.h>

int main()
{
char string[] = "Computer";
char* result = strchr(string, 'u');

printf("Original string: %s\n\n", string);


printf("string: %p\n", string);
printf("string+4: %p\n", string+4);
printf("result: %p\n", result); // note that result and string+4 have the same
value. Why?

result[0] = '*';
printf("\nOriginal string changed to: %s", string);

return 0;
}
226 11 String Processing

Fig. 11.31 Output of the code

Further Reading

1. Deitel P, Deitel H (2022) C how to program: with case studies in applications and systems
programming, 9th edn. Pearson, London
Chapter 12
Character Processing

12.1 Introduction

The character is stored in integer form in C programming. When a character is


passed as an argument, corresponding ASCII value (integer) of the character is
passed to the function instead of that character itself.
This chapter introduces some of the ready-to-use functions to work with charac-
ters. Studied functions are defined in the ctype.h header file.

12.2 isalnum Function

This function checks whether the argument passed to it is an alphanumeric character


(alphabet or number) or not.
The prototype of isalnum function is: int isalnum(int argument). The isalnum
function returns 1 if the argument is an alphanumeric character and returns 0 if the
argument is neither an alphabet nor a digit.
Let’s study an example. The following code takes a character from the user and
determines whether it is alphanumeric. Sample output of this code is shown in
Fig. 12.1.

© The Author(s), under exclusive license to Springer Nature Switzerland AG 2023 227
F. Asadi, Essentials of C Programming with Microsoft® Visual Studio®,
https://doi.org/10.1007/978-3-031-35711-4_12
228 12 Character Processing

#define _CRT_SECURE_NO_WARNINGS // put this line otherwise


// the scanf command doesn't work
#include <stdio.h>
#include <ctype.h>

int main() {
char c;
printf("Please enter a character: ");
scanf("%c", &c);

if (isalnum(c)) {
printf("Entered character is an alpha numeric (a,...,z, A,...,Z, 0,...,9)
character.\n");
}
else {
printf("Entered character is NOT an alpha numeric (a,...,z, A,...,Z,
0,...,9) character.\n");
}

return 0;
}

Fig. 12.1 Output of the code

12.3 isalpha Function

This function checks whether the argument passed to it is an alphabet character or


not. The prototype of isalpha function is: int isalpha(int argument). The isalpha
function returns 0 if the argument is not an alphabet character and returns a non-zero
value if the argument is an alphabet character.
Let’s study an example. The following code takes a character from the user and
determines whether it is an alphabet character. Sample output of this code is shown
in Fig. 12.2.
12.4 isdigit Function 229

#define _CRT_SECURE_NO_WARNINGS // put this line otherwise


// the scanf command doesn't work
#include <stdio.h>
#include <ctype.h>

int main() {
char c;
printf("Please enter a character: ");
scanf("%c", &c);

if (isalpha(c)) {
printf("Entered character is an alphabet (a,...,z, A,...,Z)
character.\n");
}
else {
printf("Entered character is NOT an alpha numeric (a,...,z, A,...,Z)
character.\n");
}

return 0;
}

Fig. 12.2 Output of the code

12.4 isdigit Function

This function checks whether the argument passed to it is a digit character or not.
The prototype of isdigit function is: int isdigit(int argument). The isdigit function
returns 0 if the argument is not a digit character and returns a non-zero value if the
argument is a digit character.
Let’s study an example. The following code takes a character from the user and
determines whether it is a digit character. Sample output of this code is shown in
Fig. 12.3.
230 12 Character Processing

#define _CRT_SECURE_NO_WARNINGS // put this line otherwise


// the scanf command doesn't work
#include <stdio.h>
#include <ctype.h>

int main() {
char c;
printf("Please enter a character: ");
scanf("%c", &c);

if (isdigit(c)) {
printf("Entered character is a numeric (0-9) character.\n");
}
else {
printf("Entered character is NOT a numeric (0-9) character.\n");
}

return 0;
}

Fig. 12.3 Output of the code

12.5 iscntrl Function

Characters that cannot be printed on the screen are known as control characters. For
example, backspace, Escape, newline, etc. The iscntrl() function checks whether a
character (passed to the function) is a control character or not. The prototype of
iscntrl function is: int iscntrl(int argument). The iscntrl function returns 0 if the
argument is not a control character and returns a non-zero value if the argument is a
control character.
Let’s study an example. The following code prints the ASCII code of control
characters. Output of this code and ASCII codes are shown in Figs. 12.4 and 12.5,
respectively.
#include <stdio.h>
#include <ctype.h>

int main() {
for (int i = 0; i < 127; i++) {
if (iscntrl(i))
printf("%d\n", i);
}
return 0;
}
12.5 iscntrl Function 231

Fig. 12.4 Output of the code


232 12 Character Processing

Fig. 12.5 ASCII codes


12.6 ispunct Function 233

12.6 ispunct Function

The ispunct function checks whether a character is a punctuation character or not.


The term “punctuation” as defined by this function includes all printable characters
that are neither alphanumeric nor a space. The prototype of ispunct function is: int
ispunct(int argument). The ispunct function returns 0 if the argument is not a punc-
tuation character and returns a non-zero value if the argument is punctuation character.
Let’s study an example. The following code prints the punctuation characters.
Output of this code is shown in Fig. 12.6.
#include <stdio.h>
#include <ctype.h>

int main() {
for (int i = 0; i < 127; i++) {
if (ispunct(i))
printf("%c\n", i);
}
return 0;
}

Fig. 12.6 Output of


the code
234 12 Character Processing

12.7 isspace Function

The isspace function checks whether a character is a white-space character or not.


The prototype of isspace function is: int isspace(int argument). If an argument passed
to the isspace function is a white-space character, it returns a non-zero integer. If not,
it returns 0. Following is an example. Output of this code is shown in Fig. 12.7.
#include <stdio.h>
#include <ctype.h>

int main() {
char c1 = ' ';
char c2 = 'a';

printf("isspace(c1)=%d\n", isspace(c1));
printf("isspace(c2)=%d\n", isspace(c2));
return 0;
}

Fig. 12.7 Output of the code

Let’s study another example. The following code prints the ASCII code of white-­
space characters. Output of this code is shown in Fig. 12.8. ASCII codes are shown
in Fig. 12.9 as well.
#include <stdio.h>
#include <ctype.h>

int main() {
for (int i = 0; i < 127; i++) {
if (isspace(i))
printf("%d\n", i);
}
return 0;
}

Fig. 12.8 Output of the code


12.7 isspace Function 235

Fig. 12.9 ASCII codes


236 12 Character Processing

12.8 islower Function

The islower function checks whether a character is a lowercase alphabet (a-z) or


not. The prototype of islower function is: int islower(int argument). The islower
function returns 0 if the argument is not a lowercase alphabet and returns a non-zero
value if the argument is a lowercase alphabet.
Let’s study an example. The following code takes a character from the user and
determines whether it is a small letter. Sample outputs of this code are shown in
Figs. 12.10 and 12.11.
#define _CRT_SECURE_NO_WARNINGS // put this line otherwise
// the scanf command doesn't work
#include <stdio.h>
#include <ctype.h>

int main() {
char c;
printf("Please enter a character: ");
scanf("%c", &c);

if (isalpha(c)) {
if (islower(c)) {
printf("Entered character is a small letter.\n");
}
else {
printf("Entered character is a capital letter.\n");
}
}else {
printf("Entered character is NOT a letter.\n");
}

return 0;
}

Fig. 12.10 Output of the code

Fig. 12.11 Output of the code


12.10 tolower Function 237

12.9 isupper Function

The isupper function checks whether a character is an uppercase alphabet (A-Z) or


not. The prototype of isupper function is: int isupper(int argument). The isupper
function returns 0 if the argument is not an uppercase alphabet and returns a non-­
zero value if the argument is an uppercase alphabet.
Let’s study an example. The following code takes a character from the user and
determines whether it is a capital letter. Sample outputs of this code are shown in
Fig. 12.12.
#define _CRT_SECURE_NO_WARNINGS // put this line otherwise
// the scanf command doesn't work
#include <stdio.h>
#include <ctype.h>

int main() {
char c;
printf("Please enter a character: ");
scanf("%c", &c);

if (isalpha(c)) {
if (isupper(c)) {
printf("Entered character is a capital letter.\n");
}
else {
printf("Entered character is a small letter.\n");
}
}else {
printf("Entered character is NOT a letter.\n");
}

return 0;
}

Fig. 12.12 Output of the code

12.10 tolower Function

The tolower function takes an uppercase alphabet and converts it to a lowercase


character. When a lowercase or a non-alphabetic character is passed to the tolower
function, the character itself is returned. The prototype of tolower function is int
tolower(int argument).
238 12 Character Processing

Let’s study an example. According to Fig. 12.9, ASCII character of capital letters
starts from 65 and ends at 90. The following code gives the integer numbers 65, 66,
67, …, 90 to the tolower function and prints the output generated by the tolower
function. Output of this code is shown in Fig. 12.13.
#include <stdio.h>
#include <ctype.h>

int main() {
for (int i = 65; i <= 90; i++) {
printf("%c\n", tolower(i));
}
return 0;
}

Fig. 12.13 Output of the code

12.11 toupper Function

The toupper function takes a lowercase alphabet and converts it to an uppercase


character. When an uppercase or a non-alphabetic character is passed to the toupper
function, the character itself is returned. The prototype of toupper function is int
toupper(int argument).
12.12 getch Function 239

Let’s study an example. According to Fig. 12.9, ASCII character of small letters
starts from 97 and ends at 120. The following code gives the integer numbers 97, 98,
99, …, 122 to the toupper function and prints the output generated by the toupper
function. Output of this code is shown in Fig. 12.14.
#include <stdio.h>
#include <ctype.h>

int main() {
for (int i = 97; i <= 122; i++) {
printf("ASCII code of %d belong to %c. toupper(%d)=%c\n", i, i, i,
toupper(i));
}
return 0;
}

Fig. 12.14 Output of the code

12.12 getch Function

The function getch in C is used to get a character as input from the user. The input
provided by the user is not displayed on the output screen. The code execution is
paused until a character is entered when a getch function is called. The getch() func-
tion returns the equivalent ASCII value for the character entered. There is no need
to add ctype.h to use the getch function.
240 12 Character Processing

Let’s study an example. Run the following code:


#include <stdio.h>

int main()
{
printf("Please enter a character...\n");
printf("Passed value by the User is: %c", getch()); // print a character entered
by the user
return 0;
}

After running the code, the message shown in Fig. 12.15 appears on the screen
and waits to receive a character from the keyboard.

Fig. 12.15 Output of the code

After pressing a key, the second printf runs and shows the character (Fig. 12.16).

Fig. 12.16 Output of the code

Further Reading

1. Deitel P, Deitel H (2022) C how to program: with case studies in applications and systems
programming, 9th edn. Pearson, London
Chapter 13
Time and Date

13.1 Introduction

This chapter studies some of the ready-to-use functions to work with date and time.

13.2 Making Delay with Sleep Function

Sleep function allows the users to wait for a current thread for a specific time. Let’s
study an example. The following code prints three messages on the screen. There is
a five-second delay between printings. Output of this code is shown in Figs. 13.1,
13.2, and 13.3.
#include <stdio.h>
#include <Windows.h> //Don’t forget this header

int main()
{
printf("Hello ");
Sleep(5000); //sleep for 5000 ms.
printf("World...\n");
Sleep(5000); //sleep for 5000 ms.
printf("C programming is fun!");
}

© The Author(s), under exclusive license to Springer Nature Switzerland AG 2023 241
F. Asadi, Essentials of C Programming with Microsoft® Visual Studio®,
https://doi.org/10.1007/978-3-031-35711-4_13
242 13 Time and Date

Fig. 13.1 Output of the code

Fig. 13.2 Output of the code

Fig. 13.3 Output of the code


13.4 time Function 243

13.3 Time Measurement

The clock function returns the number of clock ticks elapsed since the program was
launched. To get the number of seconds used by the CPU, you will need to divide
by CLOCKS_PER_SEC.
Let’s study an example. The following code measure the required time to count
from 0 up to 1000000000-1=999999999. Output of this code is shown in Fig. 13.4.
The number shown on the output depends on the CPU speed and changes from
computer to computer.
#define _CRT_SECURE_NO_WARNINGS 1
#include <stdio.h>
#include <time.h>

int main()
{
clock_t start, end;
start = clock();

for (int i = 0; i < 1000000000; i++) {}; //dummy counter

end = clock();

double deltaT = (double)(end - start) / CLOCKS_PER_SEC;


//CLOCKS_PER_SEC is defined in time.h
printf("Required Time: %f s\n", deltaT);
return 0;
}

Fig. 13.4 Output of the code

13.4 time Function

The time function returns the time since 00:00:00 UTC, January 1, 1970 (Unix
timestamp) in seconds. The prototype of this function is time_t time( time_t* sec-
ond). This function accepts single parameter second. This parameter is used to set
the time_t object which store the time. If second is not a null pointer, the returned
value is also stored in the object pointed to by second.
Following is an example. Output of this code is shown in Fig. 13.5.
244 13 Time and Date

#include <stdio.h>
#include <Windows.h>
#include <time.h>

int main()
{
printf("Program started...\n");
time_t now1 = time(NULL); // number of seconds since Jan. 1, 1970 midnight
printf("value of now1 is equal to %ld\n", now1);
Sleep(3000);
printf("Now 3 seconds passed...\n");
time_t now2 = time(NULL);
printf("value of now2 is equal to %ld\n", now2);
printf("Difference between now2 and now1 variables is: %f sec.", difftime(now2,
now1)); // difftime returns the difference of now2-now1 as a double value in seconds
return 0;
}

Fig. 13.5 Output of the code

The following code equals to the previous one.


#include <stdio.h>
#include <Windows.h>
#include <time.h>

int main()
{
printf("Program started...\n");
time_t now1 = time(NULL); // number of seconds since Jan. 1, 1970 midnight
printf("value of now1 is equal to %ld\n", now1);
Sleep(3000); // waits for 3000 ms
printf("Now 3 seconds passed...\n");
time_t now2 = time(NULL);
printf("value of now2 is equal to %ld\n", now2);
printf("Difference between now2 and now1 variables is: %d sec.", now2-now1);
return 0;
}

13.5 Date and Time

The prototype of ctime function is char* ctime(const time_t* timer). This function
returns a string representing the local time based on the argument timer. The format
of returned string is Www Mmm dd hh:mm:ss yyyy. Where Www is the weekday,
13.6 gmtime Function 245

Mmm the month (in letters), dd the day of the month, hh:mm:ss the time, and yyyy
the year. The string is followed by a new-line character (“\n”) and terminated with a
null-character.
Following is an example. Output of this function is shown in Fig. 13.6.
#define _CRT_SECURE_NO_WARNINGS 1
#include <stdio.h>
#include <time.h>

int main()
{
time_t now = time(NULL);
char* string_now = ctime(&now);
printf("%s\n", string_now);

return 0;
}

Fig. 13.6 Output of the code

13.6 gmtime Function

The gmtime function has the prototype of struct tm* gmtime(const time_t* timer).
It uses the value pointed by timer to fill a tm structure with the values that represent
the corresponding time, expressed in Coordinated Universal Time (UTC) or GMT
time zone.
This function returns a pointer to a tm structure with the time information filled
in. Fields of the tm structure are:
struct tm {
int tm_sec; /* seconds, range 0 to 59 */
int tm_min; /* minutes, range 0 to 59 */
int tm_hour; /* hours, range 0 to 23 */
int tm_mday; /* day of the month, range 1 to 31 */
int tm_mon; /* month, range 0 to 11, January=0 */
int tm_year; /* The number of years since 1900 */
int tm_wday; /* day of the week, range 0 to 6;Sunday=0 */
int tm_yday; /* day in the year, range 0 to 365, Jan 1=0 */
int tm_isdst; /* daylight saving time */
};

Following is an example. Output of this code is shown in Fig. 13.7.


246 13 Time and Date

#define _CRT_SECURE_NO_WARNINGS 1
#include <stdio.h>
#include <time.h>

int main()
{
time_t now = time(NULL);
char* string_now = ctime(&now);
printf("%s\n", string_now);

struct tm *gm_time=gmtime(&now);
printf("tm_hour: %d\n", gm_time->tm_hour);
printf("tm_min : %d\n", gm_time->tm_min);
printf("tm_sec : %d\n", gm_time->tm_sec);

printf("Note: The time printed above is printed according\n");


printf("to GMT time. Therefore your computer time and what\n");
printf("you see here may not be the same.\n");

printf("\ntm_mday (day of month): %d\n", gm_time->tm_mday);


printf("tm_mon (month, 0-11, January=0): %d\n", gm_time->tm_mon);
printf("tm_year: %d\n", 1900+gm_time->tm_year);
//tm_year gives the year relative to 1900,
//add 1900 to get the correct year

printf("\ntm_wday (Day of week,0-6, Sunday=0): %d\n", gm_time->tm_wday);


printf("tm_yday: %d\n", 1+gm_time->tm_yday);
//add 1 to gm_time->tm_yday to obtain the correct day of year
//since tm_yday gives the day of year in 0-365 range. note that 1 January=0.
printf("tm_isdst: %d\n", gm_time->tm_isdst);

return 0;
}

Fig. 13.7 Output of the code


13.7 localtime Function 247

13.7 localtime Function

The localtime function has the prototype of struct tm* localtime(const time_t*
timer). It uses the value pointed by timer to fill a tm structure with the values that
represent the corresponding local time.
This function returns a pointer to a tm structure with the time information filled
in. Fields of the tm structure are:
struct tm {
int tm_sec; /* seconds, range 0 to 59 */
int tm_min; /* minutes, range 0 to 59 */
int tm_hour; /* hours, range 0 to 23 */
int tm_mday; /* day of the month, range 1 to 31 */
int tm_mon; /* month, range 0 to 11, January=0 */
int tm_year; /* The number of years since 1900 */
int tm_wday; /* day of the week, range 0 to 6;Sunday=0 */
int tm_yday; /* day in the year, range 0 to 365, Jan 1=0 */
int tm_isdst; /* daylight saving time */
};

Following is an example. Output of this code is shown in Fig. 13.8.


#define _CRT_SECURE_NO_WARNINGS 1
#include <stdio.h>
#include <time.h>

int main()
{
time_t now = time(NULL);
char* string_now = ctime(&now);
printf("%s\n", string_now);

struct tm *cur_time=localtime(&now);
printf("tm_hour: %d\n", cur_time->tm_hour);
printf("tm_min : %d\n", cur_time->tm_min);
printf("tm_sec : %d\n", cur_time->tm_sec);

printf("Note: The time printed above is local time of\n");


printf("your computer.\n");

printf("\ntm_mday (day of month): %d\n", cur_time->tm_mday);


printf("tm_mon (month, 0-11, January=0): %d\n", cur_time->tm_mon);
printf("tm_year: %d\n", 1900+cur_time->tm_year);
//tm_year gives the year relative to 1900,
//add 1900 to get the correct year

printf("\ntm_wday (Day of week,0-6, Sunday=0): %d\n", cur_time->tm_wday);


printf("tm_yday: %d\n", 1+cur_time->tm_yday);
//add 1 to cur_time->tm_yday to obtain the correct day of year
//since tm_yday gives the day of year in 0-365 range. note that 1 January=0.
printf("tm_isdst: %d\n", cur_time->tm_isdst);

return 0;
}
248 13 Time and Date

Fig. 13.8 Output of the code

13.8 asctime Function

The asctime function has the prototype of char* asctime(const struct tm* timeptr)
and returns a pointer to a string which represents the day and time of the timeptr.
The timeptr is a pointer to tm structure that contains a calendar time broken down
into its components as shown below:
struct tm {
int tm_sec; /* seconds, range 0 to 59 */
int tm_min; /* minutes, range 0 to 59 */
int tm_hour; /* hours, range 0 to 23 */
int tm_mday; /* day of the month, range 1 to 31 */
int tm_mon; /* month, range 0 to 11, January=0 */
int tm_year; /* The number of years since 1900 */
int tm_wday; /* day of the week, range 0 to 6;Sunday=0 */
int tm_yday; /* day in the year, range 0 to 365, Jan 1=0 */
int tm_isdst; /* daylight saving time */
};

Following is an example. Output of this code is shown in Fig. 13.9.


#define _CRT_SECURE_NO_WARNINGS 1
#include <stdio.h>
#include <time.h>

int main()
{
time_t now = time(NULL);
struct tm* cur_time = localtime(&now);
char* string1 = asctime(cur_time);
//asctime works with struct tm type.
printf("%s\n", string1);

return 0;
}
13.9 strftime Function 249

Fig. 13.9 Output of the code

13.9 strftime Function

The strftime function has the prototype size_t strftime(char* str, size_t maxsize,
const char* format, const struct tm* timeptr). This function formats the time repre-
sented in the structure timeptr according to the formatting rules defined in format
and stored into str. Table 13.1 shows the formatting specifiers that can be used.

Table 13.1 Format specifiers


Specifier Replaced by
%a Abbreviated weekday name
%A Full weekday name
%b Abbreviated month name
%B Full month name
%c Date and time representation
%d Day of the month (01-31)
%H Hour in 24h format (00-23)
%I Hour in 12h format (01-12)
%j Day of the year (001-366)
%m Month as a decimal number (01-12)
%M Minute (00-59)
%p AM or PM designation
%S Second (00-59)
%U Week number with the first Sunday as the first day of week
one (00-53)
%w Weekday as a decimal number with Sunday as 0 (0-6)
%W Week number with the first Monday as the first day of week
one (00-53)
%x Date representation
%X Time representation
%y Year, last two digits (00-99)
%Y Year
%Z Timezone name or abbreviation
%% A % sign
250 13 Time and Date

Following is an example. Output of this code shown in Fig. 13.10.


#define _CRT_SECURE_NO_WARNINGS 1
#include <stdio.h>
#include <time.h>

int main()
{
time_t now = time(NULL);
struct tm* cur_time = localtime(&now);

char s[128]; // s is a buffer big enough to save output of commands. 128 is


good.
// see: https://bit.ly/2Y225xG
strftime(s, 128, "Date (mm.dd.yy): %x\nTime is: %X", cur_time);
printf("%s", s);

return 0;
}

Fig. 13.10 Output of the code

13.10 _strtime and _strdate Functions

The _strtime function has the prototype of char* _strtime(char* timestr). This func-
tion copies the current local time into the buffer pointed to by timestr. The time is
formatted as hh:mm:ss, where hh is two digits that represent the hour in 24-hour
notation, mm is two digits for the minutes past the hour, and ss is two digits for
seconds. For example, the string 18:23:44 represents 23 minutes and 44 seconds
after 6 P.M. The buffer must be at least 9 bytes long.
The _strdate function has the prototype of char* _strdate(char* datestr). This
function copies the current system date to the buffer pointed to by datestr, formatted
mm/dd/yy, where mm is two digits representing the month, dd is two digits repre-
senting the day, and yy is the last two digits of the year. For example, the string
01/04/99 represents January 04, 2023. The buffer must be at least 9 bytes long.
Following is an example. Output of this code is shown in Fig. 13.11.
Further Reading 251

#define _CRT_SECURE_NO_WARNINGS 1
#include <stdio.h>

int main()
{

char tmpbuf[128];
_strtime(tmpbuf, 128);
printf("OS time is (hh:mm:ss): %s\n", tmpbuf);

_strdate(tmpbuf, 128);
printf("OS date is (mm/dd/yy): %s\n", tmpbuf);

return 0;
}

Fig. 13.11 Output of the code

Further Reading

1. Hart JM (2010) Windows system programming. Addison-Wesley, Upper Saddle River


Chapter 14
Sorting and Searching

14.1 Introduction

In computer science, a sorting algorithm is an algorithm that puts elements of a list


into an order. The most frequently used orders are numerical order and lexicograph-
ical order, and either ascending or descending.
This chapter studies some of the sorting algorithms and their C implementations.
In most of the real world problems, quick sort is used if the size of array is big.

14.2 Bubble Sort

The bubble sort is not an efficient method to sort an array if the array size is big.
However, coding the bubble sort algorithm is a good programming practice. Suppose
we are trying to sort the elements in an ascending order using bubble sort. Here are
the steps of first Iteration (Compare and Swap) for bubble sort (Fig. 14.1):
(a) Starting from the first index, compare the first and the second elements.
(b) If the first element is greater than the second element, they are swapped.
(c) Now, compare the second and the third elements. Swap them if they are not
in order.
(d) The above process goes on until the last element.

© The Author(s), under exclusive license to Springer Nature Switzerland AG 2023 253
F. Asadi, Essentials of C Programming with Microsoft® Visual Studio®,
https://doi.org/10.1007/978-3-031-35711-4_14
254 14 Sorting and Searching

Fig. 14.1 Compare step = 0


the adjacent elements

i=0 –2 45 0 11 –9

i=1 –2 45 0 11 –9

i=2 –2 0 45 11 –9

i=3 –2 0 11 45 –9

–2 0 11 –9 45

The same process goes on for the remaining iterations. After each iteration, the
largest element among the unsorted elements is placed at the end (Fig. 14.2).

Fig. 14.2 Put the largest step = 1


element at the end

i=0 –2 0 11 –9 45

i=1 –2 0 11 –9 45

i=2 –2 0 11 –9 45

–2 0 –9 11 45
14.2 Bubble Sort 255

In each iteration, the comparison takes place up to the last unsorted element
(Fig. 14.3).

Fig. 14.3 Compare the step = 2


adjacent elements

i=0 –2 0 –9 11 45

i=1 –2 0 –9 11 45

–2 –9 0 11 45

The array is sorted when all the unsorted elements are placed at their correct
positions (Fig. 14.4).

Fig. 14.4 The array is sorted if step = 3


all elements are kept in the right
order

i=0 –2 –9 0 11 45

–9 –2 0 11 45

The following code uses bubble sort to sort the array a. Functions a_bubble_sort
and d_bubble_sort sort the array in ascending and descending orders, respectively.
Output of this code is shown in Fig. 14.5.
256 14 Sorting and Searching

#include <stdio.h>
void a_bubble_sort(int a[], int length); //ascending sort
void d_bubble_sort(int a[], int length); //descending sort

int main() {
int a[] = { 7,1,3,9,0,2,4,5,8,6};
int length = sizeof(a) / sizeof(a[0]);

a_bubble_sort(a, length);
printf("ascending order : ");
for (int i = 0; i < length; i++)
{
printf("%d ", a[i]);
}

d_bubble_sort(a, length);
printf("\ndescending order: ");
for (int i = 0; i < length; i++)
{
printf("%d ",a[i]);
}

return 0;
}

void a_bubble_sort(int a[], int length)


{
for (int i = 0; i < length; i++)
{
for (int j = 0; j < (length - 1); j++)
{
if (a[j] > a[j + 1])
{
int temp = a[j];
a[j] = a[j + 1];
a[j + 1] = temp;
}
}
}
}

void d_bubble_sort(int a[], int length)


{
for (int i = 0; i < length; i++)
{
for (int j = 0; j < (length - 1); j++)
{
if (a[j] < a[j + 1])
{
int temp = a[j];
a[j] = a[j + 1];
a[j + 1] = temp;
}
}
}
}
14.2 Bubble Sort 257

Fig. 14.5 Output of the code

The following code is an optimized version of the previous code. Output of this
code is shown in Fig. 14.6.
258 14 Sorting and Searching

#include <stdio.h>
#include <stdbool.h>

void a_bubble_sort(int a[], int length); //ascending sort


void d_bubble_sort(int a[], int length); //descending sort

int main() {
int a[] = { 7,1,3,9,0,2,4,5,8,6};
int length = sizeof(a) / sizeof(a[0]);

a_bubble_sort(a, length);
printf("ascending order : ");
for (int i = 0; i < length; i++)
{
printf("%d ", a[i]);
}

d_bubble_sort(a, length);
printf("\ndescending order: ");
for (int i = 0; i < length; i++)
{
printf("%d ",a[i]);
}

return 0;
}

void a_bubble_sort(int a[], int length)


{
bool swapped = false;
int i = 0;
do
{
swapped = false;
for (int j = 0; j < (length - 1 - i); j++)
{
if (a[j] > a[j + 1])
{
int temp = a[j];
a[j] = a[j + 1];
a[j + 1] = temp;
swapped = true;
}
}
i++;
} while (swapped);
}

void d_bubble_sort(int a[], int length)


{
bool swapped = false;
int i = 0;
do
{
swapped = false;
for (int j = 0; j < (length - 1 - i); j++)
{
if (a[j] < a[j + 1])
{
int temp = a[j];
a[j] = a[j + 1];
a[j + 1] = temp;
swapped = true;
}
}
i++;
} while (swapped);
}
14.3 Insertion Sort 259

Fig. 14.6 Output of the code

14.3 Insertion Sort

Insertion sort is a sorting algorithm that places an unsorted element at its suitable
place in each iteration. Insertion sort works similarly as we sort cards in our hand in
a card game. We assume that the first card is already sorted, then we select an
unsorted card. If the unsorted card is greater than the card in hand, it is placed on the
right, otherwise, to the left. In the same way, other unsorted cards are taken and put
in their right place. A similar approach is used by insertion sort.
Let’s study an example. Suppose we need to sort the array shown in Fig. 14.7 in
an ascending order using the insertion sort.

Fig. 14.7 Initial array

The first element in the array is assumed to be sorted. Take the second element
and store it separately in key.
Compare key with the first element. If the first element is greater than key, then
key is placed in front of the first element (Fig. 14.8).

Fig. 14.8 If the first


element is greater than key,
then key is placed in front
of the first element
260 14 Sorting and Searching

Now, the first two elements are sorted. Take the third element and compare it
with the elements on its left. Place it just behind the element smaller than it. If there
is no element smaller than it, then place it at the beginning of the array (Fig. 14.9).

Fig. 14.9 1 is selected


as key

Similarly, place every unsorted element at its correct position (Figs. 14.10
and 14.11).
14.3 Insertion Sort 261

Fig. 14.10 Place 4


behind 1

Fig. 14.11 Place 3 behind


1 and the array is sorted
262 14 Sorting and Searching

The following code uses insertion sort to sort the array a in an ascending order.
Output of this code is shown in Fig. 14.12.
#define _CRT_SECURE_NO_WARNINGS

#include <stdio.h>

void insertion_sort(int a[], int length);

int main() {
int a[] = { 8,4,9,5,7,6,3,2 };
insertion_sort(a, sizeof(a) / sizeof(a[0]));

printf("sorted array: ");


for (int i = 0; i < sizeof(a) / sizeof(a[0]); i++)
printf("%d ", a[i]);
return 0;
}

void insertion_sort(int a[], int length)


{
for (int i = 1; i < length; i++)
{
int key = a[i];
int j = i - 1;

while (j >= 0 && a[j] > key)


{
a[j + 1] = a[j];
j = j - 1;
}
a[j + 1] = key;
}
}

Fig. 14.12 Output of the code

14.4 Quick Sort Algorithm

Quicksort is an efficient, general-purpose sorting algorithm. Quicksort was devel-


oped by British computer scientist Tony Hoare in 1959 and published in 1961. It is
still a commonly used algorithm for sorting.
Quicksort is a divide-and-conquer algorithm. It works by selecting a “pivot” ele-
ment from the array and partitioning the other elements into two sub-arrays, accord-
ing to whether they are less than or greater than the pivot. For this reason, it is
sometimes called partition-­exchange sort. The sub-arrays are then sorted recur-
sively. This can be done in-place, requiring small additional amounts of memory to
perform the sorting.
14.5 Quick Sort for Integer Values 263

The theory of quick sort algorithm is explained in [?-?].

14.5 Quick Sort for Integer Values

The following code uses the qsort function (which is defined in the stdlib.h header
file) to arrange the integer array values in an ascending order. Output of this code is
shown in Fig. 14.13.
#include <stdio.h>
#include <stdlib.h>

int values[] = { 88, 56, 100, 2, 25, 7, 26, 45,-3 };

int cmpfunc(const void* a, const void* b);

int main() {

int N = sizeof(values) / sizeof(values[0]);

printf("Before sorting the list is: \n");


for (int i = 0; i < N; i++) {
printf("%d ", values[i]);
}

qsort(values, N, sizeof(int), cmpfunc);

printf("\nAfter sorting the list is: \n");


for (int i = 0; i < N; i++) {
printf("%d ", values[i]);
}

return(0);
}

int cmpfunc(const void* a, const void* b) {


return (*(int*)a - *(int*)b);
}

Fig. 14.13 Output of the code


264 14 Sorting and Searching

The following code uses the qsort function to arrange the integer array values in
a descending order. Output of this code is shown in Fig. 14.14.
#include <stdio.h>
#include <stdlib.h>

int values[] = { 88, 56, 100, 2, 25, 7, 26, 45,-3 };

int cmpfunc(const void* a, const void* b);

int main() {

int N = sizeof(values) / sizeof(values[0]);

printf("Before sorting the list is: \n");


for (int i = 0; i < N; i++) {
printf("%d ", values[i]);
}

qsort(values, N, sizeof(int), cmpfunc);

printf("\nAfter sorting the list is: \n");


for (int i = 0; i < N; i++) {
printf("%d ", values[i]);
}

return(0);
}

int cmpfunc(const void* a, const void* b) {


return (*(int*)b - *(int*)a);
}

Fig. 14.14 Output of the code

14.6 Quick Sort for Double Values

The following code uses the qsort function to arrange the double array values in an
ascending order. Output of this code is shown in Fig. 14.15.
14.6 Quick Sort for Double Values 265

#include <stdio.h>
#include <stdlib.h>

double values[] = { 88.3, 56.5, 100.4, 2.0, 0.25, 7.63, 26.41, 45.22,-3.04 };

int cmpfunc(const void* a, const void* b);

int main() {

int N = sizeof(values) / sizeof(values[0]);

printf("Before sorting the list is: \n");


for (int i = 0; i < N; i++) {
printf("%.2f ", values[i]);
}

qsort(values, N, sizeof(double), cmpfunc);

printf("\nAfter sorting the list is: \n");


for (int i = 0; i < N; i++) {
printf("%.2f ", values[i]);
}

return(0);
}

int cmpfunc(const void* a, const void* b)


{
if (*(double*)a > *(double*)b)
return 1;
else if (*(double*)a < *(double*)b)
return -1;
else
return 0;
}

Fig. 14.15 Output of the code

The following code uses the qsort function to arrange the double array values in
a descending order. Output of this code is shown in Fig. 14.16.
266 14 Sorting and Searching

#include <stdio.h>
#include <stdlib.h>

double values[] = { 88.3, 56.5, 100.4, 2.0, 0.25, 7.63, 26.41, 45.22,-3.04 };

int cmpfunc(const void* a, const void* b);

int main() {

int N = sizeof(values) / sizeof(values[0]);

printf("Before sorting the list is: \n");


for (int i = 0; i < N; i++) {
printf("%.2f ", values[i]);
}

qsort(values, N, sizeof(double), cmpfunc);

printf("\nAfter sorting the list is: \n");


for (int i = 0; i < N; i++) {
printf("%.2f ", values[i]);
}

return(0);
}

int cmpfunc(const void* a, const void* b)


{
if (*(double*)a > *(double*)b)
return -1;
else if (*(double*)a < *(double*)b)
return 1;
else
return 0;
}

Fig. 14.16 Output of the code

14.7 Quick Sort for Strings

The following code uses the qsort function to arrange the string array cities in an
ascending order. Output of this code is shown in Fig. 14.17.
14.7 Quick Sort for Strings 267

#include <stdio.h>
#include <stdlib.h>

char* cities[] = { "new york", "new york", "New York", "Los Angeles",
"chicago", "Houston", "phoenix", "Dallas", "Texas" };

int sortstring(const void* str1, const void* str2);

int main() {

int N = sizeof(cities) / sizeof(char*);

printf("Before sorting the list is: \n");


for (int i = 0; i < N; i++) {
printf("%s, ", cities[i]);
}

qsort(cities, sizeof(cities) / sizeof(char*), sizeof(char*), sortstring);

printf("\n\nAfter sorting the list is: \n");


for (int i = 0; i < N; i++) {
printf("%s, ", cities[i]);
}

return(0);
}

int sortstring(const void* str1, const void* str2)


{
char* const* pp1 = str1;
char* const* pp2 = str2;
return strcmp(*pp1, *pp2);
}

Fig. 14.17 Output of the code

The following code uses the qsort function to arrange the string array cities in a
descending order. Output of this code is shown in Fig. 14.18.
268 14 Sorting and Searching

#include <stdio.h>
#include <stdlib.h>

char* cities[] = { "new york", "new york", "New York", "Los Angeles",
"chicago", "Houston", "phoenix", "Dallas", "Texas" };

int sortstring(const void* str1, const void* str2);

int main() {

int N = sizeof(cities) / sizeof(char*);

printf("Before sorting the list is: \n");


for (int i = 0; i < N; i++) {
printf("%s, ", cities[i]);
}

qsort(cities, sizeof(cities) / sizeof(char*), sizeof(char*), sortstring);

printf("\n\nAfter sorting the list is: \n");


for (int i = 0; i < N; i++) {
printf("%s, ", cities[i]);
}

return(0);
}

int sortstring(const void* str1, const void* str2)


{
char* const* pp1 = str1;
char* const* pp2 = str2;
return strcmp(*pp2, *pp1);
}

Fig. 14.18 Output of the code

14.8 Binary Search

Binary search is a searching algorithm for finding an element’s position in a sorted


array. In this approach, the element is always searched in the middle of a portion of
an array. Binary search can be implemented only on a sorted list of items. If the ele-
ments are not yet sorted, we need to sort them first.
Binary Search Algorithm can be implemented in two ways, as follows:
1. Iterative Method
2. Recursive Method
14.8 Binary Search 269

The recursive method follows the divide-and-conquer approach. The general


steps for both methods are discussed below. The array in which searching is to be
performed is shown in Fig. 14.19.

Fig. 14.19 Initial array

Let x = 4 be the element to be searched. Set two pointers low and high at the
lowest and the highest positions, respectively (Fig. 14.20).

Fig. 14.20 Setting


pointers

Find the middle element mid of the array, i.e., arr[(low + high)/2] =
arr[(0+6)/2]=arr[3]=6 (Fig. 14.21).

Fig. 14.21 Mid element

If x == mid, then return mid. Else, compare the element to be searched with mid.
If x > mid, compare x with the middle element of the elements on the right side
of mid. This is done by setting low to low = mid + 1.
Else, compare x with the middle element of the elements on the left side of mid.
This is done by setting high to high = mid – 1 (Fig. 14.22).

Fig. 14.22 Finding mid


element

Repeat steps 3 to 6 until low meets high. x=4 is found (Fig. 14.23).

Fig. 14.23 x=4 is found


270 14 Sorting and Searching

The iterative implementation of binary search is shown below. Sample output of


this code is shown in Fig. 14.24. This code returns -1 when the element is not in
the array.
//Iterative implementation of binary search

//This code searches the array sorted

#define _CRT_SECURE_NO_WARNINGS

#include <stdio.h>

int binary_search(int a[], int e, int l, int r); // a is the array


// e is the element we are looking
for
// l is the left index (H in Fig.
14.20)
// r is the right index (L in Fig.
14.20)

int main() {
int sorted[] = { 1,2,3,4,5,6,7,8,9,10,11,12,13 };

int n = 0;

printf("enter -1 to exit\n");
do
{
printf("\nplease enter the number that you want to be searched : ");
scanf("%d", &n);

printf("index of %d is %d\n", n, binary_search(sorted, n, 0, 12));


} while (n != -1);

return 0;
}

int binary_search(int a[], int e, int l, int r)


{
while (l<= r) {
int mid = l + (r - l) / 2;

if (a[mid] == e)
return mid;

if (a[mid] < e)
l = mid + 1;

else
r = mid - 1;
}

return -1;
}
14.8 Binary Search 271

Fig. 14.24 Output of the code

The recursive implementation of binary search is shown below. Sample output of


this code is shown in Fig. 14.25. This code returns -1 when the element is not in
the array.
272 14 Sorting and Searching

//Recursive implementation of binary search

//This code searches the array sorted

#define _CRT_SECURE_NO_WARNINGS

#include <stdio.h>

int binary_search(int a[], int e, int l, int r); // a is the array


// e is the element we are looking
for
// l is the left index (H in Fig.
14.20)
// r is the right index (L in Fig.
14.20)

int main() {
int sorted[] = {1,2,3,4,5,6,7,8,9,10,11,12,13};

int n = 0;

printf("enter -1 to exit\n");
do
{
printf("\nplease enter the number that you want to be searched : ");
scanf("%d", &n);

printf("index of %d is %d\n", n, binary_search(sorted, n, 0, 12));


} while (n != -1);

return 0;
}

int binary_search(int a[], int e, int l, int r)


{
int mid = l + (r - l) / 2; // index for midpoint from left index to right index

if (l > r) return -1; //shows that element doesn't exist in the list

if (a[mid] == e)
return mid;
else if (a[mid] > e)
return binary_search(a, e, l, mid - 1);
else
return binary_search(a, e, mid+1, r);
}

Fig. 14.25 Output of the code


Further Reading 273

Further Reading

1. Deitel P, Deitel H (2022) C how to program: with case studies in applications and systems
programming, 9th edn. Pearson, London
Chapter 15
File Processing

15.1 Introduction

A file represents a sequence of bytes on the disk where a group of related data is
stored. File is created for permanent storage of data. Files permit you to easily move
your data from one computer to another without any changes as well.
When dealing with files, there are two types of files you should know about: text
files and binary files.
Text files are the normal .txt files. You can easily create text files using any sim-
ple text editors such as Notepad. When you open those files, you will see all the
contents within the file as plain text. You can easily edit or delete the contents. They
take minimum effort to maintain, are easily readable, but provide the least security
and take bigger storage space.
Binary files are mostly the .bin files in your computer. Instead of storing data in
plain text, they store it in the binary form (0s and 1s). They can hold a higher amount
of data, are not readable easily, and provides better security than text files.
This chapter studies the files.

15.2 Creating a New File

When working with files, you need to declare a pointer of type file: FILE* fptr;
opening a file is performed using the fopen function defined in the stdio.h header
file. The syntax for opening a file in standard I/O is: fptr = fopen("PathAndFileNam
e","mode"). The different types of opening modes are shown in Table 15.1.

© The Author(s), under exclusive license to Springer Nature Switzerland AG 2023 275
F. Asadi, Essentials of C Programming with Microsoft® Visual Studio®,
https://doi.org/10.1007/978-3-031-35711-4_15
276 15 File Processing

Table 15.1 Opening modes


Mode Meaning of mode During inexistence of file
r Open for reading If the file does not exist, fopen returns NULL
rb Open for reading in binary mode If the file does not exist, fopen returns NULL
w Open for writing If the file exists, its contents are overwritten (its
contents will be removed). If the file does not exist, it
will be created
wb Open for writing in binary mode If the file exists, its contents are overwritten. If the
file does not exist, it will be created
a Open for append. Data is added If the file does not exist, it will be created
to the end of the file
ab Open for append in binary mode. If the file does not exist, it will be created
Data is added to the end of the
file
r+ Open for both reading and If the file does not exist, fopen returns NULL
writing
rb+ Open for both reading and If the file does not exist, fopen returns NULL
writing in binary mode
w+ Open for both reading and If the file exists, its contents are overwritten. If the
writing file does not exist, it will be created
wb+ Open for both reading and If the file exists, its contents are overwritten. If the
writing in binary mode file does not exist, it will be created
a+ Open for both reading and If the file does not exist, it will be created
appending
ab+ Open for both reading and If the file does not exist, it will be created
appending in binary mode

The file (both text and binary) should be closed (using the fclose function) after
reading/writing. Let’s study an example. In the following code, a text file in D:\ path
with name io.txt is opened for writing. Then the fputs function writes a string to the
specified stream up to but not including the null character. After running the code,
open the io.txt and ensure that Hello World is written there (Fig. 15.1).
#define _CRT_SECURE_NO_WARNINGS

#include <stdio.h>

main(void)
{
FILE* fh_output; //file handle
fh_output = fopen("D:\\io.txt", "w"); //"w" open the file for writing
//if io.txt doesn't exists, it will create
it.
//if io.txt does exist, it will delete
everything there.
fputs("Hello \nWorld!", fh_output);

fclose(fh_output);
return 0;
}
15.2 Creating a New File 277

Fig. 15.1 Contents of


io.txt

Following is another example. Output of this code is shown in Fig. 15.2.


#define _CRT_SECURE_NO_WARNINGS

#include <stdio.h>

main(void)
{
FILE* fh_output;
fh_output = fopen("D:\\io.txt", "w");
fputs("Hello", fh_output);
fputs("World", fh_output);
fputs("!", fh_output);

fclose(fh_output);
return 0;
}

Fig. 15.2 Contents of


io.txt

Let’s study another example. The following code shows how to handle the errors.
Note that when NULL is returned, an error is occurred.
278 15 File Processing

#define _CRT_SECURE_NO_WARNINGS

#include <stdio.h>
#include <errno.h>
#include <string.h>

extern int errno; //errno is defined in the errno.h

main(void)
{
FILE* fh_output;
fh_output = fopen("C:\\io.txt", "w");

if (fh_output == NULL)
{
printf("Error Message: %s\n", strerror(errno));
return 1;
}
else {
fputs("Hello \nWorld!", fh_output);
fclose(fh_output);
}

return 0;
}

15.3 Append Mode

In append mode, the previous contents of the file are not affected. New data will be
written to the end of the file. Let’s study an example. The following code opens the
D:\io.txt in the append mode. You will obtain the result shown in Fig. 15.3 if you run
the code twice.
#define _CRT_SECURE_NO_WARNINGS

#include <stdio.h>

main(void)
{
FILE* fh_output;
fh_output = fopen("D:\\io.txt", "a");
fputs("Hello World!\n", fh_output);
fclose(fh_output);

return 0;
}

Fig. 15.3 Contents of


io.txt
15.5 fprintf Function 279

15.4 ftell Function

ftell returns the current file position of the given stream. Following is an example.
Output of this code and content of io.txt are shown in Figs. 15.4 and 15.5,
respectively.
#define _CRT_SECURE_NO_WARNINGS

#include <stdio.h>

main(void)
{
FILE* fh_output; //file handle
fh_output = fopen("D:\\io.txt", "w");
printf("current location of cursor: %d.\n", ftell(fh_output));

fputs("Hello \nWorld!", fh_output);


printf("current location of cursor: %d.\n", ftell(fh_output));

fclose(fh_output);
return 0;
}

Fig. 15.4 Output of the code

Fig. 15.5 Contents of


io.txt

15.5 fprintf Function

fprintf function sends formatted output to a stream. Format specifiers are shown in
Table 15.2.
280 15 File Processing

Table 15.2 Format specifiers Specifier Description


%c Character
%d or %i Signed decimal integer
%e Scientific notation (mantissa/
exponent) using e character
%E Scientific notation (mantissa/
exponent) using E character
%f Decimal floating point
%g Uses the shorter of %e or %f
%G Uses the shorter of %E or %f
%o Signed octal
%s String of characters
%u Unsigned decimal integer
%x Unsigned hexadecimal integer
%X Unsigned hexadecimal integer
(capital letters)
%p Pointer address

Following is an example. Output of this code is shown in Fig. 15.6.


#define _CRT_SECURE_NO_WARNINGS

#include <stdio.h>

main(void)
{
FILE* fh_output;
fh_output = fopen("D:\\io.txt", "w");
int a = 10;
float b = 20.30;
char c = 'x';

fprintf(fh_output, "value of a=%d, b=%.2f and c=%c", a, b, c);

fclose(fh_output);
return 0;
}

Fig. 15.6 Contents of


io.txt
15.6 fseek Function 281

15.6 fseek Function

fseek function sets the file position of the stream to the given offset. The prototype
of this function is int fseek(FILE *stream, long int offset, int whence). The descrip-
tion of parameters are given below:
stream: This is the pointer to a FILE object that identifies the stream.
offset: This is the number of bytes to offset from whence.
whence: This is the position from where offset is added. It is specified by one of
the constants shown in Table 15.3.

Table 15.3 Constants used No. Description


with fseek function 1 SEEK_SET : Beginning of file
2 SEEK_CUR : Current position
of the file pointer
3 SEEK_END : End of file

Following is an example. Output of this code is shown in Fig. 15.7.


#define _CRT_SECURE_NO_WARNINGS

#include <stdio.h>

main(void)
{
FILE* file;
file= fopen("D:\\file.txt", "w");

if (file == NULL)
{
printf("Error opening file.\n");
return 1;
}

fprintf(file, "abcdefgh\n");
fprintf(file, "ijklmnop");

fseek(file, 0, SEEK_SET);
fprintf(file, "qrstuvwx\n");

fclose(file);
return 0;
}

Fig. 15.7 Contents of


file.txt
282 15 File Processing

Following is another example. Output of this code is shown in Fig. 15.8.


#define _CRT_SECURE_NO_WARNINGS

#include <stdio.h>

main(void)
{
FILE* file;
file = fopen("D:\\file.txt", "w");

if (file == NULL)
{
printf("Error opening file.\n");
return 1;
}

fprintf(file, "abcdefgh\n");
fprintf(file, "ijklmnop");

fseek(file, -3, SEEK_CUR); // 3 places before the current location


fprintf(file, "+");
fseek(file, +5, SEEK_CUR); // 5 places after the current location
fprintf(file, "&");

fclose(file);
return 0;
}

Fig. 15.8 Contents of


file.txt
15.7 rewind Function 283

Following is another example. Output of this code is shown in Fig. 15.9.


#define _CRT_SECURE_NO_WARNINGS

#include <stdio.h>

main(void)
{
FILE* file;
file = fopen("D:\\file.txt", "w");

if (file == NULL)
{
printf("Error opening file.\n");
return 1;
}

fprintf(file, "abcdefgh\n");
fprintf(file, "ijklmnop");

fseek(file, -5, SEEK_END);


fprintf(file, "@");

fclose(file);
return 0;
}

Fig. 15.9 Contents of


file.txt

15.7 rewind Function

The void rewind(FILE* stream) sets the file position to the beginning of the file of
the given stream. Following is an example. Output of this code is shown in Fig. 15.10.
284 15 File Processing

#define _CRT_SECURE_NO_WARNINGS

#include <stdio.h>

main(void)
{
FILE* file;
file = fopen("D:\\file.txt", "w");

if (file == NULL)
{
printf("Error opening file.\n");
return 1;
}

fprintf(file, "abcdefgh");
fprintf(file, "ijklmnop");

rewind(file);
fprintf(file, "+-*/");

fclose(file);
return 0;
}

Fig. 15.10 Contents of


file.txt

15.8 Reading a File

The int fscanf(FILE* stream, const char* format, argument-list) reads formatted
input from a stream. The following codes reads the values stored in io.txt file. The
content of io.txt is shown in Fig. 15.11. Output of this code is shown in Fig. 15.12.
15.8 Reading a File 285

#define _CRT_SECURE_NO_WARNINGS

#include <stdio.h>

main(void)
{
FILE* fh_input;
fh_input = fopen("D:\\io.txt", "r");
int a;
float b;

fscanf(fh_input, "%d", &a);


printf("1st value read from file is:%d.\n", a);

fscanf(fh_input, "%d", &a);


printf("2nd value read from file is:%d.\n", a);

fscanf(fh_input, "%f", &b);


printf("3rd value read from file is:%f.\n", b);

fscanf(fh_input, "%d", &a);


printf("4th value read from file is:%d.\n", a);

fclose(fh_input);

return 0;
}

Fig. 15.11 Content of


io.txt

Fig. 15.12 Output of the code


286 15 File Processing

15.9 End Of File (EOF)

The EOF indicates the file reached end with nothing to read. The following code
continues reading the io.txt until it reaches the EOF. The content of io.txt is shown
in Fig. 15.13. Output of this code is shown in Fig. 15.14.
#define _CRT_SECURE_NO_WARNINGS

#include <stdio.h>

main(void)
{
FILE* fh_input;
fh_input = fopen("D:\\io.txt", "r");
int a;

while (fscanf(fh_input, "%d", &a)!=EOF)


printf("value read from file is:%d.\n", a);

fclose(fh_input);

return 0;
}

Fig. 15.13 Content of


io.txt

Fig. 15.14 Output of the code


15.10 fgets Function 287

15.10 fgets Function

The char* fgets(char* str, int n, FILE* stream) reads a line from the specified stream
and stores it into the string pointed to by str. It stops when either (n-1) characters are
read, the newline character is read, or the end-of-file is reached, whichever
comes first.
Following is an example. This code reads the io.txt line by line. The content of
io.txt is shown in Fig. 15.15. Output of this code is shown in Fig. 15.16.
#define _CRT_SECURE_NO_WARNINGS

#include <stdio.h>

main(void)
{
FILE* fh_input;
fh_input = fopen("D:\\io.txt", "r");
char buffer[256];
fgets(buffer, 256, fh_input);
printf("%s", buffer);

fgets(buffer, 256, fh_input);


printf("%s", buffer);

fgets(buffer, 256, fh_input);


printf("%s", buffer);

fclose(fh_input);

return 0;
}

Fig. 15.15 Content of


io.txt

Fig. 15.16 Output of the code


288 15 File Processing

fgets returns NULL when it reaches the end of file. The following code checks to
see whether fgets returned NULL. It stops reading once fgets returned NULL. Output
of this code is shown in Fig. 15.17.
#define _CRT_SECURE_NO_WARNINGS

#include <stdio.h>

main(void)
{
FILE* fh_input;
fh_input = fopen("D:\\io.txt", "r");
char buffer[256];

while (fgets(buffer, 256, fh_input)!=NULL)


printf("%s", buffer);

fclose(fh_input);

return 0;
}

Fig. 15.17 Output of the code

15.11 getc Function

The int getc(FILE *stream) gets the next character (an unsigned char) from the
specified stream and advances the position indicator for the stream.
Following is an example. This code reads the io.txt character by character. The
content of io.txt is shown in Fig. 15.18. Output of this code is shown in Fig. 15.19.
#define _CRT_SECURE_NO_WARNINGS

#include <stdio.h>

main(void)
{
FILE* fh_input;
fh_input = fopen("D:\\io.txt", "r");

char ch;
do
{
ch = getc(fh_input);
printf("%c", ch);
} while (ch != EOF);

return 0;
}
15.12 Writing to a Binary File 289

Fig. 15.18 Content of


io.txt

Fig. 15.19 Output of the code

15.12 Writing to a Binary File

A binary file is the one in which data is stored in the file in the same way as it is
stored in the main memory for processing. It is stored in binary format instead of
ASCII characters. It is normally used for storing numeric information (int, float,
double). Normally, a binary file can be created only from within a program and its
contents can be read only by a program.
Table 15.4 showed the major differences between text files and binary files.

Table 15.4 Major differences between text files and binary files
Text file Binary file
In text file, text, character, numbers are stored In binary file, data is stored in binary format
one character per byte, i.e., 32667 occupies 5 and each data would occupy the same
bytes although it occupies 2 bytes in memory number of bytes on disks as it occupies in
memory
In the text file, the newline character is converted In binary file, conversion of newline to
to carriage-return/linefeed before being written carriage-return and linefeed does not take
to the disk place
Text files are used to store data more user Binary files are used to store data more
friendly compactly
In the text file, a special character(“\0”) whose In the binary file, no such character is
ASCII value is 26 inserted after the last character present. Files keep track of the end of the file
to mark the end of file from the number of characters present
Content written in text files is human readable Content written in binary files is not human
readable and looks like encrypted content
290 15 File Processing

To write into a binary file, you need to use the fwrite function. The prototype of
this function is: size_t fwrite(const void* ptr, size_t size, size_t nmemb, FILE*
stream). This function takes four arguments:
ptr: This is the pointer to the array of elements to be written.
size: This is the size in bytes of each element to be written.
nmemb: This is the number of elements, each one with a size of size bytes.
stream: This is the pointer to a FILE object that specifies an output stream.
Let’s study some examples. The following code writes integer data to a binary file.
#define _CRT_SECURE_NO_WARNINGS

#include <stdio.h>

main(void)
{
FILE* file;
file= fopen("D:\\file.bin", "wb");
if (file == NULL)
{
printf("Error opening file.\n");
return 1;
}
int data = 123;
fwrite(&data, sizeof(data), 1, file);
fclose(file);
return 0;
}

Following code writes an array to a binary file.


#define _CRT_SECURE_NO_WARNINGS

#include <stdio.h>

main(void)
{
int data[] = {100,200,300,400,500,600,700};

FILE* file;
file= fopen("D:\\file.bin", "wb");
if (file == NULL)
{
printf("Error opening file.\n");
return 1;
}

fwrite(data, sizeof(data), 1, file);


fclose(file);
return 0;
}
15.13 Reading from Binary Files 291

15.13 Reading from Binary Files

To read from a binary file, you need to use the fread function. The prototype of this
function is:
size_t fread(void* ptr, size_t size, size_t nmemb, FILE* stream). This function
takes four arguments:
ptr : This is the pointer to a block of memory with a minimum size of
size*nmemb bytes.
size : This is the size in bytes of each element to be read.
nmemb : This is the number of elements, each one with a size of size bytes.
stream : This is the pointer to a FILE object that specifies an input stream.
Let’s study an example. The following code reads the binary file produced by the
previous code. Output of this code is shown in Fig. 15.20.
#define _CRT_SECURE_NO_WARNINGS

#include <stdio.h>

main(void)
{
int data[7];

FILE* file;
file= fopen("D:\\file.bin", "rb");

if (file == NULL)
{
printf("Error opening file.\n");
return 1;
}

fread(data, sizeof(data), 1, file);


fclose(file);

for (int i = 0; i < 7; i++)


printf("data[%d]=%d\n",i, data[i]);
return 0;
}

Fig. 15.20 Output of the code


292 15 File Processing

The following code shows how to write and read a structure to a binary file.
Output of this code is shown in Fig. 15.21.
#define _CRT_SECURE_NO_WARNINGS

#include <stdio.h>

typedef struct point


{
int x;
int y;
} point;

main(void)
{
point p1, p2, p3, p4;

p1.x = 0;
p1.y = 0;

p2.x = 1;
p2.y = 1;

p3.x = 2;
p3.y = 2;

p4.x = 3;
p4.y = 3;

FILE* file1;
file1= fopen("D:\\file.bin", "wb");

if (file1 == NULL)
{
printf("Error opening file.\n");
return 1;
}

fwrite(&p1, sizeof(point), 1, file1);


fwrite(&p2, sizeof(point), 1, file1);
fwrite(&p3, sizeof(point), 1, file1);
fwrite(&p4, sizeof(point), 1, file1);
fclose(file1);

FILE* file2;
file2 = fopen("D:\\file.bin", "rb");
point p5;
for (int i = 0; i < 4; i++)
{
fread(&p5, sizeof(point), 1, file2);
printf("p%i.x=%d ", i+1, p5.x);
printf("p%i.y=%d\n", i+1, p5.y);
}
fclose(file2);
return 0;
}
15.13 Reading from Binary Files 293

Fig. 15.21 Output of the code

You can use the following code as well. Output of this code is shown in Fig. 15.22.
#define _CRT_SECURE_NO_WARNINGS

#include <stdio.h>

typedef struct point


{
int x;
int y;
} point;

main(void)
{
point p1, p2, p3, p4;

p1.x = 0;
p1.y = 0;

p2.x = 1;
p2.y = 1;

p3.x = 2;
p3.y = 2;

p4.x = 3;
p4.y = 3;

FILE* file1;
file1= fopen("D:\\file.bin", "wb+");

if (file1 == NULL)
{
printf("Error opening file.\n");
return 1;
}

fwrite(&p1, sizeof(point), 1, file1);


fwrite(&p2, sizeof(point), 1, file1);
fwrite(&p3, sizeof(point), 1, file1);
fwrite(&p4, sizeof(point), 1, file1);

rewind(file1);
point p5;
for (int i = 0; i < 4; i++)
{
fread(&p5, sizeof(point), 1, file1);
printf("p%i.x=%d ", i+1, p5.x);
printf("p%i.y=%d\n", i+1, p5.y);
}
fclose(file1);
return 0;
}
294 15 File Processing

Fig. 15.22 Output of the code

15.14 Error Handling

errno.h is a header file in the standard library of the C programming language. It


defines macros for reporting and retrieving error conditions using the symbol errno
(short for "error number"). errno acts like an integer variable. At program startup,
the value stored in errno is zero.
strerror function returns a string containing a message derived from an error code.
Let’s study an example. In the following error, we tried to read a file that does not
exist. Output of this code is shown in Fig. 15.23. After trying to read the xyz.txt file,
errno equals to 2. The strerror generates the “No such file or directory” string.
#define _CRT_SECURE_NO_WARNINGS

#include <stdio.h>
#include <errno.h>
#include <string.h>

extern int errno;

int main()
{
FILE* fh;
printf("errno before any error: %d\n", errno);
fh = fopen("xyz.txt", "r");
if (fh == NULL)
{
printf("errno after: %d\n", errno);
printf("Error Message: %s\n", strerror(errno));
}else{
fclose(fh);
}
return 0;
}

Fig. 15.23 Output of the code


Further Readings 295

You can use the perror as well. The prototype of this function is void perror(const
char* str). It prints a descriptive error message to stderr. First, the string str is
printed, followed by a colon, then a space.
Following is an example. Output of this example is shown in Fig. 15.24.
#define _CRT_SECURE_NO_WARNINGS

#include <stdio.h>
#include <errno.h>
#include <string.h>

extern int errno;

int main()
{
FILE* fh;
printf("errno before any error: %d\n", errno);
fh = fopen("xyz.txt", "r");
if (fh == NULL)
{
printf("errno after: %d\n", errno);
perror("Error Message");
//printf("Error Message: %s\n", strerror(errno));
}else{
fclose(fh);
}
return 0;
}

Fig. 15.24 Output of the code

Further Readings

1. Deitel P, Deitel H (2022) C how to program: with case studies in applications and systems
programming, 9th edn. Pearson, London
2. Hart JM (2010) Windows system programming. Addison-Wesley, Upper Saddle River
Chapter 16
Useful Functions to Work with Files
and Directories

16.1 Introduction

This chapter introduces some useful functions to work with files and directories.

16.2 Copying .txt Files (I)

The following code copies C:\test.txt to D:\copy.txt. This code reads the source file
(C:\test.txt) character by character and copies it to the destination (D:\copy.txt) file.
#define _CRT_SECURE_NO_WARNINGS

#include <stdio.h>

int main() {
FILE* file;
FILE* copy;

file = fopen("c:\\test.txt", "r");


copy = fopen("d:\\copy.txt", "w");

if (file == NULL || copy == NULL)


{
printf("Error opening file(s).\n");
return 1;
};

char c;
while ((c = fgetc(file)) != EOF)
fputc(c, copy);

fclose(file);
fclose(copy);
printf("Files are copied.");

return(0);
}

© The Author(s), under exclusive license to Springer Nature Switzerland AG 2023


F. Asadi, Essentials of C Programming with Microsoft® Visual Studio®, 297
https://doi.org/10.1007/978-3-031-35711-4_16
298 16 Useful Functions to Work with Files and Directories

16.3 Copying .txt Files (II)

In the previous section, the addresses of source and destination files are put in the
source code. In this section, the addresses of source and destination files are taken
from the command line (see Sect. 7.4 in Chap. 7). The following code takes the
source and destination addresses from the command line.
#define _CRT_SECURE_NO_WARNINGS

#include <stdio.h>

int main(int argc, char* argv[]) {


FILE* file;
FILE* copy;

file = fopen(argv[1], "r");


copy = fopen(argv[2], "w");

if (argc != 3)
{
printf("Argument number error.\n");
return 1;
};

if (file == NULL || copy == NULL)


{
printf("Error opening file(s).\n");
return 1;
};

char c;
while ((c = fgetc(file)) != EOF)
fputc(c, copy);

fclose(file);
fclose(copy);
printf("Files are copied.");

return(0);
}

Let’s test the code. Click the Project> Project Properties (Fig. 16.1) and give the
source and destination paths (Fig. 16.2).
16.3 Copying .txt Files (II) 299

Fig. 16.1 Project> Project Properties

Fig. 16.2 Project Property Pages window


300 16 Useful Functions to Work with Files and Directories

Select the Use Multi-Byte Character Set (Fig. 16.3).

Fig. 16.3 Project Property Pages window

Now you can press F5, and see the output of the code.

16.4 Copying Files with CopyFileA Function (I)

You can use the CopyFileA function (defined in Windows.h header file) to copy a
binary or text file. The following code shows how to use this function. It will not
overwrite the destination file if it already exists. For instance, assume that you want
to copy C:\ExistingFile.txt to D:\NewFile.txt and D:\NewFile.txt already exists. The
following code does not overwrite the D:\NewFile.txt.
16.5 Copying Files with CopyFileA Function (II) 301

#include <stdio.h>
#include <Windows.h>

int main()
{
//see https://bit.ly/3k32iRO

BOOL flag=CopyFileA("c:\\ExistingFile.txt", "d:\\NewFile.txt", TRUE);


if (flag)
printf("Copy successful.\n");
else
printf("Error! File already exists. Existing destination file leaved
unchanged.\n");

return 0;
}

Suppose you want to copy a file from C:\ExistingFile.txt to D:\NewFile.txt, and


D:\NewFile.txt already exists. The following code creates/overwrites the ­ D:\
NewFile.txt:
#include <stdio.h>
#include <Windows.h>

int main()
{
//see https://bit.ly/3k32iRO

BOOL flag=CopyFileA("c:\\ExistingFile.txt", "d:\\NewFile.txt", FALSE);


if (flag)
printf("Copy successful.\n");
else
printf("Existing destination file is changed.\n");

return 0;
}

16.5 Copying Files with CopyFileA Function (II)

In the previous section, the addresses of source and destination files are put in the
source code. In this section, the addresses of source and destination files are taken
from the command line (see Sect. 7.4 in Chap. 7). The following code takes the
source and destination addresses from the command line.
#include <stdio.h>
#include <Windows.h>

int main(int argc, LPTSTR argv[])


{
//see https://bit.ly/3k32iRO

BOOL flag = CopyFileA(argv[1], argv[2], TRUE);

if (flag)
printf("Copy successful.\n");
else
printf("Error! File already exists. Existing destination file leaved
unchanged.\n");

return 0;
}
302 16 Useful Functions to Work with Files and Directories

Let’s test the file. Click the Project> Project1 Properties (Fig. 16.4) and give the
source and destination addresses (Fig. 16.5). Press F5 to test the code.

Fig. 16.4 Project> Project Properties

Fig. 16.5 Project Property Pages window


16.7 Remove a File 303

16.6 Rename a File

The following code shows how to rename a file.


#include <stdio.h>

int main() {
int ret;
char oldname[] = "d:\\file.txt";
char newname[] = "d:\\newfile.txt";

ret = rename(oldname, newname);

if (ret == 0) {
printf("File renamed successfully");
}
else {
printf("Error: unable to rename the file");
}

return(0);
}

16.7 Remove a File

You can use the following code to remove a file.


#include <stdio.h>

int main()
{
int result;

result=remove("d:\\io.txt");

if (result == 0) {
printf("File deleted successfully");
}
else {
printf("Error: unable to delete the file");
}

return 0;
}

You can use the following code as well.


#include <stdio.h>
#include <Windows.h>

int main()
{
BOOL flag=DeleteFileA("d:\\NewTest.txt");
if (flag)
printf("Delete successful...\n");
else
printf("Error! Such a file doesn't exists!\n");

return 0;
}
304 16 Useful Functions to Work with Files and Directories

16.8 Printing the Contents of a Directory

The following code requires the dirent library. This library can be downloaded from
GitHub (https://github.com/tronkko/dirent). After downloading the files, you need
to copy them into the include folder of Visual Studio. Click the Project> Project1
Properties (Fig. 16.6) and study the External Include Directories (Fig. 16.7) to find
the address of include folder.

Fig. 16.6 Project> Project Properties


16.8 Printing the Contents of a Directory 305

Fig. 16.7 Project Property Pages window

The following code prints the contents of current working directory. Output of
this code is shown in Fig. 16.8.
// see https://bit.ly/3XGy5qj
// see https://github.com/tronkko/dirent
// see https://bit.ly/3vUwS2r

#define _CRT_SECURE_NO_WARNINGS

#include <dirent.h>

int main()
{
DIR* directory;
struct dirent* entry;
directory = opendir(".");// opendir(".") opens the current working directory
// directory = opendir("c:\\") opens the c:\

if (directory == NULL)
{
printf("Error opening directory");
return 1;
}

while ((entry = readdir(directory)) != NULL)


{
printf("%s\n", entry->d_name);
}
if (closedir(directory) == -1)
{
printf("Error closing directory.\n");
return 1;
}
return(0);
}
306 16 Useful Functions to Work with Files and Directories

Fig. 16.8 Output of the code

Let’s study another example. The following code adds a label to each item so you
can see whether it is a file or directory. Output of this code is shown in Fig. 16.9.
// see https://bit.ly/3XGy5qj
// see https://github.com/tronkko/dirent
// see https://bit.ly/3vUwS2r

#define _CRT_SECURE_NO_WARNINGS

#include <dirent.h>

int main()
{
DIR* directory;
struct dirent* entry;
directory = opendir(".");

if (directory == NULL)
{
printf("Error opening directory");
return 1;
}

while ((entry = readdir(directory)) != NULL)


{
if (entry->d_type == DT_REG)
printf("File: %s\n", entry->d_name);
else if (entry->d_type == DT_DIR)
printf("Dir: %s\n", entry->d_name);
}

if (closedir(directory) == -1)
{
printf("Error closing directory.\n");
return 1;
}
return(0);
}
16.9 Obtaining the Address of Current Working Directory 307

Fig. 16.9 Output of the code

16.9 Obtaining the Address of Current Working Directory

The following code used the _getcwd function (which is defined in the direct.h
header file) to print the current working directory. Sample output of this code is
shown in Fig. 16.10.
#include <stdio.h>
#include <direct.h>

int main()
{
char buffer[1024];

if (_getcwd(buffer, 1024) == NULL)


{
printf("Error! failed to get the current working directory.\n");
return 1;
}
printf("current working directory:\n%s", buffer);

return 0;
}

Fig. 16.10 Output of the code


308 16 Useful Functions to Work with Files and Directories

16.10 Changing the Current Working Directory

You can use the _chdir function to change the current working directory. Following
code is an example. Output of this code is shown in Fig. 16.11.
int main()
{
char buffer[1024];

if (_getcwd(buffer, 1024) == NULL)


{
printf("Error! failed to get the current working directory.\n");
return 1;
}
printf("before running the _chdir, working directory is:\n%s", buffer);

char* newdir = "c:\\test"; //Ensure that such a directory exists


//in your computer. Otherwise you will
//receive the error message.
if (_chdir(newdir) == -1)
{
printf("\nChange of directory failed.");
return 1;
}

if (_getcwd(buffer, 1024) == NULL)


{
printf("Error! failed to get the current working directory.\n");
return 1;
}
printf("\nAfter running the _chdir, working directory is:\n%s", buffer);

return 0;
}

Fig. 16.11 Output of the code

16.11 Making Directories

You can make a directory with the aid of _mkdir function. Following code is an
example. Output of this code is shown in Fig. 16.12.
16.12 Removing Directories 309

#include <stdio.h>
#include <direct.h>

int main()
{
int result;

result = _mkdir("C:\\test");

if (result == 0)
printf("Directory created\n");
else
printf("Error creating directory\n");

return 0;
}

Fig. 16.12 Output of the code

16.12 Removing Directories

You can remove an empty directory with the aid of _rmdir function which is defined
in the direct.h header file. The following code removes the empty c:\test directory.
Output of this code is shown in Fig. 16.13.
#include <stdio.h>
#include <direct.h>

int main()
{
int result;

result = _rmdir("c:\\test"); // return -1 when some error occurs


// _rmdir removes empty directories only

if (result == -1)
{
printf("Remove directory failed.\n");
return 1;
}
else
printf("Directory removed successfully");

return 0;
}
310 16 Useful Functions to Work with Files and Directories

Fig. 16.13 Output of the code

You cannot remove a directory if it is not empty or is in use. The following code
gives suitable messages on these cases.
#include <stdio.h>
#include <direct.h>
#include <errno.h>

int main()
{
int result;

result=_rmdir("c:\\test"); // return -1 when some error occurs

if (result == -1)
{
printf("Remove directory failed.\n");

if (errno == ENOENT)
printf("Path not found.");
else if (errno == ENOTEMPTY)
printf("Directory is not empty");
else if (errno == EACCES)
printf("Directory is in use");
return 1;
}
else
printf("Directory removed successfully");

return 0;
}

Further Reading

1. Hart JM (2010) Windows system programming. Addison-Wesley, Upper Saddle River


Chapter 17
Serial Communication in C

17.1 Introduction

Modern computers have some USB ports. A cheap USB-to-serial converter can be
used to convert the USB protocol into simple serial protocol. A virtual serial port is
made when a USB-to-serial converter is connected to a USB port.
This chapter shows how you can transfer data with that virtual serial port made
by USB-to-serial converter. In this chapter, we will use an Arduino UNO board to
send and receive data. The Arduino UNO has an onboard USB-to-serial converter.
Therefore, there is no need for any external USB-to-serial converter.

17.2 Reading from the Serial Port

In this section, we will use the Arduino board as a sender. The Arduino board is con-
nected to port COM 3 (Fig. 17.1). It sends the “Hello from Arduino…” string with
9600 bps to COM 3.

© The Author(s), under exclusive license to Springer Nature Switzerland AG 2023 311
F. Asadi, Essentials of C Programming with Microsoft® Visual Studio®,
https://doi.org/10.1007/978-3-031-35711-4_17
312 17 Serial Communication in C

Fig. 17.1 Tools> Port

The Arduino code is shown below:

void setup() {
// put your setup code here, to run once:
Serial.begin(9600);
}

void loop() {
// put your main code here, to run repeatedly:
Serial.println("Hello from Arduino...");
delay(1000);
}

Upload the code into the Arduino board (Fig. 17.2).


17.2 Reading from the Serial Port 313

Fig. 17.2 Upload button

The following code opens the COM 3 with baud rate of 9600 bps. It reads the
data from serial port (using ReadFile function) and shows the received data on the
computer screen. Output of this code is shown in Fig. 17.3.
314 17 Serial Communication in C

//a usefull reference: https://bit.ly/3XuZBXF


//another usefull reference https://bit.ly/3IHdPAv

#include<windows.h>
#include<stdio.h>
int main()
{
HANDLE hComm;
hComm = CreateFileA("\\\\.\\COM3", // Port name
GENERIC_READ | GENERIC_WRITE, // Read/Write
0, // No Sharing
NULL, // No Security
OPEN_EXISTING, // Open existing port only
0, // Non Overlapped I/O
NULL); // Null for Comm Devices

if (hComm == INVALID_HANDLE_VALUE)
printf("Error in opening serial port\n");
else
printf("opening serial port successful\n");

DCB dcbSerialParams = { 0 };
dcbSerialParams.DCBlength = sizeof(dcbSerialParams);

if ((GetCommState(hComm, &dcbSerialParams) == 0))


{
printf("error getting comm state\n");
}

dcbSerialParams.BaudRate = CBR_9600; // configuring the Baud rate


dcbSerialParams.ByteSize = DATABITS_8;
dcbSerialParams.Parity = NOPARITY;
dcbSerialParams.StopBits = ONESTOPBIT;
SetCommState(hComm, &dcbSerialParams); // configuring the port according to dcb
structures

COMMTIMEOUTS timeouts = { 0 }; // timeouts setting


timeouts.ReadIntervalTimeout = 50;
timeouts.ReadTotalTimeoutConstant = 50;
timeouts.ReadTotalTimeoutMultiplier = 10;
timeouts.WriteTotalTimeoutConstant = 50;
timeouts.WriteTotalTimeoutMultiplier = 10;
SetCommTimeouts(hComm, &timeouts);

DWORD dwEventMask;
SetCommMask(hComm, EV_RXCHAR); // configuring windows for reception
WaitCommEvent(hComm, &dwEventMask, NULL); // waiting for the reception

int i = 0;
DWORD NoBytesRead;
char TempChar;
char SerialBuffer[256];
do {
ReadFile(hComm, &TempChar, sizeof(TempChar), &NoBytesRead, NULL);//reads the
serial port
SerialBuffer[i] = TempChar;
i++;
} while (NoBytesRead > 0);

for (int j = 0; j < i - 1; j++)


printf("%c", SerialBuffer[j]); // printing out the data

CloseHandle(hComm); // closing the Serial Port

return 0;
}
17.3 Writing to the Serial Port 315

Fig. 17.3 Output of the code

17.3 Writing to the Serial Port

In this section, we will use the Arduino board as receiver. The Arduino board is con-
nected to port COM 3 (Fig. 17.4). It receives a command from the computer. When
the command is “on,” “ON,” or “On,” the onboard LED of Arduino is turned on.
When the command is “off,” “OFF,” or “Off,” the onboard LED of Arduino is
turned off.

Fig. 17.4 Tools> Port


316 17 Serial Communication in C

Upload the following code to the Arduino (Fig. 17.5):

void setup() {
// put your setup code here, to run once:
Serial.begin(9600);
pinMode(LED_BUILTIN,OUTPUT);
}

void loop() {
if (Serial.available()>0){
String inputCommand=Serial.readString();
Serial.println((String)"Entered command: "+inputCommand);

if (inputCommand=="on" ||inputCommand=="ON"||inputComman
d=="On")
{
digitalWrite(LED_BUILTIN,HIGH);
}

if (inputCommand=="off"||inputCommand=="OFF"||inputComman
d=="Off")
{
digitalWrite(LED_BUILTIN,LOW);
}
}
}
17.3 Writing to the Serial Port 317

Fig. 17.5 The code is entered to Arduino IDE

The following code opens the COM 3 with baud rate of 9600 bps. It takes a com-
mand from the user and sends the string to the serial port (using WriteFile function).
Sample output of this code is shown in Fig. 17.6.
318 17 Serial Communication in C

//a usefull reference: https://bit.ly/3XuZBXF


//another usefull reference https://bit.ly/3IHdPAv

#define _CRT_SECURE_NO_WARNINGS
#include<windows.h>
#include<stdio.h>
#include<string.h>

int main()
{
HANDLE hComm;

hComm = CreateFileA("\\\\.\\COM3", // Port name


GENERIC_READ | GENERIC_WRITE, // Read/Write
0, // No Sharing
NULL, // No Security
OPEN_EXISTING, // Open existing port only
0, // Non Overlapped I/O
NULL); // Null for Comm Devices

if (hComm == INVALID_HANDLE_VALUE)
printf("Error in opening serial port\n");
else
printf("opening serial port successful\n");

DCB dcbSerialParams = { 0 };
dcbSerialParams.DCBlength = sizeof(dcbSerialParams);

if ((GetCommState(hComm, &dcbSerialParams) == 0))


{
printf("error getting comm state\n");
}

dcbSerialParams.BaudRate = CBR_9600;
dcbSerialParams.ByteSize = DATABITS_8;
dcbSerialParams.Parity = NOPARITY;
dcbSerialParams.StopBits = ONESTOPBIT;
SetCommState(hComm, &dcbSerialParams); // configuring the port according to dcb
structures

COMMTIMEOUTS timeouts = {0}; // timeouts setting


timeouts.ReadIntervalTimeout = 50;
timeouts.ReadTotalTimeoutConstant = 50;
timeouts.ReadTotalTimeoutMultiplier = 10;
timeouts.WriteTotalTimeoutConstant = 50;
timeouts.WriteTotalTimeoutMultiplier = 10;
SetCommTimeouts(hComm, &timeouts);

char data[10]; // determining the data to be written to the serial port


do
{
printf("please enter your command (on/off/exit): ");
scanf("%s", data);

DWORD dNoOFBytestoWrite;
DWORD dNoOfBytesWritten = 0;

dNoOFBytestoWrite = sizeof(data); // calculating the amount of bytes

WriteFile(hComm, data, dNoOFBytestoWrite, &dNoOfBytesWritten, NULL); //


writing the data to the serial port
} while (strcmp(data, "exit"));

CloseHandle(hComm); // closing the Serial Port

return 0;
}
Further Readings 319

Fig. 17.6 Output of the code

Further Readings

1. https://bit.ly/3H5huqi
2. Asadi F (2022) Essential circuit analysis using NI Multisim™ and MATLAB®. Springer,
Cham. https://doi.org/10.1007/978-­3-­030-­89850-­2
3. Asadi F (2022) Essential circuit analysis using Proteus®. Springer. https://doi.
org/10.1007/978-­981-­19-­4353-­9
4. Asadi F (2022) Essential circuit analysis using LTspice®. Springer. https://doi.
org/10.1007/978-­3-­031-­09853-­6
5. Asadi F (2022) Electric and electronic circuit simulation using TINA-TI®. River Publishers.
https://doi.org/10.13052/rp-­9788770226851
6. Asadi F (2022) Electric circuit analysis with EasyEDA. Springer. https://doi.
org/10.1007/978-­3-­031-­00292-­2
7. Asadi F (2021) Power electronics circuit analysis with PSIM®. De Gruyter. https://doi.
org/10.1515/9783110740653
8. Asadi F (2022) Simulation of power electronics circuits with MATLAB®/Simulink®: design,
analyze, and prototype power electronics. Apress. https://doi.org/10.1007/978-­1-­4842-­8220-­5
9. Asadi F, Eguchi K (2021) Electronic measurement: a practical approach. Springer. https://doi.
org/10.1007/978-­3-­031-­02021-­6
10. Asadi F, Eguchi K (2019) Simulation of power electronics converters Using PLECS®.
Academic Press. https://doi.org/10.1016/C2018-­0-­02253-­7
11. Asadi F (2023) Analog electronic circuits laboratory manual. Springer. https://doi.
org/10.1007/978-­3-­031-­25122-­1
12. Asadi F (2023) Electric circuits laboratory manual. Springer. https://doi.
org/10.1007/978-­3-­031-­24552-­7
Chapter 18
Graphical User Interface

18.1 Introduction

You can use the Visual Studio to make programs with graphical user interfaces
(GUI). In this chapter, you will learn how to make a simple program with graphical
user interface. See the references at the end of this chapter to learn more about this
subject.

18.2 Making a Simple GUI Project

Select the File> New> Project and select the CLR Empty Project (.NET Framework)
(Fig. 18.1). Then give a desired name for the project and save it in the desired path
(Fig. 18.2).

© The Author(s), under exclusive license to Springer Nature Switzerland AG 2023 321
F. Asadi, Essentials of C Programming with Microsoft® Visual Studio®,
https://doi.org/10.1007/978-3-031-35711-4_18
322 18 Graphical User Interface

Fig. 18.1 Create a new project window

Fig. 18.2 Configure your new project window


18.2 Making a Simple GUI Project 323

Right click on the Source Files in the Solution Explorer window (Fig. 18.3) and
select the Add> New Item (Fig. 18.4). If the Solution Explorer window is hidden,
click the View> Solution Explorer (Fig. 18.5) to show it.

Fig. 18.3 Solution


Explorer

Fig. 18.4 Add> New Item

Fig. 18.5 View> Solution Explorer


324 18 Graphical User Interface

After clicking the Add> New Item (Fig. 18.4), the Add New Item window
appears on the screen. Select the Windows Form (Fig. 18.6) and save it with
MyForm.h name.

Fig. 18.6 Add New Item window

After clicking the Add button in Fig. 18.6, the window shown in Fig. 18.7 appears
on the screen. Close this window using the X button (Fig. 18.7).

Fig. 18.7 Error message


18.2 Making a Simple GUI Project 325

Double click on the MyForm.h to open the GUI design environment (Fig. 18.8).
If design environment (Fig. 18.9) is not shown after double clicking the MyForm.h,
close the solution using the File> Close Solution, reopen it and double click the
MyForm.h.

Fig. 18.8 Solution


Explorer

Fig. 18.9 User interface design environment


326 18 Graphical User Interface

Select a button, two text boxes, and a label from the toolbox and design the GUI
shown in Fig. 18.10. We want to design a program that takes two numbers from the
text boxes and add them together. The result is shown in the label.

Fig. 18.10 Designed user


interface

Click on the label box to select it. The Text property of label1 is filled with
“label1” string (Fig. 18.11). Clear the “label1” (Fig. 18.12) and press the Enter but-
ton to apply the changes.

Fig. 18.11 Properties


window
18.2 Making a Simple GUI Project 327

Fig. 18.12 Text section of


Properties window

Click on the button1 (Fig. 18.10) and change its Text property to “Calc”
(Fig. 18.13). Now the GUI looks like Fig. 18.14.

Fig. 18.13 Text is changed


to Calc
328 18 Graphical User Interface

Fig. 18.14 User interface


after applying the changes

You will receive an error (Fig. 18.15) if you try to run the code. The error mes-
sage in Fig. 18.15 tells us that our program does not have any entry point. Let’s
define the entry point of the code.

Fig. 18.15 Error List window

Click the Project> FirstGuiProject Properties (Fig. 18.16) and select the Windows
SubSystem (Fig. 18.17).
18.2 Making a Simple GUI Project 329

Fig. 18.16 Project> FirstGuiProject Properties

Fig. 18.17 Project Property Pages


330 18 Graphical User Interface

Enter main to the Entry Point box (Fig. 18.18) and click the OK button.

Fig. 18.18 Determining the Entry Point

Double click the MyForm.cpp (Fig. 18.19) to open it (Fig. 18.20).

Fig. 18.19 Solution


Explorer
18.2 Making a Simple GUI Project 331

Fig. 18.20 MyForm.cpp

Enter the following code (Fig. 18.21):


#include "MyForm.h"
using namespace System;
using namespace System::Windows::Forms;

[STAThread]
void main(array<String^>^ args) {
Application::EnableVisualStyles();
Application::SetCompatibleTextRenderingDefault(false);
FirstGuiProject::MyForm form;
Application::Run(%form);
}

Fig. 18.21 Code entered to MyForm.cpp

Now you can run the code by pressing F5 and the error shown in Fig. 18.15 will
not stop you.
Let’s continue. It is time to write the code to add two numbers together. Double
click on MyForm.h (Fig. 18.22). This opens the designed user interface. Right click
on the form and click the View Code (Fig. 18.23).
332 18 Graphical User Interface

Fig. 18.22 Solution


Explorer

Fig. 18.23 View code

Add the using namespace System::Globalization to the code (Fig. 18.24).

Fig. 18.24 Globalization namespace is added to the code


Further Readings 333

Double click on the Calc button and enter the following code (Fig. 18.25):
private: System::Void button1_Click(System::Object^ sender, System::EventArgs^ e) {
double a = System::Convert::ToDouble(textBox1->Text,
System::Globalization::CultureInfo::InvariantCulture);
double b = System::Convert::ToDouble(textBox2->Text,
System::Globalization::CultureInfo::InvariantCulture);
double c = a + b;
label1->Text = System::Convert::ToString(c);
}

Fig. 18.25 Code for Calc button click event

Run the program and test it. Enter two numbers to the text boxes and click the
Calc button. Two numbers will be added together and the result will be shown
(Fig. 18.26).

Fig. 18.26 Sample run

Further Readings

1. https://bit.ly/3wRyjPR
2. https://bit.ly/3KQqQak
Index

A E
Address-of operator, 141 Enumeration, 35–37
Arrays in C, 75 Error handling in C, 294, 295
Arrow operator, 164–166, 169 exit function, 134, 135
asctime function, 248–249 Exponential function in C, 187
atexit function, 134–136 extern keyword, 122–123
atof function, 221–222
atoi function, 221
F
fgets function, 206, 287–288
B Fibonacci sequence, 103–105
Binary file in C, 275, 289–294 for loop, 51–65, 82, 83, 206
Binary search in C, 268–273 fprintf function, 279–281
Bitwise operation in C, 199–200 fseek function, 281–283
Break command, 64–65 ftell function, 279
Bubble sort in C, 253–259

G
C getc function, 288–289
calloc function, 87–88 getch function, 239–240
CLR project, 321 gmtime function, 245–247
COM port, 311, 313, 315, 317 Graphical user interface (GUI), 321–333
Conditional ternary operator in C, 42–43
Constants in C, 34, 35
Continue command, 65–66 H
CopyFileA function, 300–303 Hyperbolic function in C, 185–187
C program comments, 16

I
D if command, 39–41
Dereferencing operator, 143 if-else command, 41–42
do-while loop, 51, 64, 70–74 Insertion sort in C, 259–262

© The Editor(s) (if applicable) and The Author(s), under exclusive license to 335
Springer Nature Switzerland AG 2024
F. Asadi, Essentials of C Programming with Microsoft® Visual Studio®,
https://doi.org/10.1007/978-3-031-35711-4
336 Index

Installation of Visual Studio, 1–6 Rename a file in C, 303


Inverse trigonometric function in C, 184–185 rewind function, 283–284
isalnum function, 227–228
isalpha function, 228–229
iscntrl function, 230–233 S
isdigit function, 229–230 Serial port, 311–315, 317
islower function, 236–237 sizeof operator, 26, 79, 83, 175–176
ispunct function, 233–234 Sleep function, 241–243
isspace function, 234–236 sprintf function, 224
isupper function, 237 sscanf function, 222–224
Static variable, 108–110
strcmp function, 211–212
L strcpy function, 207
Length of an array, 79–80 _strdate function, 250
localtime function, 247–248 strftime function, 249–250
Logarithmic function in C, 183 strlen function, 206–207
Logical operators in C, 43–44 strncmp function, 212–213
strncpy function, 207–208
_strtime function, 250
M Structures in C, 155–169
Main arguments, 128–134 Switch-case command, 45–47
Make directory in C, 308
malloc function, 84–87, 148–149, 151
memcpy, 26, 89, 209 T
memmove function, 209–211 Text files in C, 275, 276, 289, 300
memset function, 208–209 tolower function, 237–238
toupper function, 238–239
Trigonometric functions in C, 184
N Type casting, 91, 176–180
Nested if statements, 44–45 typedef keywords, 37–38, 157–158
NULL pointer, 149–152, 243

U
P Unions in C, 155–169
Pointer arithmetic, 145–146 User defined functions in C, 80
Pointers in C, 75, 77–78, 141–153
Power function in C, 181
V
Variables in C, 17, 19–22, 33–35, 40, 43, 53,
Q 75, 92, 97, 108, 142, 146, 147, 155,
Quick sort in C, 253, 262–264, 266 158, 159, 166, 222
Visual Studio, viii, 1–17, 125, 180, 191,
304, 321
R void pointers, 152–153
Reading the mouse pointer, 136–138
Reading the serial port, 311–313
Recursive function, 104 W
Remove a file in C, 303–304 while loop, 51, 64, 66–67, 70, 216
Remove directory in C, 309 Writing to the serial port, 315–319

Вам также может понравиться