2019年7月15日(C语言)
Posted zjlbk
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了2019年7月15日(C语言)相关的知识,希望对你有一定的参考价值。
一、字符串函数 -> 追加字符串 strcat() -> man 3 strcat
使用格式:
#include <string.h>
char *strcat(char *dest, const char *src);
char *strncat(char *dest, const char *src, size_t n);
src:需要追加到另一个字符串默认的字符串的地址。 -> 拷贝之后会覆盖dest的\\0。
dest:被追加的字符串的空间,空间必须足够大。
返回值:指向dest区域的首元素的地址。
验证: overwriting the terminating null byte (‘\\0‘) at the
end of dest, and then adds a terminating null byte.
src覆盖dest的\\0,并且会在拼接之后在字符串的默认添加一个\\0。
#include <stdio.h>
#include <string.h>
int main()
/* 可以 */
char A[20] = "hello";
strcat(A,"world");
/* 可以 */
char A[20] = "hello";
char *p = A;
strcat(p,"world");
/* 不可以 */
char *p = "hello";
strcat(p,"world");
printf("p = %s\\n",p); //helloworld
return 0;
总结:学习过4个字符串函数的使用场景
1. strlen() -> 确定某些数据的字节数 -> 文件IO/系统编程/网络编程 write()/send()
2. strcmp() -> 检索特征数据 -> 链表/网络编程 -> 对比特征值/协议是否一致
3. strcpy() -> 用于初始化字符数组
char A[10]="helloworld"; 对
char A[10];
A = "helloworld"; 不对
char A[10];
strcpy(A,"hello");
4. strcat -> 拼接字符串,仅限追加功能 -> 后期使用sprintf() 替代 strcat()
二、数组清零方式
1、定义数组的同时初始化0
例子: char str[50] = 0;
特点:只能初始化(清零)一次。
2、清空某段内存空间。 -> bzero() -> man 3 bzero
bzero - write zero-valued bytes -> 函数的功能
#include <strings.h> -> 头文件
void bzero(void *s, size_t n); -> 函数原型
s:需要清零的内存的地址
n:需要清零的字节数
返回值:无
特点:多次调用,多次清零。
---------------------------------------------------
#include <stdio.h>
#include <strings.h>
int main()
char A[10];
int i;
for(i=0;i<10;i++)
printf("A[%d] = %c\\n",i,A[i]);
bzero(A,sizeof(A));
for(i=0;i<10;i++)
printf("A[%d] = %c\\n",i,A[i]);
return 0;
--------------------------------------------
三、堆空间
1、堆空间的特点:主动申请,主动释放。
2、如何申请堆空间? -> malloc() -> man 3 malloc
#include <stdlib.h>
void *malloc(size_t size);
size:需要申请的字节数
The memory is not initialized. -> 内存没有被初始化过。
返回值:
成功: 指向堆空间的起始地址
失败: NULL
例子:
void *pa = malloc(4) -> 在堆空间申请4个字节,然后在栈空间申请一个指针变量pa指向堆空间。
int *p = pa; -> 把堆空间的pa赋值赋值给指针变量p
int pa; -> 在栈空间申请4个字节
int *p = &pa; -> 把栈空间pa变量的地址赋值给指针变量p
例题1: 申请了堆空间,堆空间的值会是什么?
#include <stdio.h>
#include <stdlib.h>
int main()
int A[3];
printf("A = %p\\n",A);
int *p = malloc(sizeof(int)*3); // int A[3];
printf("p = %p\\n",p);
printf("p[0] = %d\\n",p[0]); //0
printf("p[1] = %d\\n",p[1]); //0
printf("p[2] = %d\\n",p[2]); //0
free(p);
return 0;
3、如何释放空间? -> free() -> man 3 free
#include <stdlib.h>
void free(void *ptr);
ptr:需要释放堆空间的地址
返回值:无
一般做法:free掉指向堆区指针之后,会让指针指向NULL。
free(p);
p = NULL;
四、堆空间与栈空间在内存中容易出错的点。
下列代码是否正确?如果正确,请指出代码的含义,如果出错,则说明错误的原因。
1、栈区
=============================
char A[10] = "hello"; //把常量区的hello拷贝到变量A数组中
strcpy(A,"world"); //把常量区的world拷贝到变量A数组中
=============================
char *p = "hello"; //把常量区的hello的首元素的地址赋值给变量p
strcpy(p,"hello"); //段错误,因为p只能存放地址,不能存放字符串。
=============================
char A[10];
strcpy(A,"hello"); //可以
==============================
char *p;
strcpy(p,"hello"); //段错误,因为p只能存放地址,不能存放字符串。
=============================
char A[10]; //在栈区中申请10个字节,使用变量A间接访问这个数组
char *p = A; //在栈区申请4个字节,使用变量p间接访问这片内存,将数组的A的首元素的地址赋值给p
strcpy(p,"hello"); //将常量区的hello拷贝到p指向的栈区空间
============================
2、堆区
============================
char *p = malloc(sizeof(char)*10); //在堆区中申请10个字节,使用p间接访问这片内存空间。
p = "hello"; //给p赋值了常量区hello的地址,就是说现在p不是指向堆,而是指向常量区。
============================
char *p = malloc(sizeof(char)*10); //在堆区中申请10个字节,使用p间接访问这片内存空间。
strcpy(p,"hello"); //可以,把常量区的hello拷贝到堆区!
五、结构体
1、什么是结构体?
将多个不同类型的变量加入到一个集合中,这个集合就称之为结构体。
由于结构体中存在不同类型的变量,所以每一个变量都需要用户自己定义。
可以在结构体中定义:
基本数据类型: char short int long float double
非基本数据类型:int A[3] int*p char B[2][3] char *px char pa[5] int(*pfun)(int)
不可以在结构体中定义:
函数
2、 如何定义结构体?
关键词: struct
模型:
struct 结构体名字
/* 结构体的组成变量 */
例子:
int a;
char b;
int A[3];
int *p;
; -> 后面记住有一个分号,不然报错。
其实结构体就是一种新的数据类型。
例子:
struct data
int a;
char b;
;
在这里只是先说: "struct data" 这种新类型由 int a;char b;组成。
3、如何定义结构体的变量?
struct mydata
char name[20];
int age;
;
struct mydata -> 新的数据类型
定义变量公式: 数据类型 + 变量名;
定义整型变量 int a;
定义结构体变量 struct mydata A;
4、结构体的指针如何定义?
定义结构体变量: struct mydata A;
1)先写一个 *
2)在*后面写一个变量的名字 *p
3)确认指针指向的内容是什么。 struct mydata A;
4)将指向的内容的变量名去掉 struct mydata
5)将第4步的结果写在第2步的前面 struct mydata *p;
结果:struct mydata *p;
变量名: p
数据类型: struct mydata *
5、结构体的变量与指针如何访问成员?
1)设计结构体模型
struct mydata
char name[20];
int age;
;
2)定义一个结构体的变量
struct mydata gec;
3)结构体变量使用"."来对成员进行访问。
公式: 结构体变量名.成员名字
例子:
strcpy(gec.name,"ggy");
gec.age = 10;
4)结构体指针使用"->"访问成员。
公式: 结构体指针变量名->成员名字
例子:
strcpy(p->name,"ggy");
p->age = 10;
六、结构体初始化值
1)先定义一个变量,后使用./->对成员进行赋值
struct mydata gec;
strcpy(gec.name,"ggy");
gec.age = 10;
2)使用初始化列表
struct mydata gec = "helloworld",20; -> 等价于将"helloworld"拷贝到name成员的空间中,20就赋值给age;
struct mydata gec = "helloworld"; -> 后面没有赋值的成员 变量为0 指针为NULL
3)使用另外一个结构体给某个结构体整体赋值
struct mydata gec;
struct mydata A = "hello",20;
gec = A;
练习: 做一个通讯录,里面存放三个同学信息,每一个同学包含: 姓名,年龄,电话号码 -> 结构体数组。
1. 先分别对三个同学注册。
2. 输出三个同学的全部信息。
#include <stdio.h>
struct mydata
char name[20];
int age;
char tel[20];
;
int main()
struct mydata A[3];
int i; //0~2
for(i=0;i<3;i++)
printf("pls input %d name",i+1);
scanf("%s",A[i].name);
printf("pls input %d age",i+1);
scanf("%d",&A[i].age);
printf("pls input %d tel",i+1);
scanf("%s",A[i].tel);
printf("====================================================\\n");
for(i=0;i<3;i++)
printf("%s %d %s\\n",A[i].name,A[i].age,A[i].tel);
return 0;
七. 计算结构体类型在内存中占用的字节数。
基本数据类型:char short int long float double -> 占用字节数固定。
例子: int a -> 占用4个字节
自定义结构体数据类型占用多少个?
struct mydata
char name[20];
int age;
char tel[20];
;
例子1:
struct mydata
char name[20];
int age;
;
sizeof(struct mydata) = ? //24
例子2:
struct mydata
int age;
char name[20];
;
sizeof(struct mydata) = ? //24
例子3:
struct mydata
int age;
char name;
;
sizeof(struct mydata) = ? //8
例子4:
struct mydata
int age;
char name;
short a;
;
sizeof(struct mydata) = ? //8
例子5:
struct mydata
char a;
char b;
short c;
;
sizeof(struct mydata) = ? //4
例子6:
struct mydata
char a;
short b;
char c;
;
sizeof(struct mydata) = ? //6
例子7:
struct mydata
char a;
short b;
char c;
int d;
int e;
;
sizeof(struct mydata) = ? //16
========================================================
struct mydata
char a;
int (*px)[3];
char A[10];
int b;
char **p;
short c;
char a;
short f;
int e;
char B[18];
; //60
========================================================
struct mydata
short a;
int (*px)(int,int);
char b;
char c;
int d;
char A[13];
short e;
int **p;
int f;
char *B[3];
; //52
计算结构体占用空间大小的方法:
1)从上往下计算,而不是根据类型的大小来计算。
2)看看当前结构体中最大的成员占用是2/4 -> 2的话结果就是2的倍数 4的话结果就是4的倍数。
3)如果某个结构体成员计算完,但是当前没有对齐,那么剩余的字节大小就应该与下一个成员大小进行比较
1. 下一个成员的大小大于当前行剩余的字节大小
结果: 剩余的字节补0,下一个成员开辟新的一行空间。
2. 下一个成员的大小小于/等于当前行剩余的字节大小
结果:将下一个成员塞进剩余的字节中
4)全部结构体成员处理完后,看看2的倍数/4的倍数来进行补0。
八、联合体
1、为什么会有联合体?
为了解决结构体在内存中占用比较大情况。
例子:
struct mydata
char name[20];
int age;
char tel[20];
;
sizeof(struct mydata) = 44; -> 占用非常多空间 -> 如果定义为联合体,则大大节省。
2、联合体定义方式与结构体一致,只需要修改关键词即可。
struct -> union
例子:
union mydata
char name[20];
int age;
char tel[20];
;
sizeof(union mydata) = 20
但是使用的时候,只能同时使用一个成员。
计算联合体的空间大小:
1)看看联合体哪个成员是占用空间最大的。
2)看看当前结构体中最大的成员占用是2/4 -> 2的话结果就是2的倍数 4的话结果就是4的倍数。
3)如果该成员占用字节数是2/4的倍数,那么联合体的大小就是该变量占用的字节数。
4)如果该成员占用字节数不是2/4的倍数,那么看情况来补0。
3、由于联合体只能同时使用一个成员,不能整体赋值。
例子:
union data
char name[10];
int age;
;
union data A = "ggy",10;
编译警告; warning: excess elements in union initializer
==========================================================
#include <stdio.h>
#include <string.h>
#include <strings.h>
union data
char name[10];
int age;
;
int main()
union data A;
strcpy(A.name,"ggy");
printf("A.name = %s\\n",A.name);
bzero(A.name,sizeof(A.name));
A.age = 10;
printf("A.age = %d\\n",A.age);
return 0;
=====================================================
4、在联合体中,所有成员的起始地址都是一致的。
#include <stdio.h>
#include <string.h>
#include <strings.h>
union data
char name[10];
int age;
;
int main()
union data A;
printf("A.name:%p\\n",A.name);
printf("A.age:%p\\n",&A.age);
return 0;
执行:
A.name:0xbfb3b220
A.age:0xbfb3b220
5、联合体也是可以作为函数的参数
#include <stdio.h>
#include <string.h>
#include <strings.h>
union data
char name[10];
int age;
;
void fun(union data B) //B = A
printf("B.name = %s\\n",B.name);
return;
int main()
union data A;
strcpy(A.name,"ggy");
fun(A);
return;
九. 枚举类型
1、什么是枚举类型?
枚举类型其实就是int类型常量,意义就是给常量一个身份。
例子: ok -> 1 warning -> 0 error -> -1
2、枚举类型一般作用地方?
1)可以作用于switch语句。
2)在函数返回值。 return 枚举类型数据类型
void fun()
if(xxxx)
return warning; -> 别人看起来就知道返回值是什么情况。
if(yyyy)
return ok;
if(zzzz)
return error;
3、如何定义枚举类型?
关键词: enum
模型:
enum mydata
ok, //如果没有赋值,第一个成员默认从0开始! //0
warning, //后面没有赋值的成员默认在前面的基础+1 //1
error, //2
;
enum mydata
ok = 1,
warning = 0,
error = -1,
;
enum mydata
ok = 10,
warning = 20,
error, //21
;
以上是关于2019年7月15日(C语言)的主要内容,如果未能解决你的问题,请参考以下文章
这段C语言程序为啥运行时显示Debug error和Runtime error?怎么改?(问题截止到2019年3月17日17时00分)