全国网站建设哪家专业,怎么开彩票网站做站长,wordpress内容登陆后可见,临沂建设质量监督站网站文章目录 1. 预处理器1.1 预处理器实例1.2 预定义宏1.3 预处理器运算符1.4 参数化的宏 2. 输入和输出2.1 getchar() putchar() 函数2.2 gets() puts() 函数 3. 文件读写3.1 打开文件3.2 关闭文件3.3 写入文件3.4 读取文件3.5 二进制 I/O 函数 4. typedef 和 #defin… 文章目录 1. 预处理器1.1 预处理器实例1.2 预定义宏1.3 预处理器运算符1.4 参数化的宏 2. 输入和输出2.1 getchar() putchar() 函数2.2 gets() puts() 函数 3. 文件读写3.1 打开文件3.2 关闭文件3.3 写入文件3.4 读取文件3.5 二进制 I/O 函数 4. typedef 和 #define的用法与区别 1. 预处理器
C 预处理器是 C 编程语言中的一个重要组成部分它在源代码编译之前执行一系列文本处理任务。 预处理器的任务包括宏替换、文件包含和条件编译等它主要有以下几个作用 宏替换预处理器可以定义和展开宏这是一种将标识符替换为具体的文本的方式。宏可以用来创建常量、函数或代码片段的别名提高代码的可读性和维护性。 示例 #define MAX(x, y) ((x) (y) ? (x) : (y))
int result MAX(5, 8); // 替换为 int result ((5) (8) ? (5) : (8));文件包含预处理器可以使用#include指令将其他源代码文件的内容包含到当前文件中这有助于模块化和组织代码。 示例 #include stdio.h // 包含标准库头文件条件编译预处理器允许在编译时基于条件包括或排除特定部分的代码这对于支持多个平台或构建配置非常有用。 示例 #ifdef DEBUG
// 仅在 DEBUG 定义时编译这部分代码
#endif注释删除预处理器会删除注释这有助于减小生成的可执行文件的大小。 符号替换预处理器会执行一些符号替换操作例如#操作符用于将宏参数字符串化##操作符用于连接标识符等。
总之C 预处理器在编译之前执行文本处理任务以生成可编译的源代码。这使得 C 语言更加灵活并可以根据不同的编译需求进行配置。然而过度使用预处理器指令可能导致代码难以维护因此需要谨慎使用。
C 预处理器不是编译器的组成部分但是它是编译过程中一个单独的步骤,简言之C 预处理器只不过是一个文本替换工具而已它们会指示编译器在实际编译之前完成所需的预处理。
我们将把 C 预处理器C Preprocessor简写为 CPP。
所有的预处理器命令都是以井号#开头。 它必须是第一个非空字符为了增强可读性预处理器指令应从第一列开始。
下面列出了所有重要的预处理器指令 #define 定义宏 #include 包含一个源代码文件 #undef 取消已定义的宏 #ifdef 如果宏已经定义则返回真 #ifndef 如果宏没有定义则返回真 #if 如果给定条件为真则编译下面代码 #else #if 的替代方案 #elif 如果前面的 #if 给定条件不为真当前条件为真则编译下面代码 #endif 结束一个 #if……#else 条件编译块 #error 当遇到标准错误时输出错误消息 #pragma 使用标准化方法向编译器发布特殊的命令到编译器中 1.1 预处理器实例
分析下面的实例来理解不同的指令。
#define MAX_ARRAY_LENGTH 20这个指令告诉 CPP 把所有的 MAX_ARRAY_LENGTH 定义为 20。使用 #define 定义常量来增强可读性。
#include stdio.h
#include myheader.h这些指令告诉 CPP 从系统库中获取 stdio.h并添加文本到当前的源文件中。 下一行告诉 CPP 从本地目录中获取 myheader.h并添加内容到当前的源文件中。
#undef FILE_SIZE
#define FILE_SIZE 42这个指令告诉 CPP 取消已定义的 FILE_SIZE并定义它为 42。
#ifndef MESSAGE#define MESSAGE You wish!
#endif这个指令告诉 CPP 只有当 MESSAGE 未定义时才定义 MESSAGE。 即如果 MESSAGE 这个宏没有被定义那么将其定义为字符串 “You wish!”。如果 MESSAGE 已经在代码中定义了那么这个代码块不会产生任何效果因为条件不满足。这种条件编译的方式常用于确保宏在多次包含相同头文件时不会重复定义从而避免编译错误。
#ifdef DEBUG/* Your debugging statements here */
#endif这个指令告诉 CPP 如果定义了 DEBUG则执行处理语句。在编译时如果向 gcc 编译器传递了 -DDEBUG 开关量这个指令就非常有用。它定义了 DEBUG可以在编译期间随时开启或关闭调试。
1.2 预定义宏
ANSI C 定义了许多宏在编程中我们可以使用这些宏但是不能直接修改这些预定义的宏。
宏 描述 __DATE__ 当前日期一个以 “MMM DD YYYY” 格式表示的字符常量。 __TIME__ 当前时间一个以 “HH:MM:SS” 格式表示的字符常量。 __FILE__ 这会包含当前文件名一个字符串常量。 __LINE__ 这会包含当前行号一个十进制常量。 __STDC__ 当编译器以 ANSI 标准编译时则定义为 1。
让我们来尝试下面的实例
#include stdio.hmain()
{printf(File :%s\n, __FILE__ );printf(Date :%s\n, __DATE__ );printf(Time :%s\n, __TIME__ );printf(Line :%d\n, __LINE__ );printf(ANSI :%d\n, __STDC__ );}当上面的代码在文件 hong.c 中被编译和执行时它会产生下列结果
File :.\hong.c
Date :Oct 13 2023
Time :18:28:58
Line :8
ANSI :11.3 预处理器运算符
C 预处理器提供了下列的运算符来帮助我们创建宏
1. 宏延续运算符\ 一个宏通常写在一个单行上。但是如果宏太长一个单行容纳不下则使用宏延续运算符\。 例如
#define message_for(a, b) \printf(#a and #b : We love you!\n)2. 字符串常量化运算符# 在宏定义中当需要把一个宏的参数转换为字符串常量时则使用字符串常量化运算符#。在宏中使用的该运算符有一个特定的参数或参数列表。 例如
#include stdio.h#define message_for(a, b) \printf(#a and #b : We love you!\n)int main(void)
{message_for(Carole, Debra);return 0;
}当上面的代码被编译和执行时它会产生下列结果
Carole and Debra: We love you!3. 标记粘贴运算符## 宏定义内的标记粘贴运算符##会合并两个参数。它允许在宏定义中两个独立的标记被合并为一个标记。 例如
#include stdio.h#define tokenpaster(n) printf (token #n %d, token##n)int main(void)
{int token34 40;tokenpaster(34);return 0;
}当上面的代码被编译和执行时它会产生下列结果
token34 40这是怎么发生的因为这个实例会从编译器产生下列的实际输出
printf (token34 %d, token34);这个实例演示了 token##n 会连接到 token34 中在这里我们使用了字符串常量化运算符#和标记粘贴运算符##。
defined() 运算符 预处理器 defined 运算符是用在常量表达式中的用来确定一个标识符是否已经使用 #define 定义过。如果指定的标识符已定义则值为真非零。如果指定的标识符未定义则值为假零。
下面的实例演示了 defined() 运算符的用法
#include stdio.h#if !defined (MESSAGE)#define MESSAGE You wish!
#endifint main(void)
{printf(Here is the message: %s\n, MESSAGE); return 0;
}
当上面的代码被编译和执行时它会产生下列结果
Here is the message: You wish!1.4 参数化的宏
CPP 一个强大的功能是可以使用参数化的宏来模拟函数。
例如下面的代码是计算一个数的平方
int square(int x) {return x * x;
}我们可以使用宏重写上面的代码如下
#define square(x) ((x) * (x))在使用带有参数的宏之前必须使用 #define 指令定义参数列表是括在圆括号内且必须紧跟在宏名称的后边。宏名称和左圆括号之间不允许有空格。
例如
#include stdio.h#define MAX(x,y) ((x) (y) ? (x) : (y))int main(void)
{printf(Max between 20 and 10 is %d\n, MAX(10, 20)); return 0;
}当上面的代码被编译和执行时它会产生下列结果
Max between 20 and 10 is 202. 输入和输出
scanf() 和 printf() 函数zheicx就不提了。
2.1 getchar() putchar() 函数
getchar() 函数从屏幕读取下一个可用的字符并把它返回为一个整数。
这个函数在同一个时间内只会读取一个单一的字符所以我们可以在循环内使用这个方法以便从屏幕上读取多个字符。 putchar() 函数把字符输出到屏幕上并返回相同的字符。这个函数在同一个时间内只会输出一个单一的字符。您可以在循环内使用这个方法以便在屏幕上输出多个字符。
请看下面的实例
#include stdio.hint main( )
{int c;printf( Enter a value :);c getchar( );printf( \nYou entered: );putchar( c );printf( \n);return 0;
}当上面的代码被编译和执行时它会等待您输入一些文本当您输入一个文本并按下回车键时程序会继续并只会读取一个单一的字符显示如下
Enter a value :12345You entered: 1 2.2 gets() puts() 函数
gets() 函数从 stdin 读取一行到 s 所指向的缓冲区直到一个终止符或 EOF。
puts() 函数把字符串 s 和一个尾随的换行符写入到 stdout。
实例
#include stdio.hint main( )
{char str[100];printf( Enter a value :);gets( str );printf( \nYou entered: );puts( str );return 0;
}当上面的代码被编译和执行时它会等待您输入一些文本当您输入一个文本并按下回车键时程序会继续并读取一整行直到该行结束显示如下
Enter a value :hello worldYou entered: hello world3. 文件读写
3.1 打开文件
可以使用 fopen( ) 函数来创建一个新的文件或者打开一个已有的文件这个调用会初始化类型 FILE 的一个对象类型 FILE 包含了所有用来控制流的必要的信息。
下面是这个函数调用的原型
FILE *fopen( const char *filename, const char *mode );在这里filename 是字符串用来命名文件访问模式 mode 的值可以是下列值中的一个
r 打开一个已有的文本文件允许读取文件。w 打开一个文本文件允许写入文件。如果文件不存在则会创建一个新文件。在这里您的程序会从文件的开头写入内容。如果文件存在则该会被截断为零长度重新写入。a 打开一个文本文件以追加模式写入文件。如果文件不存在则会创建一个新文件。在这里您的程序会在已有的文件内容中追加内容。r 打开一个文本文件允许读写文件。w 打开一个文本文件允许读写文件。如果文件已存在则文件会被截断为零长度如果文件不存在则会创建一个新文件。a 打开一个文本文件允许读写文件。如果文件不存在则会创建一个新文件。读取会从文件的开头开始写入则只能是追加模式。
如果处理的是二进制文件则需使用下面的访问模式来取代上面的访问模式
rb, wb, ab, rb, rb, wb, wb, ab, ab3.2 关闭文件
为了关闭文件请使用 fclose( ) 函数。函数的原型如下 int fclose( FILE *fp );如果成功关闭文件fclose( ) 函数返回零如果关闭文件时发生错误函数返回 EOF。
这个函数实际上会清空缓冲区中的数据关闭文件并释放用于该文件的所有内存。EOF 是一个定义在头文件 stdio.h 中的常量。
C 标准库提供了各种函数来按字符或者以固定长度字符串的形式读写文件。
3.3 写入文件
下面是把字符写入到流中的最简单的函数
int fputc( int c, FILE *fp );函数 fputc() 把参数 c 的字符值写入到 fp 所指向的输出流中。如果写入成功它会返回写入的字符如果发生错误则会返回 EOF。
可以使用下面的函数来把一个以 null 结尾的字符串写入到流中
int fputs( const char *s, FILE *fp );函数 fputs() 把字符串 s 写入到 fp 所指向的输出流中。如果写入成功它会返回一个非负值如果发生错误则会返回 EOF。
也可以使用 int fprintf(FILE *fp,const char *format, …) 函数把一个字符串写入到文件中。
尝试下面的实例
#include stdio.hint main()
{FILE *fp NULL;fp fopen(./test.txt, w);fprintf(fp, This is testing for fprintf...\n);fputs(This is testing for fputs...\n, fp);fclose(fp);
}当上面的代码被编译和执行时它会在 程序所在当前目录中创建一个新的文件 test.txt并使用两个不同的函数写入两行。 接下来让我们来读取这个文件。
3.4 读取文件
下面是从文件读取单个字符的最简单的函数
int fgetc( FILE * fp );fgetc() 函数从 fp 所指向的输入文件中读取一个字符。返回值是读取的字符如果发生错误则返回 EOF。
下面的函数允许我们从流中读取一个字符串
char *fgets( char *buf, int n, FILE *fp );函数 fgets() 从 fp 所指向的输入流中读取 n - 1 个字符。它会把读取的字符串复制到缓冲区 buf并在最后追加一个 null 字符来终止字符串。
如果这个函数在读取最后一个字符之前就遇到一个换行符 ‘\n’ 或文件的末尾 EOF则只会返回读取到的字符包括换行符。
也可以使用 int fscanf(FILE *fp, const char *format, …) 函数来从文件中读取字符串但是在遇到第一个空格和换行符时它会停止读取。
实例
#include stdio.hint main()
{FILE *fp NULL;char buff[255];fp fopen(./test.txt, r);fscanf(fp, %s, buff);printf(1: %s\n, buff );fgets(buff, 255, (FILE*)fp);printf(2: %s\n, buff );fgets(buff, 255, (FILE*)fp);printf(3: %s\n, buff );fclose(fp);}当上面的代码被编译和执行时它会读取上一部分创建的文件产生下列结果
1: This
2: is testing for fprintf... 3: This is testing for fputs...首先fscanf() 方法只读取了 This因为它在后边遇到了一个空格。 其次调用 fgets() 读取剩余的部分直到行尾。 最后调用 fgets() 完整地读取第二行。
3.5 二进制 I/O 函数
下面两个函数用于二进制输入和输出
size_t fread(void *ptr, size_t size_of_elements, size_t number_of_elements, FILE *a_file);size_t fwrite(const void *ptr, size_t size_of_elements, size_t number_of_elements, FILE *a_file);这两个函数都是用于存储块的读写 - 通常是数组或结构体。
4. typedef 和 #define的用法与区别
C 语言提供了 typedef 关键字我们可以使用它来为类型取一个新的名字。
下面的实例为单字节数字定义了一个术语 BYTE
typedef unsigned char BYTE;在这个类型定义之后标识符 BYTE 可作为类型 unsigned char 的缩写例如
BYTE b1, b2;按照惯例定义时会大写字母以便提醒用户类型名称是一个象征性的缩写但您也可以使用小写字母如下
typedef unsigned char byte;也可以使用 typedef 来为用户自定义的数据类型取一个新的名字。例如可以对结构体使用 typedef 来定义一个新的数据类型名字然后使用这个新的数据类型来直接定义结构变量如下实例
#include stdio.h
#include string.htypedef struct Books
{char title[50];char author[50];char subject[100];int book_id;
} Book;int main( )
{Book book;strcpy( book.title, 完美世界);strcpy( book.author, 辰东); strcpy( book.subject, 玄幻小说);book.book_id 12345;printf( 书标题 : %s\n, book.title);printf( 书作者 : %s\n, book.author);printf( 书类目 : %s\n, book.subject);printf( 书 ID : %d\n, book.book_id);return 0;
}当上面的代码被编译和执行时它会产生下列结果
书标题 : 完美世界
书作者 : 辰东
书类目 : 玄幻小说
书 ID : 12345 #define 是 C 指令用于为各种数据类型定义别名与 typedef 类似但是它们有几点不同。
#define 和 typedef 的区别
1. typedef 仅限于为类型定义符号名称#define 不仅可以为类型定义别名也能为数值定义别名比如您可以定义 1 为 ONE。 2. typedef 是由编译器执行解释的#define 语句是由预编译器进行处理的。
下面是 #define 的最简单的用法
实例
#include stdio.h#define TRUE 1
#define FALSE 0int main( )
{printf( TRUE 的值: %d\n, TRUE);printf( FALSE 的值: %d\n, FALSE);return 0;
}当上面的代码被编译和执行时它会产生下列结果
TRUE 的值: 1
FALSE 的值: 0