C语言基础知识备忘录

目录

一、基础语法

1.标识符

2.关键字

3.分号

4.注释

5.空格

6.main(一般认为主程序)

二、输入输出

1. scanf()输入

2. printf()输出

3. getchar()

4. putchar()

5. gets() & puts() 函数

三、 运算符

1. 运算符优先级

2. 惰性运算

3.位与、位或、异或

4.位移

5.强制转换

6.逗号表达式

7.其他

四、常用函数集合

1.sizeof

2. strlen

3. strstr

4. strtok

5. strcat和strncat

6. strcpy和strncpy

7. strcmp和strncmp(返回值只有正0负)

8. strchr和strrchr

9.malloc&calloc&realloc


一、基础语法

1.标识符

C 标识符是用来标识变量、函数,或任何其他用户自定义项目的名称。一个标识符以字母 A-Z 或 a-z 或下划线 _ 开始,后跟零个或多个字母、下划线和数字(0-9);C 语言是区分大小写的编程语言。

2.关键字

下表列出了 C 中的保留字。这些保留字不能作为常量名、变量名或其他标识符名称。

基本数据类型(5个)

  • void:声明函数无返回值或无参数

  • char:字符型类型数据

  • int:整型数据

  • float:单精度浮点型数据

  • double:双精度浮点型数据

修饰关键字(4个)

  • short:修饰int,短整型数据,可省略被修饰的int。

  • long:修饰int,长整形数据,可省略被修饰的int。

  • signed:修饰整型数据,有符号数据类型

  • unsigned:修饰整型数据,无符号数据类型

复杂类型关键字(5个)

  • struct:结构体声明

  • union:共用体声明

  • enum:枚举声明

  • typedef:声明类型别名

  • sizeof:得到特定类型或特定类型变量的大小

存储级别关键字(6个)//记住前三个(static,const,volatile)

  • volatile:与const合称“cv特性”,指定变量的值有可能会被系统或其他进程/线程改变,强制编译器每次从内存中取得该变量的值

  • static:指定为静态变量,分配在静态变量区,修饰函数时,指定函数作用域为文件内部

  • const:与volatile合称“cv特性”,指定变量不可被当前线程/进程改变(但有可能被系统或其他线程/进程改变)

  • extern:指定对应变量为外部变量,即在另外的目标文件中定义,可以认为是约定由另外文件声明的对象的一个“引用“

  • register:指定为寄存器变量,建议编译器将变量存储到寄存器中使用,也可以修饰函数形参,建议编译器通过寄存器而不是堆栈传递参数
  • auto:指定为自动变量,由编译器自动分配及释放。通常在栈上分配

跳转结构(4个)

  • return:用在函数体中,返回特定值(或者是void值,即不返回值)

  • continue:结束当前循环,开始下一轮循环

  • break:跳出当前循环或switch结构

  • goto:无条件跳转语句

分支结构(5个)

  • if:条件语句

  • else:条件语句否定分支(与if连用)

  • switch:开关语句(多重分支语句)

  • case:开关语句(switch)中的分支标记

  • default:开关语句中的“其他”分治,可选。

循环结构(3个)//当循环条件表达式为真则继续循环,为假则跳出循环。

  • for:for循环结构,for(1;2;3)4;的执行顺序为1->2->4->3->2...循环,其中2为循环条件

  • do:do循环结构,do 1 while(2);的执行顺序是1->2->1...循环,2为循环条件

  • while:while循环结构,while(1) 2;的执行顺序是1->2->1...循环,1为循环条件

3.分号

在 C 程序中,分号是语句结束符。也就是说,每个语句必须以分号结束。它表明一个逻辑实体的结束;语句{}后不用写;初始化赋值语句后需要;。

4.注释

// 开始的单行注释,这种注释可以单独占一行。

/* */ 这种格式的注释可以单行或多行。

不能在注释内嵌套注释,注释也不能出现在字符串或字符值中。

5.空格

只包含空格的行,被称为空白行,可能带有注释,C 编译器会完全忽略它。

在 C 中,空格用于描述空白符、制表符、换行符和注释。空格分隔语句的各个部分,让编译器能识别语句中的某个元素(比如 int)在哪里结束,下一个元素在哪里开始。

6.main(一般认为主程序)

程序执行将从main函数开始,也将从main函数结束,对于他人程序的理解需要从main函数开始阅读。

二、输入输出

键盘->内存缓冲区->程序输入(stdin)是C语言中标准输入流,一般用于获取键盘输入到缓冲区里的东西。

1. scanf()输入

1.1从键盘取值是以格式控制符为准,从buf(缓冲区)取符合的字符数据。不匹配停止取数据。在读取字符串时,只要遇到空格,就会停止读取。

