1. C语言中,使用第一个字符的地址,表示整个字符串。'\0' 是字符串的结尾字符,他的位置决定了一个字符串中有效字符变量的个数。
'\0' 在 ASCII 中对应数字 0 ;
2. 字面值是程序中表示字符串的一种写法,用双引号表示,不可以被修改。
多个相同内容的字面值在程序运行时都是同一个地址。
多个连续的字符串在编译时会被合并成一个。
char *p = "abc"; // p 表示字符串首地址,该值不能被修改
char *p1 = 'a'; // 错误,提示整数类型不可以赋值给指针,传递的是 a 对应的 ASCII 值;
// 如果是 char *p1 = "a"; 则正确;传递的是 a 在内存中的地址;
printf("%s\n", p);
*p = 'm'; // 错误,字符串字面值不可以修改
printf("%p\n", "abc"); // 此处打印出来的地址和上面 p 打印出来的地址一样
printf("%s\n", "abc""xyz"); // 输出为一个字符串:abcxyz;
字符数组也可以表示字符串,它存储在栈中。可以被修改,可以使用多种方式初始化。
char str[] = "abc";
char str1[3] = "abc"; // 这个写法不对,因为 '\0' 没处放;
char str2[] = {'a', 'b', 'c'}; // 错误,没有 0 ,不可以当数组用
char str3[] = {'a', 'b', 'c', 0}; // 正确
printf("%s\n", str); // 输出为:abc
printf("%d\n", sizeof(str) / sizeof(str[0]));
// 计算出字符串数组大小,输出为:4。因为后面还有一个 '\0',在编译的时候计算机自动加上。
str[0] = 'm'; // 数组表示的字符串可以改动,和上面的字面值不一样
str[1] = 0;
printf("%s\n", str); // 输出为:m,因为第二个为 0,所以计算机自动停止
3. 字符串数组常用操作:(denglu.c)
首先,字符串数组要包含头文件: #include <string.h>
fgets 函数用来从键盘读取字符串,不会出现字符数组溢出问题;
strlen 计算字符串长度(实际长度);
strcat 合并两个字符串,第二个参数的首字符必须为 char 类型;
此函数容易导致合并后长度过长,溢出。
strncat 合并字符串,且避免溢出。
strcpy 赋值字符串,同样容易溢出。
strncpy 赋值字符串,且避免溢出。
strcmp 通过 ASCII 比较字符串大小。前者大,返回 1;后者大返回 -1;一样大返回 0。
strncmp 比较两字符串中前 n 个字符大小。
#include <string.h>
char buf[10] = {0};
fgets(buf, 10, stdin); // 若输入字符超过9个,只提取前面9个,最后留一个0位置。若少于9个,那么会把\n读进去。
printf("%d\n", strlen(buf)); // 计算字符串有效字符长度(不包括 “\0”)
char str[10] = "abc";
strcat(str, "x0yz"); // str = str + "x0yz";
strcpy(str, "wqq"); // str = "wqq";
strcmp("abc","acd"); // 返回 -1
char arr[10];
printf ("%d\n", sizeof (arr)); // 10
printf ("%d\n", strlen (arr)); // 9
4. main函数参数(了解即可,很少使用)
int main(int argc, char *argv[])
5. 预处理命令 #define 专门给数字取名字,如给 3.14 取名字:
#define PI 3.14f // 后面不可以加分号,也不可以加赋值等号。
用#define取的名字叫宏,如此处 PI 即为宏;名字之间不能有空格,即不能写为:P I;
另外一种宏定义方式:
在gcc(终端)里面输入:gcc -D PI=3014 code.c
6. 宏不仅可以定义数字,还可以定义公式等,即带参数宏:
#define PI 3.14f
#define CIRCLE(r) 2 * PI * (r) // 一般给参数加个(),保证参数先运算
#define SQRE (60 * 60) // 若是个计算式,记得加个括号
#define SQUARE(n) ((n) * (n))
#define STR(n) #n // 把参数字符串化,相当于 “n”,如:STR(6+3),输出结果为:6+3
#define PTR(n) p_##n // 重命名标志符,如:PTR(value),输出结果为:p_value
宏的参数既是输入参数,又是输出参数;且参数要用()。
不要使用自增或自减作为参数传递给宏。
编译器预定义的一些宏:
printf("%d\n", __LINE__); // 显示当前行号
printf("%s\n", __FILE__); // 当前文件名
printf("%s\n", __DATE__); // 当前编译日期
printf("%s\n", __TIME__); // 当前编译时间
printf("%s\n", __STDC__ ? "符合" : "不符合"); // 查看编译器是否符合C标准,如果符合打印“符合”,反之“不符合”;
问:论述含参数的宏与函数的优缺点 ?
答: 带参宏 函数
---------------------------
处理时间 编译时 程序运行时
参数类型 没有参数类型问题 定义实参、形参类型
处理过程 不分配内存 分配内存
程序长度 变长 不变
运行速度 不占运行时间 调用和返回占用时间
7. 条件编译:
#ifdef 宏名称 // 或者(#ifndef 宏名称)
***
#else
***
#endif
举例如下:
#define ONE
int main()
{
#ifdef ONE // 如果定义了ONE宏,则运行下面语句,打印one,否则运行else,打印two
printf("one");
#else
printf("two");
#endif
retrun 0;
}
类似形式如下:
#define ONE
int main()
{
#ifndef ONE // 如果没定义ONE,打印one,否则打印two。
printf("one");
#else
printf("two");
#endif
retrun 0;
}
8. 条件编译:
#if 条件表达式 // 这样的条件编译范围变大,#ifdef 相当于 #if defined(宏名称) ,此条件表达式末尾没有符号
***
#else
***
#endif
多条件编译:
#if 条件表达式
***
#elif 条件表达式
***
***
#else
***
#endif
'\0' 在 ASCII 中对应数字 0 ;
2. 字面值是程序中表示字符串的一种写法,用双引号表示,不可以被修改。
多个相同内容的字面值在程序运行时都是同一个地址。
多个连续的字符串在编译时会被合并成一个。
char *p = "abc"; // p 表示字符串首地址,该值不能被修改
char *p1 = 'a'; // 错误,提示整数类型不可以赋值给指针,传递的是 a 对应的 ASCII 值;
// 如果是 char *p1 = "a"; 则正确;传递的是 a 在内存中的地址;
printf("%s\n", p);
*p = 'm'; // 错误,字符串字面值不可以修改
printf("%p\n", "abc"); // 此处打印出来的地址和上面 p 打印出来的地址一样
printf("%s\n", "abc""xyz"); // 输出为一个字符串:abcxyz;
字符数组也可以表示字符串,它存储在栈中。可以被修改,可以使用多种方式初始化。
char str[] = "abc";
char str1[3] = "abc"; // 这个写法不对,因为 '\0' 没处放;
char str2[] = {'a', 'b', 'c'}; // 错误,没有 0 ,不可以当数组用
char str3[] = {'a', 'b', 'c', 0}; // 正确
printf("%s\n", str); // 输出为:abc
printf("%d\n", sizeof(str) / sizeof(str[0]));
// 计算出字符串数组大小,输出为:4。因为后面还有一个 '\0',在编译的时候计算机自动加上。
str[0] = 'm'; // 数组表示的字符串可以改动,和上面的字面值不一样
str[1] = 0;
printf("%s\n", str); // 输出为:m,因为第二个为 0,所以计算机自动停止
3. 字符串数组常用操作:(denglu.c)
首先,字符串数组要包含头文件: #include <string.h>
fgets 函数用来从键盘读取字符串,不会出现字符数组溢出问题;
strlen 计算字符串长度(实际长度);
strcat 合并两个字符串,第二个参数的首字符必须为 char 类型;
此函数容易导致合并后长度过长,溢出。
strncat 合并字符串,且避免溢出。
strcpy 赋值字符串,同样容易溢出。
strncpy 赋值字符串,且避免溢出。
strcmp 通过 ASCII 比较字符串大小。前者大,返回 1;后者大返回 -1;一样大返回 0。
strncmp 比较两字符串中前 n 个字符大小。
#include <string.h>
char buf[10] = {0};
fgets(buf, 10, stdin); // 若输入字符超过9个,只提取前面9个,最后留一个0位置。若少于9个,那么会把\n读进去。
printf("%d\n", strlen(buf)); // 计算字符串有效字符长度(不包括 “\0”)
char str[10] = "abc";
strcat(str, "x0yz"); // str = str + "x0yz";
strcpy(str, "wqq"); // str = "wqq";
strcmp("abc","acd"); // 返回 -1
char arr[10];
printf ("%d\n", sizeof (arr)); // 10
printf ("%d\n", strlen (arr)); // 9
4. main函数参数(了解即可,很少使用)
int main(int argc, char *argv[])
5. 预处理命令 #define 专门给数字取名字,如给 3.14 取名字:
#define PI 3.14f // 后面不可以加分号,也不可以加赋值等号。
用#define取的名字叫宏,如此处 PI 即为宏;名字之间不能有空格,即不能写为:P I;
另外一种宏定义方式:
在gcc(终端)里面输入:gcc -D PI=3014 code.c
6. 宏不仅可以定义数字,还可以定义公式等,即带参数宏:
#define PI 3.14f
#define CIRCLE(r) 2 * PI * (r) // 一般给参数加个(),保证参数先运算
#define SQRE (60 * 60) // 若是个计算式,记得加个括号
#define SQUARE(n) ((n) * (n))
#define STR(n) #n // 把参数字符串化,相当于 “n”,如:STR(6+3),输出结果为:6+3
#define PTR(n) p_##n // 重命名标志符,如:PTR(value),输出结果为:p_value
宏的参数既是输入参数,又是输出参数;且参数要用()。
不要使用自增或自减作为参数传递给宏。
编译器预定义的一些宏:
printf("%d\n", __LINE__); // 显示当前行号
printf("%s\n", __FILE__); // 当前文件名
printf("%s\n", __DATE__); // 当前编译日期
printf("%s\n", __TIME__); // 当前编译时间
printf("%s\n", __STDC__ ? "符合" : "不符合"); // 查看编译器是否符合C标准,如果符合打印“符合”,反之“不符合”;
问:论述含参数的宏与函数的优缺点 ?
答: 带参宏 函数
---------------------------
处理时间 编译时 程序运行时
参数类型 没有参数类型问题 定义实参、形参类型
处理过程 不分配内存 分配内存
程序长度 变长 不变
运行速度 不占运行时间 调用和返回占用时间
7. 条件编译:
#ifdef 宏名称 // 或者(#ifndef 宏名称)
***
#else
***
#endif
举例如下:
#define ONE
int main()
{
#ifdef ONE // 如果定义了ONE宏,则运行下面语句,打印one,否则运行else,打印two
printf("one");
#else
printf("two");
#endif
retrun 0;
}
类似形式如下:
#define ONE
int main()
{
#ifndef ONE // 如果没定义ONE,打印one,否则打印two。
printf("one");
#else
printf("two");
#endif
retrun 0;
}
8. 条件编译:
#if 条件表达式 // 这样的条件编译范围变大,#ifdef 相当于 #if defined(宏名称) ,此条件表达式末尾没有符号
***
#else
***
#endif
多条件编译:
#if 条件表达式
***
#elif 条件表达式
***
***
#else
***
#endif