private static string CreateValidFileName( string Filename )
{string invalidChars = Regex.Escape( new string( Path.GetInvalidFileNameChars() ) );
string invalidReStr = string.Format( @"[{0}]+", invalidChars );
return Regex.Replace( Filename , invalidReStr, "_" );}
All the question that scared me now i am trying to scare them .. so that they cant scare others :)
Wednesday, May 4, 2011
Removing invalid characters from file name and making file valid.
Tuesday, May 3, 2011
C# Arrays
class ArrayList{
static void Main()
{
// Declare a single-dimensional array
int[] array1 = new int[5];
// Declare and set array element values
int[] array2 = new int[] { 1, 3, 5, 7, 9 };
// Alternative syntax
int[] array3 = { 1, 2, 3, 4, 5, 6 };
// Declare a two dimensional array
int[,] multiDimensionalArray1 = new int[2, 3];
// Declare and set array element values
int[,] multiDimensionalArray2 = { { 1, 2, 3 }, { 4, 5, 6 } };
// Declare a jagged array
int[][] jaggedArray = new int[6][];
// Set the values of the first array in the jagged array structure
jaggedArray[0] = new int[4] { 1, 2, 3, 4 };
}
}DLL Concepts
What is a DLL?
A DLL is a library that contains code and data that can be used by more than one program at the same time. For example, in Windows operating systems, the Comdlg32 DLL performs common dialog box related functions. Therefore, each program can use the functionality that is contained in this DLL to implement an Open dialog box. This helps promote code reuse and efficient memory usage.By using a DLL, a program can be modularized into separate components. For example, an accounting program may be sold by module. Each module can be loaded into the main program at run time if that module is installed. Because the modules are separate, the load time of the program is faster, and a module is only loaded when that functionality is requested.
Additionally, updates are easier to apply to each module without affecting other parts of the program. For example, you may have a payroll program, and the tax rates change each year. When these changes are isolated to a DLL, you can apply an update without needing to build or install the whole program again.
The following list describes some of the files that are implemented as DLLs in Windows operating systems:
- ActiveX Controls (.ocx) files
An example of an ActiveX control is a calendar control that lets you select a date from a calendar. - Control Panel (.cpl) files
An example of a .cpl file is an item that is located in Control Panel. Each item is a specialized DLL. - Device driver (.drv) files
An example of a device driver is a printer driver that controls the printing to a printer.
DLL advantages
The following list describes some of the advantages that are provided when a program uses a DLL:- Uses fewer resources
When multiple programs use the same library of functions, a DLL can reduce the duplication of code that is loaded on the disk and in physical memory. This can greatly influence the performance of not just the program that is running in the foreground, but also other programs that are running on the Windows operating system. - Promotes modular architecture
A DLL helps promote developing modular programs. This helps you develop large programs that require multiple language versions or a program that requires modular architecture. An example of a modular program is an accounting program that has many modules that can be dynamically loaded at run time. - Eases deployment and installation
When a function within a DLL needs an update or a fix, the deployment and installation of the DLL does not require the program to be relinked with the DLL. Additionally, if multiple programs use the same DLL, the multiple programs will all benefit from the update or the fix. This issue may more frequently occur when you use a third-party DLL that is regularly updated or fixed.
DLL dependencies
When a program or a DLL uses a DLL function in another DLL, a dependency is created. Therefore, the program is no longer self-contained, and the program may experience problems if the dependency is broken. For example, the program may not run if one of the following actions occurs:- A dependent DLL is upgraded to a new version.
- A dependent DLL is fixed.
- A dependent DLL is overwritten with an earlier version.
- A dependent DLL is removed from the computer.
The following list describes the changes that have been introduced in Microsoft Windows 2000 and in later Windows operating systems to help minimize dependency issues:
- Windows File Protection
In Windows File Protection, the operating system prevents system DLLs from being updated or deleted by an unauthorized agent. Therefore, when a program installation tries to remove or update a DLL that is defined as a system DLL, Windows File Protection will look for a valid digital signature. - Private DLLs
Private DLLs let you isolate a program from changes that are made to shared DLLs. Private DLLs use version-specific information or an empty .local file to enforce the version of the DLL that is used by the program. To use private DLLs, locate your DLLs in the program root folder. Then, for new programs, add version-specific information to the DLL. For old programs, use an empty .local file. Each method tells the operating system to use the private DLLs that are located in the program root folder.
DLL troubleshooting tools
Several tools are available to help you troubleshoot DLL problems. The following tools are some of these tools.Dependency Walker
The Dependency Walker tool can recursively scan for all dependent DLLs that are used by a program. When you open a program in Dependency Walker, Dependency Walker performs the following checks:- Dependency Walker checks for missing DLLs.
- Dependency Walker checks for program files or DLLs that are not valid.
- Dependency Walker checks that import functions and export functions match.
- Dependency Walker checks for circular dependency errors.
- Dependency Walker checks for modules that are not valid because the modules are for a different operating system.
drive\Program Files\Microsoft Visual Studio\Common\Tools
DLL Universal Problem Solver
The DLL Universal Problem Solver (DUPS) tool is used to audit, compare, document, and display DLL information. The following list describes the utilities that make up the DUPS tool:- Dlister.exe
This utility enumerates all the DLLs on the computer and logs the information to a text file or to a database file. - Dcomp.exe
This utility compares the DLLs that are listed in two text files and produces a third text file that contains the differences. - Dtxt2DB.exe
This utility loads the text files that are created by using the Dlister.exe utility and the Dcomp.exe utility into the dllHell database. - DlgDtxt2DB.exe
This utility provides a graphical user interface (GUI) version of the Dtxt2DB.exe utility.
DLL development
This section describes the issues and the requirements that you should consider when you develop your own DLLs.Types of DLLs
When you load a DLL in an application, two methods of linking let you call the exported DLL functions. The two methods of linking are load-time dynamic linking and run-time dynamic linking.Load-time dynamic linking
In load-time dynamic linking, an application makes explicit calls to exported DLL functions like local functions. To use load-time dynamic linking, provide a header (.h) file and an import library (.lib) file when you compile and link the application. When you do this, the linker will provide the system with the information that is required to load the DLL and resolve the exported DLL function locations at load time.Run-time dynamic linking
In run-time dynamic linking, an application calls either the LoadLibrary function or the LoadLibraryEx function to load the DLL at run time. After the DLL is successfully loaded, you use the GetProcAddress function to obtain the address of the exported DLL function that you want to call. When you use run-time dynamic linking, you do not need an import library file.The following list describes the application criteria for when to use load-time dynamic linking and when to use run-time dynamic linking:
- Startup performance
If the initial startup performance of the application is important, you should use run-time dynamic linking. - Ease of use
In load-time dynamic linking, the exported DLL functions are like local functions. This makes it easy for you to call these functions. - Application logic
In run-time dynamic linking, an application can branch to load different modules as required. This is important when you develop multiple-language versions.
The DLL entry point
When you create a DLL, you can optionally specify an entry point function. The entry point function is called when processes or threads attach themselves to the DLL or detached themselves from the DLL. You can use the entry point function to initialize data structures or to destroy data structures as required by the DLL. Additionally, if the application is multithreaded, you can use thread local storage (TLS) to allocate memory that is private to each thread in the entry point function. The following code is an example of the DLL entry point function.BOOL APIENTRY DllMain(
HANDLE hModule, // Handle to DLL module
DWORD ul_reason_for_call, // Reason for calling function
LPVOID lpReserved ) // Reserved
{
switch ( ul_reason_for_call )
{
case DLL_PROCESS_ATTACHED:
// A process is loading the DLL.
break;
case DLL_THREAD_ATTACHED:
// A process is creating a new thread.
break;
case DLL_THREAD_DETACH:
// A thread exits normally.
break;
case DLL_PROCESS_DETACH:
// A process unloads the DLL.
break;
}
return TRUE;
}
The entry point function should only perform simple initialization tasks and should not call any other DLL loading or termination functions. For example, in the entry point function, you should not directly or indirectly call the LoadLibrary function or the LoadLibraryEx function. Additionally, you should not call the FreeLibrary function when the process is terminating.
Note In multithreaded applications, make sure that access to the DLL global data is synchronized (thread safe) to avoid possible data corruption. To do this, use TLS to provide unique data for each thread.
Exporting DLL functions
To export DLL functions, you can either add a function keyword to the exported DLL functions or create a module definition (.def) file that lists the exported DLL functions.To use a function keyword, you must declare each function that you want to export with the following keyword:
__declspec(dllexport)
To use exported DLL functions in the application, you must declare each function that you want to import with the following keyword:__declspec(dllimport)
Typically, you would use one header file that has a define statement and an ifdef statement to separate the export statement and the import statement.You can also use a module definition file to declare exported DLL functions. When you use a module definition file, you do not have to add the function keyword to the exported DLL functions. In the module definition file, you declare the LIBRARY statement and the EXPORTS statement for the DLL. The following code is an example of a definition file.
// SampleDLL.def
//
LIBRARY "sampleDLL"
EXPORTS
HelloWorldSample DLL and application
In Microsoft Visual C++ 6.0, you can create a DLL by selecting either the Win32 Dynamic-Link Library project type or the MFC AppWizard (dll) project type.The following code is an example of a DLL that was created in Visual C++ by using the Win32 Dynamic-Link Library project type.
// SampleDLL.cpp
//
#include "stdafx.h"
#define EXPORTING_DLL
#include "sampleDLL.h"
BOOL APIENTRY DllMain( HANDLE hModule,
DWORD ul_reason_for_call,
LPVOID lpReserved
)
{
return TRUE;
}
void HelloWorld()
{
MessageBox( NULL, TEXT("Hello World"), TEXT("In a DLL"), MB_OK);
}
// File: SampleDLL.h
//
#ifndef INDLL_H
#define INDLL_H
#ifdef EXPORTING_DLL
extern __declspec(dllexport) void HelloWorld() ;
#else
extern __declspec(dllimport) void HelloWorld() ;
#endif
#endif// SampleApp.cpp
//
#include "stdafx.h"
#include "sampleDLL.h"
int APIENTRY WinMain(HINSTANCE hInstance,
HINSTANCE hPrevInstance,
LPSTR lpCmdLine,
int nCmdShow)
{
HelloWorld();
return 0;
}In run-time dynamic linking, you use code that is similar to the following code to call the SampleDLL.dll exported DLL function.
...
typedef VOID (*DLLPROC) (LPTSTR);
...
HINSTANCE hinstDLL;
DLLPROC HelloWorld;
BOOL fFreeDLL;
hinstDLL = LoadLibrary("sampleDLL.dll");
if (hinstDLL != NULL)
{
HelloWorld = (DLLPROC) GetProcAddress(hinstDLL, "HelloWorld");
if (HelloWorld != NULL)
(HelloWorld);
fFreeDLL = FreeLibrary(hinstDLL);
}
...
- The application folder
- The current folder
- The Windows system folder
Note The GetSystemDirectory function returns the path of the Windows system folder. - The Windows folder
Note The GetWindowsDirectory function returns the path of the Windows folder.
The .NET Framework assembly
With the introduction of Microsoft .NET and the .NET Framework, most of the problems that are associated with DLLs have been eliminated by using assemblies. An assembly is a logical unit of functionality that runs under the control of the .NET common language runtime (CLR). An assembly physically exists as a .dll file or as an .exe file. However, internally an assembly is very different from a Microsoft Win32 DLL.An assembly file contains an assembly manifest, type metadata, Microsoft intermediate language (MSIL) code, and other resources. The assembly manifest contains the assembly metadata that provides all the information that is required for an assembly to be self-describing. The following information is included in the assembly manifest:
- Assembly name
- Version information
- Culture information
- Strong name information
- The assembly list of files
- Type reference information
- Referenced and dependent assembly information
The following list describes some of the features of assemblies compared to the features of Win32 DLLs:
- Self-describing
When you create an assembly, all the information that is required for the CLR to run the assembly is contained in the assembly manifest. The assembly manifest contains a list of the dependent assemblies. Therefore, the CLR can maintain a consistent set of assemblies that are used in the application. In Win32 DLLs, you cannot maintain consistency between a set of DLLs that are used in an application when you use shared DLLs. - Versioning
In an assembly manifest, version information is recorded and enforced by the CLR. Additionally, version policies let you enforce version-specific usage. In Win32 DLLs, versioning cannot be enforced by the operating system. Instead, you must make sure that DLLs are backward compatible. - Side-by-side deployment
Assemblies support side-by-side deployment. One application can use one version of an assembly, and another application can use a different version of an assembly. Starting in Windows 2000, side-by-side deployment is supported by locating DLLs in the application folder. Additionally, Windows File Protection prevents system DLLs from being overwritten or replaced by an unauthorized agent. - Self-containment and isolation
An application that is developed by using an assembly can be self-contained and isolated from other applications that are running on the computer. This feature helps you create zero-impact installations. - Execution
An assembly is run under the security permissions that are supplied in the assembly manifest and that are controlled by the CLR. - Language independent
An assembly can be developed by using any one of the supported .NET languages. For example, you can develop an assembly in Microsoft Visual C#, and then use the assembly in a Microsoft Visual Basic .NET project.
DLL conflicts
http://msdn2.microsoft.com/en-us/library/ms811694.aspx
Implementing side-by-side component sharing in applications
http://msdn2.microsoft.com/en-us/library/ms811700.aspx
How to build and service isolated applications and side-by-side assemblies for Windows XP
http://msdn2.microsoft.com/en-us/library/ms997620.aspx
Simplifying deployment and solving DLL conflicts with the .NET Framework
http://msdn2.microsoft.com/en-us/netframework/aa497268.aspx
The .NET Framework developer's guide: Assemblies
http://msdn2.microsoft.com/en-us/library/hk5f40ct(vs.71).aspx
Run-time dynamic linking
http://msdn2.microsoft.com/en-us/library/ms685090.aspx
Thread local storage
http://msdn2.microsoft.com/en-us/library/ms686749.aspx
http://msdn2.microsoft.com/en-us/library/ms811694.aspx
Implementing side-by-side component sharing in applications
http://msdn2.microsoft.com/en-us/library/ms811700.aspx
How to build and service isolated applications and side-by-side assemblies for Windows XP
http://msdn2.microsoft.com/en-us/library/ms997620.aspx
Simplifying deployment and solving DLL conflicts with the .NET Framework
http://msdn2.microsoft.com/en-us/netframework/aa497268.aspx
The .NET Framework developer's guide: Assemblies
http://msdn2.microsoft.com/en-us/library/hk5f40ct(vs.71).aspx
Run-time dynamic linking
http://msdn2.microsoft.com/en-us/library/ms685090.aspx
Thread local storage
http://msdn2.microsoft.com/en-us/library/ms686749.aspx
Monday, May 2, 2011
Creating SharePoint 2010 permissions levels
Following is the way to define permission level programmatically
First we need to know the permission levels available. following table contains the details:
And now here is the code by which we can define the custom role or permission level:
PRoleDefinition role = new SPRoleDefinition();
role.BasePermissions = SPBasePermissions.OpenItems | SPBasePermissions.EditListItems | SPBasePermissions.ViewListItems | SPBasePermissions.ViewPages | SPBasePermissions.Open | SPBasePermissions.ViewFormPages;
role.Name = “My Role Name”;
role.Description = “My Role Description”;
rootWeb.RoleDefinitions.Add(role);
Then we assign a set of permissions to an existing group in this case called MyGroup
SPRoleAssignment roleAssignment = new SPRoleAssignment(rootWeb.SiteGroups["MyGroup"]);
roleAssignment.RoleDefinitionBindings.Add(role);
rootWeb.RoleAssignments.Add(roleAssignment);
First we need to know the permission levels available. following table contains the details:
Role | Description |
EmptyMask | Has no permissions on the Web site. Not available through the user interface. |
ViewListItems | View items in lists, documents in document libraries, and view Web discussion comments. |
AddListItems | Add items to lists, add documents to document libraries, and add Web discussion comments. |
EditListItems | Edit items in lists, edit documents in document libraries, edit Web discussion comments in documents, and customize Web Part Pages in document libraries. |
DeleteListItems | Delete items from a list, documents from a document library, and Web discussion comments in documents. |
ApproveItems | Approve a minor version of a list item or document. |
OpenItems | View the source of documents with server-side file handlers. |
ViewVersions | View past versions of a list item or document. |
DeleteVersions | Delete past versions of a list item or document. |
CancelCheckout | Discard or check in a document which is checked out to another user. |
ManagePersonalViews | Create, change, and delete personal views of lists. |
ManageLists | Create and delete lists, add or remove columns in a list, and add or remove public views of a list. |
ViewFormPages | View forms, views, and application pages, and enumerate lists. |
Open | Allow users to open a Web site, list, or folder to access items inside that container. |
ViewPages | View pages in a Web site. |
AddAndCustomizePages | Add, change, or delete HTML pages or Web Part Pages, and edit the Web site using a SharePoint Foundation–compatible editor. |
ApplyThemeAndBorder | Apply a theme or borders to the entire Web site. |
ApplyStyleSheets | Apply a style sheet (.css file) to the Web site. |
ViewUsageData | View reports on Web site usage. |
CreateSSCSite | Create a Web site using Self-Service Site Creation. |
ManageSubwebs | Create subsites such as team sites, Meeting Workspace sites, and Document Workspace sites. |
CreateGroups | Create a group of users that can be used anywhere within the site collection. |
ManagePermissions | Create and change permission levels on the Web site and assign permissions to users and groups. |
BrowseDirectories | Enumerate files and folders in a Web site using Microsoft Office SharePoint Designer 2007 and WebDAV interfaces. |
And now here is the code by which we can define the custom role or permission level:
PRoleDefinition role = new SPRoleDefinition();
role.BasePermissions = SPBasePermissions.OpenItems | SPBasePermissions.EditListItems | SPBasePermissions.ViewListItems | SPBasePermissions.ViewPages | SPBasePermissions.Open | SPBasePermissions.ViewFormPages;
role.Name = “My Role Name”;
role.Description = “My Role Description”;
rootWeb.RoleDefinitions.Add(role);
Then we assign a set of permissions to an existing group in this case called MyGroup
SPRoleAssignment roleAssignment = new SPRoleAssignment(rootWeb.SiteGroups["MyGroup"]);
roleAssignment.RoleDefinitionBindings.Add(role);
rootWeb.RoleAssignments.Add(roleAssignment);
Wednesday, April 27, 2011
C++ Programming Style Guidelines
- Use a source code style that makes the code readable and consistent. Unless you have a group code style or a style of your own, you could use a style similar to the Kernighan and Ritchie style used by a vast majority of C programmers. Taken to an extreme, however, it's possible to end up with something like this:
int i;main(){for(;i["]<i;++i){--i;}"];read('-'-'-',i+++"hell\ o, world!\n",'/'/'/'));}read(j,i,p){write(j/p+p,i---j,i/i);
--Dishonorable mention, Obfuscated C Code Contest, 1984. Author requested anonymity. - It is common to see the main routine defined as main(). The ANSI way of writing this is int main(void) (if there are is no interest in the command line arguments) or as int main( int argc, char **argv ). Pre-ANSI compilers would omit the void declaration, or list the variable names and follow with their declarations.
- WhitespaceUse vertical and horizontal whitespace generously. Indentation and spacing should reflect the block structure of the code.
A long string of conditional operators should be split onto separate lines. For example:
if (foo->next==NULL && number < limit && limit <=SIZE && node_active(this_input)) {...
might be better as:
if (foo->next == NULL && number < limit && limit <= SIZE && node_active(this_input)) { ...
Similarly, elaborate for loops should be split onto different lines:
for (curr = *varp, trail = varp; curr != NULL; trail = &(curr->next), curr = curr->next ) { ...
Other complex expressions, such as those using the ternary ?: operator, are best split on to several lines, too.
z = (x == y) ? n + f(x) : f(y) - n; - CommentsThe comments should describe what is happening, how it is being done, what parameters mean, which globals are used and any restrictions or bugs. However, avoid unnecessary comments. If the code is clear, and uses good variable names, it should be able to explain itself well. Since comments are not checked by the compiler, there is no guarantee they are right. Comments that disagree with the code are of negative value. Too many comments clutter code.
Here is a superfluous comment style:
i=i+1; /* Add one to i */
It's pretty clear that the variable i is being incremented by one. And there are worse ways to do it:
/************************************ * * * Add one to i * * * ************************************/ i=i+1; - Naming Conventions Names with leading and trailing underscores are reserved for system purposes and should not be used for any user-created names. Convention dictates that:
- #define constants should be in all CAPS.
- enum constants are Capitalized or in all CAPS
- Function, typedef, and variable names, as well as struct, union, and enum tag names should be in lower case.
- Variable namesWhen choosing a variable name, length is not important but clarity of expression is. A long name can be used for a global variable which is rarely used but an array index used on every line of a loop need not be named any more elaborately than i. Using 'index' or 'elementnumber' instead is not only more to type but also can obscure the details of the computation. With long variable names sometimes it is harder to see what is going on. Consider:
for(i=0 to 100) array[i]=0
versus
for(elementnumber=0 to 100) array[elementnumber]=0; - Function namesFunction names should reflect what they do and what they return. Functions are used in expressions, often in an if clause, so they need to read appropriately. For example:
if (checksize(x))
is unhelpful because it does not tell us whether checksize returns true on error or non-error; instead:
if (validsize(x))
makes the point clear. - DeclarationsAll external data declaration should be preceded by the extern keyword.
The "pointer'' qualifier, '*', should be with the variable name rather than with the type.
char *s, *t, *u;
instead of
char* s, t, u;
The latter statement is not wrong, but is probably not what is desired since 't' and 'u' do not get declared as pointers. - Header FilesHeader files should be functionally organized, that is, declarations for separate subsystems should be in separate header files. Also, declarations that are likely to change when code is ported from one platform to another should be in a separate header file.
Avoid private header filenames that are the same as library header filenames. The statement #include "math.h'' includes the standard library math header file if the intended one is not found in the current directory. If this is what you want to happen, comment this fact.
Finally, using absolute pathnames for header files is not a good idea. The "include-path'' option of the C compiler (-I (capital "eye") on many systems) is the preferred method for handling extensive private libraries of header files; it permits reorganizing the directory structure without having to alter source files. - scanf scanf should never be used in serious applications. Its error detection is inadequate. Look at the example below:
#include <stdio.h> int main(void) { int i; float f; printf("Enter an integer and a float: "); scanf("%d %f", &i, &f); printf("I read %d and %f\n", i, f); return 0; }
Test run
Enter an integer and a float: 182 52.38
I read 182 and 52.380001
Another TEST run
Enter an integer and a float: 6713247896 4.4
I read -1876686696 and 4.400000 - ++ and --When the increment or decrement operator is used on a variable in a statement, that variable should not appear more than once in the statement because order of evaluation is compiler-dependent. Do not write code that assumes an order, or that functions as desired on one machine but does not have a clearly defined behavior:
int i = 0, a[5]; a[i] = i++; /* assign to a[0]? or a[1]? */
- Don't let yourself believe you see what isn't there.Look at the following example:
while (c == '\t' || c = ' ' || c == '\n') c = getc(f);
The statement in the while clause appears at first glance to be valid C. The use of the assignment operator, rather than the comparison operator, results in syntactically incorrect code. The precedence of = is lowest of any operator so it would have to be interpreted this way (parentheses added for clarity):
while ((c == '\t' || c) = (' ' || c == '\n')) c = getc(f);
The clause on the left side of the assignment operator is:
(c == '\t' || c)
which does not result in an lvalue. If c contains the tab character, the result is "true" and no further evaluation is performed, and "true" cannot stand on the left-hand side of an assignment. - Be clear in your intentions. When you write one thing that could be interpreted for something else, use parentheses or other methods to make sure your intent is clear. This helps you understand what you meant if you ever have to deal with the program at a later date. And it makes things easier if someone else has to maintain the code.
It is sometimes possible to code in a way that anticipates likely mistakes. For example, you can put constants on the left of equality comparisons. That is, instead of writing:
while (c == '\t' || c == ' ' || c == '\n') c = getc(f);
You can say:
while ('\t' == c || ' ' == c || '\n' == c) c = getc(f);
This way you will get a compiler diagnostic:
while ('\t' = c || ' ' == c || '\n' == c) c = getc(f);
This style lets the compiler find problems; the above statement is invalid because it tries to assign a value to '\t'. - Trouble from unexpected corners.C implementations generally differ in some aspects from each other. It helps to stick to the parts of the language that are likely to be common to all implementations. By doing that, it will be easier to port your program to a new machine or compiler and less likely that you will run into compiler idiosyncracies. For example, consider the string:
/*/*/2*/**/1
This takes advantage of the "maximal munch" rule. If comments nest, it is interpreted this way:
/* /* /2 */ * */ 1
The two /* symbols match the two */ symbols, so the value of this is 1. If comments do not nest, on some systems, a /* in a comment is ignored. On others a warning is flagged for /*. In either case, the expression is interpreted this way:
/* / */ 2 * /* */ 1
2 * 1 evaluates to 2. - Flushing Output BufferWhen an application terminates abnormally, the tail end of its output is often lost. The application may not have the opportunity to completely flush its output buffers. Part of the output may still be sitting in memory somewhere and is never written out. On some systems, this output could be several pages long.
Losing output this way can be misleading because it may give the impression that the program failed much earlier than it actually did. The way to address this problem is to force the output to be unbuffered, especially when debugging. The exact incantation for this varies from system to system but usually looks something like this:
setbuf(stdout, (char *) 0);
This must be executed before anything is written to stdout. Ideally this could be the first statement in the main program. - getchar() - macro or functionThe following program copies its input to its output:
#include <stdio.h> int main(void) { register int a; while ((a = getchar()) != EOF) putchar(a); }
Removing the #include statement from the program would cause it to fail to compile because EOF would then be undefined.
We can rewrite the program in the following way:
#define EOF -1 int main(void) { register int a; while ((a = getchar()) != EOF) putchar(a); }
This will work on many systems but on some it will run much more slowly.
Since function calls usually take a long time, getchar is often implemented as a macro. This macro is defined in stdio.h, so when #include <stdio.h> is removed, the compiler does not know what getchar is. On some systems it assumes that getchar is a function that returns an int.
In reality, many C implementations have a getchar function in their libraries, partly to safeguard against such lapses. Thus in situations where #include <stdio.h> is missing the compiler uses the function version of getchar. Overhead of function call makes the program slower. The same argument applies to putchar. - null pointerA null pointer does not point to any object. Thus it is illegal to use a null pointer for any purpose other than assignment and comparison.
Never redefine the NULL symbol. The NULL symbol should always have a constant value of zero. A null pointer of any given type will always compare equal to the constant zero, whereas comparison with a variable with value zero or to some non-zero constant has implementation-defined behaviour.
Dereferencing a null pointer may cause strange things to happen. - What does a+++++b mean?The only meaningful way to parse this is:
a ++ + ++ b
However, the maximal munch rule requires it to be broken down as:
a ++ ++ + b
This is syntactically invalid: it is equivalent to:
((a++)++) + b
But the result of a++ is not an lvalue and hence is not acceptable as an operand of ++. Thus the rules for resolving lexical ambiguity make it impossible to resolve this example in a way that is syntactically meaningful. In practice, of course, the prudent thing to do is to avoid construction like this unless you are absolutely certain what they mean. Of course, adding whitespace helps the compiler to understand the intent of the statement, but it is preferable (from a code maintenance perspective) to split this construct into more than one line:
++b; (a++) + b;
- Treat functions with care Functions are the most general structuring concept in C. They should be used to implement "top-down" problem solving - namely breaking up a problem into smaller and smaller subproblems until each piece is readily expressed in code. This aids modularity and documentation of programs. Moreover, programs composed of many small functions are easier to debug.
Cast all function arguments to the expected type if they are not of that type already, even when you are convinced that this is unnecessary since they may hurt you when you least expect it. In other words, the compiler will often promote and convert data types to conform to the declaration of the function parameters. But doing so manually in the code clearly explains the intent of the programmer, and may ensure correct results if the code is ever ported to another platform.
If the header files fail to declare the return types of the library functions, declare them yourself. Surround your declarations with #ifdef/#endif statements in case the code is ever ported to another platform.
Function prototypes should be used to make code more robust and to make it run faster. - Dangling elseStay away from "dangling else" problem unless you know what you're doing:
if (a == 1) if (b == 2) printf("***\n"); else printf("###\n");
The rule is that an else attaches to the nearest if. When in doubt, or if there is a potential for ambiguity, add curly braces to illuminate the block structure of the code. - Array boundsCheck the array bounds of all arrays, including strings, since where you type "fubar'' today someone someday may type "floccinaucinihilipilification". Robust production software should not use gets().
The fact that C subscripts start from zero makes all kinds of counting problems easier. However, it requires some effort to learn to handle them. - Null statementThe null body of a for or while loop should be alone on a line and commented so that it is clear that the null body is intentional and not missing code.
while (*dest++ = *src++) ; /* VOID */ - Test for true or falseDo not default the test for non-zero, that is:
if (f() != FAIL)
is better than
if (f())
even though FAIL may have the value 0 which C considers to be false. (Of course, balance this against constructs such as the one shown above in the "Function Names" section.) An explicit test will help you out later when somebody decides that a failure return should be -1 instead of 0.
A frequent trouble spot is using the strcmp function to test for string equality, where the result should never be defaulted. The preferred approach is to define a macro STREQ:
#define STREQ(str1, str2) (strcmp((str1), (str2)) == 0)
Using this, a statement such as:
If ( STREQ( inputstring, somestring ) ) ...
carries with it an implied behavior that is unlikely to change under the covers (folks tend not to rewrite and redefine standard library functions like strcmp()).
Do not check a boolean value for equality with 1 (TRUE, YES, etc.); instead test for inequality with 0 (FALSE, NO, etc.). Most functions are guaranteed to return 0 if false, but only non-zero if true. Thus,
if (func() == TRUE) {...
is better written
if (func() != FALSE)
- Embedded statementThere is a time and a place for embedded assignment statements. In some constructs there is no better way to accomplish the results without resulting in bulkier and less readable code:
while ((c = getchar()) != EOF) { process the character }
Using embedded assignment statements to improve run-time performance is possible. However, you should consider the tradeoff between increased speed and decreased maintainability that results when embedded assignments are used in artificial places. For example:
x = y + z; d = x + r;
should not be replaced by:
d = (x = y + z) + r;
even though the latter may save one cycle. In the long run the time difference between the two will decrease as the optimizer is enhanced, while the difference in ease of maintenance will increase. - goto statementsgoto should be used sparingly. The one place where they can be usefully employed is to break out of several levels of switch, for, and while nesting, although the need to do such a thing may indicate that the inner constructs should be broken out into a separate function.
for (...) { while (...) { ... if (wrong) goto error; } } ... error: print a message
When a goto is necessary the accompanying label should be alone on a line and either tabbed one stop to the left of the code that follows, or set at the beginning of the line. Both the goto statement and target should be commented to their utility and purpose. - Fall-though in switchWhen a block of code has several labels, place the labels on separate lines. This style agrees with the use of vertical whitespace, and makes rearranging the case options a simple task, should that be required. The fall-through feature of the C switch statement must be commented for future maintenance. If you've ever been "bitten" by this feature, you'll appreciate its importance!
switch (expr) { case ABC: case DEF: statement; break; case UVW: statement; /*FALLTHROUGH*/ case XYZ: statement; break; }
While the last break is technically unnecessary, the consistency of its use prevents a fall-through error if another case is later added after the last one. The default case, if used, should always be last and does not require a final break statement if it is last. - ConstantsSymbolic constants make code easier to read. Numerical constants should generally be avoided; use the #define function of the C preprocessor to give constants meaningful names. Defining the value in one place (preferably a header file) also makes it easier to administer large programs since the constant value can be changed uniformly by changing only the define. Consider using the enumeration data type as an improved way to declare variables that take on only a discrete set of values. Using enumerations also lets the compiler warn you of any misuse of an enumerated type. At the very least, any directly-coded numerical constant must have a comment explaining the derivation of the value.
Constants should be defined consistently with their use; e.g. use 540.0 for a float instead of 540 with an implicit float cast. That said, there are some cases where the constants 0 and 1 may appear as themselves instead of as defines. For example if a for loop indexes through an array, then:
for (i = 0; i < arraysub; i++)
is quite reasonable, while the code:
gate_t *front_gate = opens(gate[i], 7); if (front_gate == 0) error("can't open %s\n", gate[i]);
is not. In the second example front_gate is a pointer; when a value is a pointer it should be compared to NULL instead of 0. Even simple values like 1 or 0 are often better expressed using defines like TRUE and FALSE (and sometimes YES and NO read better).
Don't use floating-point variables where discrete values are needed. This is due to the inexact representation of floating point numbers (see the second test in scanf, above). Test floating-point numbers using <= or >=; an exact comparison (== or !=) may not detect an "acceptable" equality.
Simple character constants should be defined as character literals rather than numbers. Non-text characters are discouraged as non-portable. If non-text characters are necessary, particularly if they are used in strings, they should be written using a escape character of three octal digits rather than one (for example, '\007'). Even so, such usage should be considered machine-dependent and treated as such. - Conditional CompilationConditional compilation is useful for things like machine-dependencies, debugging, and for setting certain options at compile-time. Various controls can easily combine in unforeseen ways. If you use #ifdef for machine dependencies, make sure that when no machine is specified, the result is an error, not a default machine. The #error directive comes in handy for this purpose. And if you use #ifdef for optimizations, the default should be the unoptimized code rather than an uncompilable or incorrect program. Be sure to test the unoptimized code.
- Utilities for compiling and linking such as Make simplify considerably the task of moving an application from one environment to another. During development, make recompiles only those modules that have been changed since the last time make was used. Use lint frequently. lint is a C program checker that examines C source files to detect and report type incompatibilities, inconsistencies between function definitions and calls, potential program bugs, etc.
Also, investigate the compiler documentation for switches that encourage it to be "picky". The compiler's job is to be precise, so let it report potential problems by using appropriate command line options. - Minimize the number of global symbols in the application. One of the benefits is the lower probability of conflicts with system-defined functions.
- Many programs fail when their input is missing. All programs should be tested for empty input. This is also likely to help you understand how the program is working
- Don't assume any more about your users or your implementation than you have to. Things that "cannot happen" sometimes do happen. A robust program will defend against them. If there's a boundary condition to be found, your users will somehow find it! Never make any assumptions about the size of a given type, especially pointers.
When char types are used in expressions most implementations will treat them as unsigned but there are others which treat them as signed. It is advisable to always cast them when used in arithmetic expressions.
Do not rely on the initialization of auto variables and of memory returned by malloc. - Make your program's purpose and structure clear.
- Keep in mind that you or someone else will likely be asked to modify your code or make it run on a different machine sometime in the future. Craft your code so that it is portable to other machines.
Subscribe to:
Posts (Atom)
Featured Posts
OBS Browser Source Not Working? How to Interact With Web Pages Inside OBS Studio
If you're using OBS Studio to display a website, YouTube page, dashboard, live poll, chat widget, or web application, you may notice so...
-
public struct CoOrds { public int x, y; public CoOrds( int p1, int p2) { x = p1; y = p2; } }
-
LM Studio Overview LM Studio is a desktop application designed for developing and experimenting with large language models (LLMs)...