scanf("%s   %d",a,&b);//a字符串,b字符

1.2 ret可以记录scanf读取次数

int data,dete;
int ret = scanf("%d%d",&data,&dete);

1.3 连续输入时,scanf俩格式控制符之间有什么,键入时就加上什么

int a,b,c,d;            //会忽略任何空白字符(空格、回车、制表符等)
scanf("%d %d",&a,&b);   //数与数间加空格
scanf("%d,%d",&c,&d);   //数与数间加逗号
scanf("%d%d",&c,&d);    //数与数间加空格

1.3.1 scanf()一个格式控制符我们却输入了两次,这是因为我们在scanf()里加入了’ \n ‘。

scanf("%d\n%d",&a,&b);

总结:scanf可以根据不同格式符,在缓冲区拿取不同数据,遇到空格结束,回车确认,对这个回车确认符并不进行处理,回车符会留在输入缓存区中。因此,在下一个读“字符”操作函数(getchar, scanf("%c"), gets()等)运行时,会读到这个字符(%d会忽略任何空白字符(空格、回车、制表符等)忽略是从缓冲区里删除,但并不保存)(%s一直找到\0结束,否则有可能出现段错误或乱码)。

2. printf()输出

int printf(const char *format, ...) 函数把输出写入到标准输出流 stdout ,并根据提供的格式产生输出。

  1. %s:将字符串输出。
  2. %c:将字符输出。
  3. %d:将十进制整数以带符号方式输出。
  4. %ld:将长整型以带符号方式输出。
  5. %f:将浮点数以小数形式输出。
  6. %e:将浮点数以指数形式输出。
  7. %x:将十六进制整数以无符号方式输出,并且以小写字母表示a-f。
  8. %X:将十六进制整数以无符号方式输出,并且以大写字母表示A-F。
  9. %u:将十进制整数以无符号方式输出。
  10. %p:输出指针地址值。
  11. %o:将八进制形式输出一个整数。

输出不仅要注意格式控制符所影响的内容输出,还要注意输入数据格式时对数据的影响。

3. getchar()

int getchar(void),所以它返回的是ASCII码,所以只要是ASCII码表里有的字符它都能读取出来。在调用getchar()函数时,编译器会依次读取用户键入缓存区的一个字符(注意这里只读取一个字符,如果缓存区有多个字符,那么将会读取上一次被读取字符的下一个字符),如果缓存区没有用户键入的字符,那么编译器会等待用户键入并回车后再执行下一步 (注意键入后的回车键也算一个字符,输出时直接换行)。

4. putchar()

int putchar(int c) 函数把字符输出到屏幕上,并返回相同的字符。这个函数在同一个时间内只会输出一个单一的字符。可以在循环内使用这个方法

int c;
c = getchar( );
putchar( c );

5. gets() & puts() 函数

char *gets(char *s) 函数从 stdin 读取一行到 s 所指向的缓冲区,直到一个终止符或 EOF。

int puts(const char *s) 函数把字符串 s 和一个尾随的换行符写入到 stdout

三、 运算符

1. 运算符优先级

2. 惰性运算

逻辑与 :错&&?(右不执行)

逻辑或 :真||? (右不执行)

3.位与、位或、异或

位或运算 | :有1为1,全0为0

位与运算 & :有0为0,全1为1

异或运算 ^ :异则为1,同则为0

4.位移

数左移<<n : 数*2^n

数右移>>n : 数/(2^n)

5.强制转换

隐式转换:系统按照隐式规则自动进行的转换

强制转换:用户显式自定义进行的转换(不存在四舍五入)

隐式规则:从小类型向大类型转换,目的是保证不丢失表达式中数据的精度

6.逗号表达式

(表达式1,表达式2,表达式3表达式n)求值顺序:
先求表达式1,再求表达式2,再求表达式3,最后求表达式n整个逗号表达式的值为表达式n的值
逗号表达式的优先级最低,运算顺序是从左往右,整个表达式的值为表达式最右边的值

int a = 10, 11, 12, 13;   //a = 10
int b = (10, 11, 12, 13)  //b = 13根据优先级,该式为赋值表达式

注意:赋值表达式:f =(1,2)//括号优先级高,先处理括号里的逗号表达式,再赋值

逗号表达式:a<1,b>2      a=1,b=2      f=1.0,2.0

7.其他

无符号数加上有符号数

先将有符号数转为无符号数(负数的补码当做正数二进制),然后进行无符号数计算

unsigned int a = 6;                 //0000 0000 0000 0110正数原反补一致
int b = -20;                        //1000 0000 0001 0100-补->1111 1111 1110 1100
(a+b>b)?printf(">6"):printf("<6");  //1111 1111 1111 0010>6,三目运算符输出“>6”

