#undef removes or undefines a macro name which is previously created or defined using #define directive.
Syntax
#undefMACRO_NAME
Note: If a Macro template is associated with a Macro expansion, you need not mention the macro expansion to undefine the macro. You simple undefine using this syntax: #undef MACRO_NAME
Video Tutorial: #undef Preprocessor Directive: C Program
#include<stdio.h>
#define iOS
#undef iOS
int main()
{
#if defined(iOS)
printf("I Love Apple Devices\n");
#else
printf("Macro iOS has been undefined\n");
#endif // defined
return 0;
}
Output: Macro iOS has been undefined
In above source code we’re undefining the Macro iOS immediately after defining it. So defined(iOS) returns false or 0. So code inside #else block gets compiled and executed.
#include<stdio.h>
#define iOS
int main()
{
#if defined(iOS)
printf("I Love Apple Devices\n");
printf("Gift me a latest iPhone!\n");
#else
printf("Macro iOS has been undefined\n");
#endif // defined
return 0;
}
Output: I Love Apple Devices Gift me a latest iPhone!
Here Macro iOS is defined, so defined(iOS) returns true. That’s why block of code inside #if directive gets compiled and executed.
#include<stdio.h>
#define iOS
int main()
{
#undef iOS
#if defined(iOS)
printf("I Love Apple Devices\n");
#else
printf("Macro iOS has been undefined\n");
#endif // defined
return 0;
}
Output: Macro iOS has been undefined
Even though #define iOS is defined at global level you can undefine it inside main() method.
Note:defined() is a preprocessor operator which returns true if the passed macro name is defined orelse returns false or zero if its not defined.
Instead of defined() preprocessor operator you could even use #ifdef or #ifndef to check if the Macro template or Macro name is defined or not defined.
printf("This displays all your iPhone Device Details\n");
#else
printf("I'm inside do while block.\n");
#endif // defined
printf("Enter your choice? (0/1)\n");
scanf("%d", &flag);
}while(flag);
#undef iOS
#if defined(iOS)
printf("I Love Apple Devices\n");
printf("This displays all your iPhone Device Details\n");
#else
printf("Macro iOS has been undefined\n");
#endif // defined
return 0;
}
#include<stdio.h>
#define iOS
int main()
{
int flag = 1;
do
{
#if defined(iOS)
printf("I Love Apple Devices\n");
printf("This displays all your iPhone Device Details\n");
#else
printf("I'm inside do while block.\n");
#endif // defined
printf("Enter your choice? (0/1)\n");
scanf("%d", &flag);
}while(flag);
#undef iOS
#if defined(iOS)
printf("I Love Apple Devices\n");
printf("This displays all your iPhone Device Details\n");
#else
printf("Macro iOS has been undefined\n");
#endif // defined
return 0;
}
Output: I Love Apple Devices This displays all your iPhone Device Details Enter your choice? (0/1) 1 I Love Apple Devices This displays all your iPhone Device Details Enter your choice? (0/1) 1 I Love Apple Devices This displays all your iPhone Device Details Enter your choice? (0/1) 0 Macro iOS has been undefined
In above program we are defining iOS macro globally. Inside main method we use do while loop and keep executing #if #else #endif directives. Since iOS is defined, the block of code inside #if gets executed each time. Once user enters 0 as input, the control exits do while loop execution. Next it encounters #undef iOS, so defined(iOS) now returns false or 0, hence code inside #else directive gets executed.
In this video tutorial, lets see how we can make use of #error preprocessor command or directive.
Where Is It Useful?
If you’re a Software developer working with C programming language, then your project will have a lot of code and dependency source codes. While compiling, compiler will take a lot of time. In big projects usually you forget the purpose of compilation by the time it completes compilation. In such cases, make use of #error directive. If there are any errors at certain locations the compiler will stop further compilation as and when it encounters #error directive. This saves a lot of time and resources. So #error directive is usually helpful in debugging your project code.
It’s also helpful in projects with critical user inputs. Suppose user enters wrong data due to which the project itself might crash and utilize a lot of resource while trying to execute. In such cases it’s better to terminate the program execution.
Video Tutorial: #error Preprocessor Directive: C Programming
#include<stdio.h>
#define iOS
#ifndef iOS
#error First Include iOS Macro
#else
int main()
{
printf("I Love Apple Devices!\n");
return 0;
}
#endif // iOS
Output: I Love Apple Devices!
Here #ifndef directive checks if the macro iOS is defined. If its NOT defined it returns true or 1. If it’s defined then it returns 0 or false.
So if the macro iOS is not defined, then the code inside #ifndef gets compiled and executed, else the code inside #else block gets compiled and executed.
When Macro iOS is not defined
When Macro iOS is not defined, the code inside #ifndef gets compiled, where the compiler encounters #error directive. Now the compiler immediately stops any further compilation and displays the error message associated with #error directive.
This “include” directive causes one file to be included in another. For example, when we include stdio.h (header file) in our above program, all the content(code) gets imported or included in our program source code. This way we can make use of any function present inside stdio.h library file in our c program.
Car Program
We are writing Car simulation program in C – we write all the related code in different files by group them together and then include it in our main Car program. For example, we can separate wheels, color and display related things and then include all those things in our main Car program. This way our main Car program source code looks less clumsy and more over we need not worry about the implementation details present in those files.
Ex: When we include stdio.h file, we do not worry about the implementation details of printf() method. We simply use it for displaying content to the console. All the implementation details are present in stdio.h header file.
When we use < and > to wrap around the file name, the linker looks for the files in standard library storage folder. When we wrap the file name in double quotes it looks for the file in current directory.
Usually user written, custom header files are wrapped in double quotes.
We’ll be writing our own library files in this video series. But for now it’ll get too complicated if we go any further.
Note: There are many preprocessor statements other than include directive. We’ll discuss them as and when we use it in our C programs.
We define two CSS classes which we use to apply for alternate list items – using ngClass directive. Alternatively the list items appear in bold and in normal font weight.
ngClass Directive – using ternary operator: src/pages/home/home.html
Here we use ternary operator and whenever i % 2 is zero we apply bold class to that item, if not we apply normal class to that list item.
ngClass Directive: src/pages/home/home.html
< ion-header>
< ion-navbar>
< ion-title>
Company Names
< /ion-title>
< /ion-navbar>
< /ion-header>
< ion-content padding>
< ion-list no-lines>
< ion-item *ngFor="let item of items; let i = index;"
[ngClass]="{'bold': (i % 2 == 0)}">
{{i+1}}. {{item}}
< /ion-item>
< /ion-list>
< /ion-content>
< ion-header> < ion-navbar> < ion-title> Company Names < /ion-title> < /ion-navbar>
< /ion-header>
< ion-content padding>
< ion-list no-lines> < ion-item *ngFor="let item of items; let i = index;" [ngClass]="{'bold': (i % 2 == 0)}"> {{i+1}}. {{item}} < /ion-item>
< /ion-list>
< /ion-content>
This is yet another way of doing the same thing which we did using ternary operator above. Here, if i % 2 is equal to zero, then bold class will be applied, if not it won’t be applied.
Today lets learn how to implement reordering of list items in Ionic 2, using reorder directive and ionItemReorder event.
We’re using previous day code to implement reordering list items. So please go through these two small video tutorials before continuing .. (if you’re an advance user, then you can directly follow todays video tutorial).
In this video tutorial lets learn 1. To build drag and rearrange interface and functionality. 2. Solve the ion-refresher component interference with the reorder directive. 3. Save rearranged data back to the database.
Reordering list items using reorder directive: Ionic 2
But if we have ion-header, ion-footer and other items inside the list for which we do not want the reorder directive to be applied. reorder on ion-item-group: src/pages/home/home.html
In that case we need to group those items on which we want the reordering, and then apply reorder directive on that group, as shown in above example.
reordering code: src/pages/home/home.ts
reorderItems(indexes){
let element =this.items[indexes.from];this.items.splice(indexes.from,1);this.items.splice(indexes.to,0, element);};
reorderItems(indexes){ let element = this.items[indexes.from]; this.items.splice(indexes.from, 1); this.items.splice(indexes.to, 0, element);
};
When the item is dragged and dropped to the new position, (ionItemReorder) event is emitted and this event also provides initial and new position index of the reordered item. Using this, we reorder the list items.
Above code snippet is a simple JavaScript code, where we first get the actual item value which is being reordered(using its index value – indexes.from) and store it in a temporary variable. Next we remove that item from the list. Finally we place that element in the new position. All these operation is done using simple JavaScript splice method.
import { reorderArray } from 'ionic-angular';
class MyComponent { items = []; reorderItems(indexes) { this.items = reorderArray(this.items, indexes); }
}
Ionic 2 also provides helper function called reorderArray to reorder the array of items. Here we import the helper class and then use it to reorder the array of items.
Note that we have a button inside ion-header. We switch the value of btnName variable between ‘edit’ and ‘Done’ alternatively when the user clicks on it. Also we have assigned a variable(flag) to reorder directive. flag is of type Boolean and it also switches between ‘true’ and ‘false’ when the user clicks on btnName button. This way we enable and disable the visual drag and rearrange interface on the list items.
src/pages/home/home.ts
import{ Component } from '@angular/core';import{ NavController } from 'ionic-angular';import{ Storage } from '@ionic/storage';@Component({
selector:'page-home',
templateUrl:'home.html'})exportclass HomePage {
items: any;
btnName: any ='edit';
flag: any =false;
constructor(public navCtrl: NavController, public storage: Storage){this.doRefresh(0);};
doRefresh(refresher){this.storage.get('myStore1').then((data)=>{this.items= data;if(refresher !=0)
refresher.complete();});};
reorderItems(indexes){
let element =this.items[indexes.from];this.items.splice(indexes.from,1);this.items.splice(indexes.to,0, element);};
actionBtn(){if(this.btnName=='edit'){this.btnName='Done';this.flag=true;}else{this.btnName='edit';this.flag=false;this.storage.set('myStore1',this.items);}};}
Here we initialize the btnName with a value of ‘edit’ and flag as ‘false’. So initially, the drag and rearrange interface will be disabled. Once the user clicks on the ‘edit’ button present inside ion-header, the visual drag and rearrange interface appears. After the rearrangement of the item is finished user needs to click on ‘Done’ button and we save the rearranged list items to our database. This way we can persist the rearranged data.
We could even save the data to database inside reorderItems() method itself, so that the data gets saved when the user drags and drops the item in its new position. Without the need for the user to click on ‘Done’ button.
Initially variable ‘btnName’ will be ‘edit’ and flag will be ‘false’. When the user clicks on ‘edit’ button, the label name changes to ‘Done’ and the flag value changes to ‘true’. By this, the drag and rearrange interface appears on the list items. Once the arrangement is done, the user needs to click on the button ‘Done’. When the user clicks on ‘Done’ button, the button label or name changes back to ‘edit’ and the visual drag and rearrange interface gets disabled and optionally we save the rearranged data back to the database.
This code has both ion-refresher as well as reorder directive. Here when the user tries to drag an item downwards the refresher component gets invoked. To avoid that, we can simply disable ion-refresher when we enable reordering and enable ion-refresher when we disable reordering, as shown in below code.
Example Application: We’ve implemented the same code in one of our application ‘RSS Reader‘. Go to ‘Feed’ tab and add few blog / news sites rss feeds and the refresh the ‘Feed’ tab to see ‘list item reordering’ in action.