2024-2025-1 20241301 《计算机基础与程序设计》第十周学习总结
|这个作业属于哪个课程|2024-2025-1-计算机基础与程序设计|
|这个作业要求在哪里|2024-2025-1计算机基础与程序设计第一周作业|
|这个作业的目标|<复习知识,巩固基础>|
|作业正文|https://www.cnblogs.com/HonJo/p/18580240|
一、教材学习内容总结
(一)字符串
C语言中的字符串是一种特殊的字符数组,它以空字符(null character,即'\0'
)作为结束标志。在C语言中,字符串实际上是字符数组的首地址,因此可以通过字符数组来操作字符串。以下是C语言中字符串的一些基本概念和操作:
-
字符串的表示:
字符串可以用字符数组或者指向字符的指针来表示。例如:char str[] = "Hello, World!"; char *p = "Hello, World!";
在这里,
str
是一个字符数组,而p
是一个指向字符的指针。 -
字符串的结束符:
字符串以空字符'\0'
作为结束标志。这意味着在字符串的最后一个字符之后,必须有一个空字符来表示字符串的结束。 -
字符串的长度:
字符串的长度是指字符串中字符的数量,不包括结束符'\0'
。 -
字符串的输入输出:
使用printf
和scanf
函数可以对字符串进行输入输出操作。例如:printf("%s\n", str); // 输出字符串 scanf("%s", str); // 输入字符串
注意,
scanf
使用%s
格式符时,遇到空格、制表符或换行符会停止读取,因此不适合读取含有空格的字符串。 -
字符串处理函数:
C语言标准库提供了许多处理字符串的函数,如strcpy
(复制字符串)、strcat
(连接字符串)、strlen
(计算字符串长度)、strcmp
(比较字符串)、strchr
(查找字符)等。 -
字符串字面量:
在C语言中,字符串字面量(如"Hello, World!"
)是只读的,它们存储在程序的只读数据段中,不能被修改。 -
字符串的内存分配:
在堆上动态分配内存来存储字符串可以使用malloc
或calloc
函数,例如:char *str = malloc(100 * sizeof(char)); // 分配100个字符的空间
使用完毕后,需要用
free
函数释放内存。 -
字符串的安全性:
在处理字符串时,需要注意缓冲区溢出的问题。例如,使用strcpy
时可能会覆盖内存,导致安全问题。因此,推荐使用strncpy
等更安全的函数。 -
字符串的编码:
在C语言中,默认情况下字符串是以ASCII编码存储的。对于非ASCII字符,可以使用多字节字符集,如UTF-8。 -
字符串的遍历:
可以通过循环遍历字符串中的每个字符,直到遇到空字符'\0'
为止。
字符串是C语言中非常基础且重要的概念,掌握字符串的处理对于编程来说至关重要。
(二)字符串处理函数
在C语言中,字符串处理函数是标准库中的一部分,主要用于操作以null字符('\0'
)结尾的字符数组。以下是一些常用的字符串处理函数:
-
strcpy
(字符串复制):- 原型:
char *strcpy(char *dest, const char *src);
- 功能:将
src
指向的字符串复制到dest
指向的内存空间中。 - 注意:
dest
必须有足够的空间来存储复制的字符串。
- 原型:
-
strncpy
(安全字符串复制):- 原型:
char *strncpy(char *dest, const char *src, size_t n);
- 功能:将
src
指向的字符串的前n
个字符复制到dest
指向的内存空间中。 - 注意:如果
src
的长度小于n
,则dest
将被填充null字符直到长度为n
。
- 原型:
-
strcat
(字符串连接):- 原型:
char *strcat(char *dest, const char *src);
- 功能:将
src
指向的字符串连接到dest
指向的字符串的末尾。 - 注意:
dest
必须有足够的空间来存储连接后的字符串。
- 原型:
-
strncat
(安全字符串连接):- 原型:
char *strncat(char *dest, const char *src, size_t n);
- 功能:将
src
指向的字符串的前n
个字符连接到dest
指向的字符串的末尾。
- 原型:
-
strlen
(计算字符串长度):- 原型:
size_t strlen(const char *str);
- 功能:计算
str
指向的字符串的长度(不包括结束的null字符)。
- 原型:
-
strcmp
(比较字符串):- 原型:
int strcmp(const char *str1, const char *str2);
- 功能:比较两个字符串
str1
和str2
。 - 返回值:如果
str1
小于str2
返回负数,相等返回0,大于返回正数。
- 原型:
-
strncmp
(比较字符串前n个字符):- 原型:
int strncmp(const char *str1, const char *str2, size_t n);
- 功能:比较两个字符串
str1
和str2
的前n
个字符。
- 原型:
-
strchr
(查找字符首次出现):- 原型:
char *strchr(const char *str, int c);
- 功能:在
str
指向的字符串中查找字符c
第一次出现的位置。 - 返回值:如果找到,返回指向该字符的指针;如果没有找到,返回
NULL
。
- 原型:
-
strrchr
(查找字符最后一次出现):- 原型:
char *strrchr(const char *str, int c);
- 功能:在
str
指向的字符串中查找字符c
最后一次出现的位置。
- 原型:
-
strstr
(查找子字符串首次出现):- 原型:
char *strstr(const char *haystack, const char *needle);
- 功能:在
haystack
指向的字符串中查找needle
指向的子字符串第一次出现的位置。
- 原型:
-
strtok
(字符串分割):- 原型:
char *strtok(char *str, const char *delim);
- 功能:使用
delim
指定的分隔符分割str
指向的字符串。 - 注意:这个函数会修改原始字符串,并且是线程不安全的。
- 原型:
-
strtok_r
(线程安全的字符串分割):- 原型:
char *strtok_r(char *str, const char *delim, char **save_ptr);
- 功能:线程安全的版本,使用
save_ptr
参数来保存状态。
- 原型:
这些函数是处理C语言字符串的基础工具,正确使用它们可以有效地进行字符串操作。在使用这些函数时,需要注意内存管理和函数的返回值,以避免常见的编程错误,如缓冲区溢出和空指针引用。
(三)结构体
在C语言中,结构体(struct
)是一种复合数据类型,它允许将多个不同类型的数据项组合成一个单一的数据结构。结构体可以用来表示复杂的数据对象,如学生信息、书籍信息等。以下是结构体的一些基本概念和用法:
-
定义结构体:
使用struct
关键字来定义一个新的结构体类型。例如,定义一个表示学生信息的结构体:struct Student { char name[50]; int age; float score; };
-
声明结构体变量:
定义结构体类型后,可以声明该类型的变量:struct Student student1;
-
访问结构体成员:
使用点(.
)操作符来访问结构体变量的成员:student1.name = "John Doe"; student1.age = 20; student1.score = 95.5;
-
指针和结构体:
如果有一个指向结构体的指针,可以使用箭头(->
)操作符来访问成员:struct Student *p = &student1; p->name = "John Doe"; p->age = 20; p->score = 95.5;
-
初始化结构体:
可以在声明结构体变量时进行初始化:struct Student student2 = {"Jane Doe", 19, 92.0};
或者使用指定初始化器(C99标准):
struct Student student3 = {.name = "Alice", .age = 22, .score = 88.5};
-
结构体数组:
可以创建结构体数组来存储多个结构体实例:struct Student students[3] = { {"John Doe", 20, 95.5}, {"Jane Doe", 19, 92.0}, {"Alice", 22, 88.5} };
-
结构体作为函数参数:
可以将结构体作为参数传递给函数,通常使用指针来避免复制整个结构体:void printStudent(struct Student *s) { printf("Name: %s, Age: %d, Score: %.2f\n", s->name, s->age, s->score); }
-
返回结构体的函数:
函数可以返回结构体类型的值:struct Student createStudent(char *name, int age, float score) { struct Student s; strcpy(s.name, name); s.age = age; s.score = score; return s; }
-
嵌套结构体:
一个结构体可以包含另一个结构体作为其成员:struct Address { char street[100]; char city[50]; }; struct Student { char name[50]; int age; struct Address address; };
-
结构体和内存对齐:
结构体的内存布局可能会受到编译器的内存对齐规则的影响,这可能会增加结构体的总大小。可以使用编译器特定的属性或指令来控制内存对齐。 -
结构体和位段:
C99标准引入了位段(bit fields),允许在结构体中定义占用特定位数的成员。
结构体是C语言中表示和操作复杂数据的强大工具,它们在实际编程中被广泛使用。正确使用结构体可以提高代码的可读性和可维护性。
二、教材学习中遇到的问题
(一)处理字符串时应当注意哪些问题
处理字符串时,需要注意以下几个问题以确保程序的正确性和安全性:
-
空字符(
'\0'
):- 确保字符串以空字符结尾,因为C语言中的字符串处理函数通常依赖空字符来确定字符串的结束。
-
缓冲区溢出:
- 确保在复制或连接字符串时不会超出目标缓冲区的大小,否则可能导致程序崩溃或安全漏洞。
-
内存管理:
- 当使用动态内存分配(如
malloc
、calloc
)时,确保为字符串分配足够的空间,并在使用完毕后释放内存。
- 当使用动态内存分配(如
-
字符串长度:
- 在处理字符串时,注意区分字符串的长度(不包括空字符)和分配的内存大小。
-
空指针检查:
- 在使用字符串之前,检查指针是否为
NULL
,以避免空指针解引用。
- 在使用字符串之前,检查指针是否为
-
字符串比较:
- 使用
strcmp
或strncmp
等函数比较字符串时,确保比较的是字符串的内容,而不是指针的值。
- 使用
-
字符编码:
- 考虑到不同字符编码(如ASCII、UTF-8)对字符串处理的影响,特别是在处理多字节字符时。
-
字符串分割:
- 使用
strtok
时,它不是线程安全的,并且会修改原始字符串。如果需要线程安全或不修改原始字符串,可以使用strtok_r
。
- 使用
-
字符串操作函数的选择:
- 根据需要选择正确的字符串操作函数,例如,使用
strncpy
和strncat
来防止溢出,而不是它们的非安全版本。
- 根据需要选择正确的字符串操作函数,例如,使用
-
格式化输出:
- 使用
printf
和scanf
等函数时,正确使用格式化字符串,避免格式化字符串漏洞。
- 使用
-
字符串拼接:
- 避免使用
gets
函数,因为它不安全。使用fgets
代替,并且指定最大读取长度。
- 避免使用
-
字符串搜索:
- 使用
strchr
或strstr
时,检查返回值是否为NULL
,以确定字符或子字符串是否存在。
- 使用
-
类型匹配:
- 确保传递给字符串处理函数的参数类型正确,例如,确保传递
const char*
给需要只读字符串的函数。
- 确保传递给字符串处理函数的参数类型正确,例如,确保传递
-
国际化和本地化:
- 如果程序需要支持多语言,考虑字符串的国际化和本地化问题。
-
性能问题:
- 在处理大量数据或在性能敏感的应用中,考虑字符串操作的性能影响。
-
异常和错误处理:
- 考虑在字符串操作中添加异常和错误处理机制,以便在出现问题时能够优雅地处理。
-
避免硬编码:
- 避免在代码中硬编码字符串,使用常量或宏定义来提高代码的可维护性。
通过注意这些问题,可以编写出更加健壮、安全和高效的字符串处理代码。
(二)使用指针处理字符串时应当注意哪些问题
使用指针处理字符串时,需要特别注意以下几个问题来确保程序的正确性和安全性:
-
空指针检查:
- 在使用指针之前,始终检查它是否为
NULL
,以避免空指针解引用。
- 在使用指针之前,始终检查它是否为
-
内存分配:
- 如果使用
malloc
、calloc
或realloc
等函数动态分配内存,确保分配了足够的空间,并在使用完毕后释放内存。
- 如果使用
-
内存释放:
- 避免重复释放内存(double free),一旦内存被释放,将指针设置为
NULL
。
- 避免重复释放内存(double free),一旦内存被释放,将指针设置为
-
缓冲区溢出:
- 确保在使用字符串操作函数(如
strcpy
、strcat
)时,目标缓冲区有足够的空间来存储结果字符串,以防止缓冲区溢出。
- 确保在使用字符串操作函数(如
-
指针算术:
- 在进行指针算术时,确保正确地处理字符数组的边界,避免越界访问。
-
指针类型匹配:
- 确保指针类型与所指向的数据类型匹配,特别是在将字符指针传递给函数时。
-
字符串终止:
- 确保字符串以空字符
'\0'
结尾,因为许多字符串处理函数依赖这个终止符来确定字符串的结束。
- 确保字符串以空字符
-
指针别名:
- 避免让两个指针指向同一块内存区域,除非你明确知道这样做的后果。
-
指针与数组:
- 理解指针和数组之间的关系,特别是在数组名作为参数传递给函数时。
-
指针和字符串字面量:
- 字符串字面量是只读的,指向它们的指针不应该用来修改字符串内容。
-
内存泄漏:
- 避免内存泄漏,确保每次
malloc
都有对应的free
。
- 避免内存泄漏,确保每次
-
指针比较:
- 比较指针时,比较的是它们指向的地址,而不是它们指向的内容。
-
指针和动态数组:
- 当使用指针操作动态数组时,确保正确地管理内存,包括分配和释放。
-
指针和类型转换:
- 在将指针转换为其他类型(如
void*
)时,确保在需要时进行正确的类型转换。
- 在将指针转换为其他类型(如
-
指针和函数返回值:
- 从函数返回指针时,确保返回的指针指向有效的内存区域,并且调用者知道如何正确地处理它。
-
指针和多线程:
- 在多线程环境中使用指针时,考虑线程安全问题,确保对共享数据的访问是同步的。
-
指针和字符串操作函数:
- 使用指针和字符串操作函数时,确保理解函数的行为,特别是它们如何处理空字符和缓冲区大小。
-
指针和格式化输出:
- 使用
printf
等函数输出字符串时,确保使用正确的格式说明符,如%s
用于char*
类型的指针。
- 使用
-
指针和字符串常量:
- 如果指针指向的是一个字符串常量,不要尝试修改它,因为它通常存储在只读内存区域。
通过注意这些事项,可以有效地避免在使用指针处理字符串时出现的常见错误和安全问题。
三、基于AI的学习