除号/ :得数为整形

==和=不能在一个表达式里,编译出错。

前后缀运算符(++,--)不能用于常量和表达式,例如5++,--(a+b)。

取模运算符左右都为整数。

四、常用函数集合

1.sizeof

sizeof() 是一个运算符(单目)而不是函数,用于计算一个类型或变量所占用的内存字节数。可以用它来获取任何类型的数据的字节数,包括基本数据类型、数组、结构体、共用体等等。

指针大小取决于系统位数

int *p = NULL;
sizeof(p);//在32位系统,指针的大小占用4字节
sizeof(p);//在64位系统,指针的大小占用8字节

2. strlen

只能用来求字符串长度的函数,遇到‘\0’停止,且长度不包含‘\0’,头文件<string.h>。

注意:strlen() 函数只能用于计算以空字符 '\0' 结尾的字符串的长度,如果字符串中没有空字符 '\0' ,则 strlen() 函数的行为是未定义的。

sizeof和strlen的区别:

  • sizeof() 是一个运算符,而 strlen() 是一个函数。

  • sizeof() 计算的是变量或类型所占用的内存字节数(空间大小),而 strlen() 计算的是字符串中字符的个数。

  • sizeof() 可以用于任何类型的数据,而 strlen() 只能用于以空字符 '\0' 结尾的字符串。

  • sizeof() 计算字符串的长度,包含末尾的 '\0',strlen() 计算字符串的长度,不包含字符串末尾的 '\0'

char arr[20]= {"jhsgdjaggf"};
int a = sizeof(arr);//20
int b = strlen(arr);//10
printf("%d\n%d",a,b);

3. strstr

4. strtok

注意

  1. 该函数会将改变原始字符串 str,使其所包含的所有分隔符变成结束标记 ‘\0’ 。

  2. 由于该函数需要更改字符串 str,因此 str 指向的内存必须是可写的。

  3. 首次调用时 str 指向原始字符串,此后每次调用 str 用 NULL 代替。

char s[20] = "yueqian\ncom\ncn";
char *p = strtok(s, "\n"); // 首次调用时,s 指向需要分割的字符串
while(p != NULL)
{
    printf("%s\n", p);
    p = strtok(NULL, "."); // 此后每次调用,均使用 NULL 代替。
}

5. strcat和strncat

注意

  1. 这两个函数的功能,都是将 src 中的字符串,复制拼接到 dest 的末尾。

  2. strcat() 没有边界控制,因此可能会由于 src 的过长而导致内存溢出。

  3. strncat() 有边界控制,最多复制 n+1 个字符(其中最后一个是 ‘\0’ )到 dest 的末尾

char s1[10] = "abc";
strcat(s1, "xyz");
printf("%s\n", s1); // 输出 "abcxyz"
char s2[10] = "abc";
strcat(s3, "123456789"); // 此处操作内存溢出,可能会发生内存崩溃
char s[10] = "abc";
strncat(s, "123456789", sizeof(s)-strlen(s)-1);
printf("%s\n", s); // 输出 "abc123456",两个字符串被拼接到了一起,且不会溢出

6. strcpy和strncpy

注意

  1. 这两个函数的功能,都是将 src 中的字符串,复制到 dest 中。

  2. strcpy() 没有边界控制,因此可能会由于 src 的过长而导致内存溢出。

  3. strncpy() 有边界控制,最多复制 n+1 个字符(其中最后一个是 ‘\0’ )到 dest 中 。

