宏的随堂练习3:写一个log宏
#include <stdio.h>
//frm用于接收printf的第一个参数const char* format(格式控制字符串)
//printf第二个参数是变参... ,变参宏则在...前取一个名字作为标志,如args...
// 技巧:##连接,则允许某个参数为空, -E时发现frm后面无',' 是因为编译器做的优化
#ifdef DEBUG
#define log(frm, args...) { \
printf("[%s : %s : %d]", __FILE__, __func__, __LINE__);\
printf(frm, ##args); \
}
#else
#define log(frm, args...)
#endif
// 条件式编译,如果定义了DEBUG,则输出log,否则什么都不做。
// 编译时需要加-D参数, 如:gcc -DDEBUG main.c ,则会输出log内容
int main() {
int x = 123;
int y = 234;
log("%d %d\n", x, y);
log("Hello World\n"); // args前不加## 会报错
return 0;
}
技巧:##连接,则允许某个参数为空
#define contact(a, b) a##b
//int abc, def;//某些环境不能去掉,否则会报错
int abcdef = 0;
contact(abc, def) = 123123;
printf("%d", abcdef); // 返回值是123123
如果写成
#define contact(a, b) ab
则表示将contact(a, b)替换成字符串ab
gcc -DDEBUG 1.c
-D参数是指的是在预处理阶段手动加入某某宏
-------------------------------------------
宏的代码演示:
attribute宏(gcc标准宏):使其他函数优于main函数执行
#include <stdio.h>
// attribute宏:使其他函数优于main函数执行
__attribute__((constructor))
void test() {
printf("test\n");
}
// main不能省略
int main() {
return 0;
}
泛型宏:
#include <stdio.h>
// 泛型宏_Generic 根据传入内容替换字符串
#define TYPE_STR(a) _Generic((a),\
int : "%d",\
double : "%.2lf",\
char * : "%s"\
)
// 想办法加入\n
//#define TYPE(a) TYPE_SRT(a)
int main() {
int a = 123;
double r = 3.1415926;
char str[] = "hello world";
printf(TYPE_STR(a), a);
printf("\n");
printf(TYPE_STR(r), r);
printf("\n");
printf(TYPE_STR(str), str);
printf("\n");
return 0;
}
船长bug了 想办法
----------------------------------------------
字符串(2时02分):
字符数组:
0~n-1
// 定义字符数组
char str[size]
// 初始化
char str[] = "Hello"; // 将一行字符串当一个值赋值给字符数组
char str[size] = {'h', 'e', 'l', 'l', 'o'};
char str[size] = {0};
// \0 是字符杠0,(空字符),对应ASCII码是:0 0x00
// 遍历字符
for (int i = 0; str[i]; i++) {
cout << str[i];
}
头文件:string.h
函数:
strlen(str):计算字符串长度,以\0作为结束符(不统计\0,使用sizeof可以统计\0)
-----------
strcmp(str1, str2):字符串比较(<0[str1 < str2] =0[str1 = str2] >0[str1 > str2])
strcpy(dest, src):字符串拷贝(src拷贝到dest)
上面一组一直找\0,而\0可能会被误操作干掉,导致不安全。
-----------
strncmp(str1, str2, n):安全的字符串比较
strncpy(str1, str2, n):安全的字符串拷贝
安全的(工程用):先受n控制,不足n位则受\0控制
-----------
memcpy(str1, str2, n):内存拷贝,将str2指向内存的内容拷贝到str1,n表示拷贝的字节数。
memcmp(str1, str2, n):内存比较,将两段内存比较,看看里面的值是否相同。
memset(str1, c, n):内存设置,将str1所指向的空间里面,每一个字节(n个)初始化成c值
int arr[100] = {0};
等价于:
memset(arr, 0, sizeof(int) * 100);
注意:memset是按照字节赋值,除了0、-1可以正常逻辑赋值,其他的比如赋1,则实际上为:00000001 00000001 00000001 00000001
内存的操作速度比字符串快。mem可以接收非字符串的数组
-----------
sscanf(str1, format, ... );从字符串str1中读入内容。
sprintf(str1, format, ... );将内容输出到str1中
随堂练习4:
使用字符串相关方法,计算一个整型16进制表示的数位
利用sprintf
或者%x
#include <stdio.h>
#include <string.h>
int main() {
char str[11];
int n;
while (~scanf("%d", &n)) {
sprintf(str, "%X", n);
printf("%d(%s) has %lu digits\n", n, str, strlen(str));
}
return 0;
}