char s1[5] = "abc";
strcpy(s1, "xyz);
printf("%s\n", s1); // 输出 "xyz",原有的"abc"被覆盖
char s2[5] = "abc";
strcpy(s2, "123456789"); // 此处操作内存溢出,可能会发生内存崩溃
char s[5] = "abc";
strncpy(s, "123456789", sizeof(s)-1);
printf("%s\n", s); // 输出 "1234",有边界保护,不会溢出

7. strcmp和strncmp(返回值只有正0负)

注意: 比较字符串大小,实际上比较的是字符的 ASCII码值的大小。 从左到右逐个比较两个字符串的每一个字符,当能“决出胜负”时立刻停止比较。

printf("%d\n", strcmp("abc", "abc")); // 输出0,两个字符串相等
printf("%d\n", strcmp("abc", "aBc")); // 输出正数,"abc" 大于 "aBc"
printf("%d\n", strcmp("999", "aaa")); // 输出负数,"999" 小于 "aaa"

8. strchr和strrchr

注意

  1. 这两个函数的功能,都是在指定的字符串 s 中,试图找到字符 c。

  2. strchr() 从左往右找,strrchr() 从右往左找。

  3. 字符串结束标记 ‘\0’ 被认为是字符串的一部分。

char *p;
p = strchr("www.qq.com", '.'); // 从左到右找到第一个出现的字符'.'
printf("%s\n", p); // 输出 ".qq.com"
p = strrchr("www.qq.com", '.');// 从右到左找到第一个出现的字符'.'
printf("%s\n", p); // 输出 ".com"

9.malloc&calloc&realloc

malloc 和 calloc 之间的不同点是,malloc 不会设置内存为零,而 calloc 会设置分配的内存为零。realloc尝试重新调整之前调用 malloc 或 calloc 所分配的 ptr 所指向的内存块的大小。

#include<stdlib.h>//头文件
int *p = malloc(3*sizeof(int));//申请3块大小为int的堆空间内存
bzero(p,3*sizeof(int));//堆内存清零
free(p);//释放空间锚点
#include<stdlib.h>//头文件
int *k = calloc(3,sizeof(int));//申请3块连续的大小为int的堆空间内存
//空间自动清零
free(k);//释放空间锚点
//原址扩容空间充足会在原地址上扩容;不足则另起炉灶,会改变空间地址
#include <stdio.h>
#include <stdlib.h>//头文件
#include <string.h>
int main(int argc, char const *argv[])
{
	// 申请堆空间
	char *p = calloc(1,sizeof(char));
	if(p == NULL)//判断功能是否正常
	{
		printf("calloc failed:");
		return -1;
	} 
    char buf[] = "afjoiajfajflajlfjalflafjslfjsljfls";
	// 扩容,否则会溢出,扩容后会复制p到ptr
	char *ptr = realloc(p,100);
	strcpy(ptr,buf);
	printf("%s\n",ptr);
	return 0;
}

释放内存的含义: 释放内存意味着将内存的使用权归还给系统。 释放内存并不会改变指针的指向。 释放内存并不会对内存做任何修改,更不会将内存清零。

free()只能释放堆内存,并且只能释放整块堆内存,不能释放别的区段的内存或者释放一部分堆内存。

未完待续,发现错误请留言指正(万分感谢)。

  • 16
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
以下是一个用C语言编写的简单手机备忘录程序的示例代码: ```c #include <stdio.h> #include <stdlib.h> #include <string.h> #define MAX_MEMOS 100 #define MAX_MEMO_LENGTH 100 // 定义备忘录结构体 typedef struct memo { char *content; } Memo; // 初始化备忘录 void initMemo(Memo memos[]) { for (int i = 0; i < MAX_MEMOS; i++) { memos[i].content = NULL; } } // 添加备忘录 void addMemo(Memo memos[]) { char buffer[MAX_MEMO_LENGTH]; int i; for (i = 0; i < MAX_MEMOS; i++) { if (memos[i].content == NULL) { printf("请输入备忘录内容(最多%d个字符):", MAX_MEMO_LENGTH - 1); fgets(buffer, MAX_MEMO_LENGTH, stdin); memos[i].content = (char *) malloc(strlen(buffer) + 1); strncpy(memos[i].content, buffer, strlen(buffer)); break; } } if (i == MAX_MEMOS) { printf("备忘录已满,无法添加新备忘录。\n"); } } // 显示备忘录 void showMemos(Memo memos[]) { printf("备忘录内容如下:\n"); for (int i = 0; i < MAX_MEMOS; i++) { if (memos[i].content != NULL) { printf("%d. %s", i + 1, memos[i].content); } } } // 删除备忘录 void deleteMemo(Memo memos[]) { int index; printf("请输入要删除的备忘录编号:"); scanf("%d", &index); getchar(); if (index < 1 || index > MAX_MEMOS) { printf("无效的备忘录编号。\n"); return; } if (memos[index - 1].content == NULL) { printf("该备忘录不存在。\n"); return; } free(memos[index - 1].content); memos[index - 1].content = NULL; printf("备忘录已删除。\n"); } int main() { Memo memos[MAX_MEMOS]; int choice; initMemo(memos); do { printf("请选择需要执行的操作:\n"); printf("1. 添加备忘录\n"); printf("2. 显示备忘录\n"); printf("3. 删除备忘录\n"); printf("4. 退出\n"); printf("你的选择是:"); scanf("%d", &choice); getchar(); switch (choice) { case 1: addMemo(memos); break; case 2: showMemos(memos); break; case 3: deleteMemo(memos); break; case 4: printf("程序已退出。\n"); break; default: printf("无效的选择。\n"); break; } } while (choice != 4); return 0; } ``` 这个程序可以在控制台上添加、显示和删除备忘录。使用者可以通过输入相应的数字选择需要执行的操作。当备忘录数量达到上限时,将无法再添加新的备忘录

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值