C语言|《C Primer Plus》读书笔记

1|0字符串和字符串函数

1|1字符串数组初始化:

\\定义字符串数组: const char m1[40] = "Limit youtself to one line's worth."; \\可以省略数组大小,让编译器自动计算数组大小: const char m2[] = "Limit youtself to one line's worth."; \\使用指针表示法创建字符串: const char* pt1 = "Something is pointing at me.";

1|2旧I/O函数:

gets() 读取整行输入,直到遇到换行符,然后丢弃换行符。

puts() 用于显示字符串,并在末尾添加换行符。

#include<stdio.h> #define STLEN 81 int main(void) { char words[STLEN]; puts("Enter a string,Please."); gets(words); printf("Yout string twice:\n"); printf("%s\n",words); puts(words); puts("Done."); return 0; }

1|3新I/O函数:

fgets()第1个参数为写入的字符数组名称。

fgets()函数通过第2个参数(例如n)限制读入的字符数来解决溢出问题。

fgets()将读取n-1个字符或遇到第一个换行符为止。fgets()读到的换行会存在字符串中。

fgets()第3个函数指明要读入的文件。如果用stdin 可表示从键盘输入,stdout表示从命令行输出。

gets_s()函数不需要第三个参数,但没fgets()方便

终极版本——s_gets函数,读取整行输出并用空字符代替换行符。(或者读取一部分输出,丢弃剩余一部分。

1|4 自定义输入/输出函数:

一般可采用getchar() 和 putchar() 配合循环whlie(*str)来定制I/O函数。

//实现puts()函数 int put2(const char * string){ int count = 0; while (*string){ putchar(*string++);//获取字符并将其保存到*(string+i) count++; } putchar('\n'); return(count);//返回字符个数 }

1|5字符串函数:

主要涉及四种字符串函数及其变种。

1|0查询长度strlen()

//该函数可缩短字符串长度 void fit(char *string, unsigned int size){ if (strlen(string) > size) string[size] = 0; }

1|0拼接字符串strcat()

 strcat()接收两个字符串作为参数,把第二个字符串拼接在第一个字符串的末尾。

strncar()函数第三个参数指定了最大添加字符数,确保安全性(第一个字符串可能不够大来容纳第二个字符串)

strcat(str1,str2); strncat(str1,str2,n);//n限制最大添加字符数

1|0比较字符串strcmp()

 如果两个字符串参数相同,返回0,否则返回非零值。(非零值都为真)

常用测试条件:

while(strcmp(str1,str2)){ ...... }

strncmp()第三个参数可限定查找的字符数:

 

1|0复制字符串strcpy()

直接拷贝字符串是不可行的。

char ptr1[40]; char ptr2[40]; ptr1 = ptr2;//仅仅是把指针赋值

正确方法:

char ptr1[40]; char ptr2[40]; strcpy(ptr1.ptr2);//复制字符串2覆盖字符串1

strncpy(target, source, n)的第三个参数指明可拷贝的最大字符数

1|0写入字符串sprintf()

sprintf(str1, "%s, %-19s", str2, str3); printf("%s", str1);//将"%s, %-19s"写入str1

1|6ctype.h 字符函数

while(*str){ *str = toupper(*str);//将str字符串全部大写 str++; }

其他自搜可用。

1|7命令行参数

main()后两个参数,需要在命令行下调用,不太会用。

1|8实例应用:字符串排序

 

1|0选择排序算法:

void stsrt(char *strings[], int num){ //采用排序指针而非字符串 char *temp; int top, seek; for(top = 0; top < num - 1; top++)    //选择排序主体 for(seek = top + 1; seek < num; seek++) if(strcmp(strings[top], strings[seek]) > 0)  //判断是否不同 { temp = strings[top]; strings[top] = strings[seek]; strings[seek] = temp;    //交换两个字符串位置 } }

2|0存储类别,链接和内存管理

本章难度很大,不是很理解。

2|1部分概念:

1|0作用域

作用域有:块作用域,函数作用域,函数原型作用域或文件作用域。

块作用域:声明在语句块中的变量,在语句块内可见

函数作用域::声明在函数中的变量,函数体内可见

函数原型作用域:仅仅在函数原型的那个括号()里面可见。

文件作用域: 变量定义在函数的外面,从定义到文件末尾可见

1|0链接

C变量有3种链接属性:外部链接、内部链接和无链接。块作用域、函数作用域和函数原型作用域的变量都是无链接变量。

具有文件作用域的变量可以时外部链接或内部链接,外部链接可在多文件程序中使用,内部链接只能在当前单元使用。

存储类别说明符static可区分内部链接和外部链接:

 int a = 6; //外部链接

static int b = 5; //内部链接 

static实例:函数调用计数。该代码避免了使用全局变量,提高安全性。

1 #include <stdio.h> 2 void count(); 3 int main(void) 4 { 5 int i=0; 6 for (i = 0;i <= 5;i++) 7 { 8 count(); 9 } 10 return 0; 11 } 12 void count() 13 { 14 /*声明一个静态局部变量*/ 15 static num = 0; 16 num++; 17 printf("%d\n",num); 18 }

1|0存储期

存储期描述了对象的生存期。(不太懂)

C对象有4种存储期:静态存储期、线程存储期、自动存储期、动态分配存储期。

静态存储期: 静态存储期的对象在程序执行期间一直存在。文件作用域变量具有静态存储期。

线程存储期:用于并发程序设计,程序执行可分为多个线程。具有线程存储期的对象,从被声明至线程结束期间存在。

以关键字_Thread_local 声明一个对象时,每个线程都获得该变量的私有备份。

自动存储期:块作用域变量通常具有自动存储期。内存自动分配和释放。 块作用域变量在前面加上static可以变长静态存储期。

2|2随机数及实例

1|0rand()函数

#include <stdlib.h> //前置库
#include <stdio.h> int main(){ srand(seed); //生成随机数种子 rand(); //生成随机数 }

1|0实例:

生成1000个1-10的随机数,统计其出现次数并打印。

1 #include <stdio.h> 2 #include <time.h> 3 #include <stdlib.h> 4 #define LEN 11 5 6 void show_array(int * a, int n); 7 8 int main(void) 9 { 10 int i, a[LEN]; 11 12 for (i = 0; i < LEN; i++) 13 { 14 a[i] = 0; 15 } 16 17 for (int j = 0; j < 1000; j++){ 18 srand(j*100+(unsigned int)time(0)); //生成1000个随机数 19 for (i = 1; i < LEN; i++) 20 { 21 if(rand()%10+1 == i) //把1000个随机数放入桶中 22 a[i] +=1; 23 } 24 } 25 show_array(a, LEN); 26 return 0; 27 } 28 void show_array(int * a, int n){ 29 for (int i = 1; i < LEN; i++) 30 { 31 printf("a[%d]:%d\n",i,a[i]); 32 } 33 }

2|3malloc()函数和free()函数

malloc()分配内存,可用来创建数组。

free()释放内存

例1:要求输入元素个数及元素值,采用malloc()函数为其设置数组并赋值

#include <stdio.h> #include <stdlib.h> int *make_array(int elem, int val); void show_array(const int ar[], int n); int main(void) { int *pa; int size; int value; printf("Enter the number of elements: "); while (scanf("%d", &size) == 1 && size > 0) //循环输入数组元素 { printf("Enter the initialization value: "); scanf("%d", &value); pa = make_array(size, value); if (pa) { show_array(pa, size); free(pa); } printf("Enter the number of elements (<1 to quit): "); } printf("Done.\n"); return 0; } int *make_array(int elem, int val){ //使用malloc()创建数组 int * ptr; ptr = (int *)malloc(elem * sizeof(int)); for(int i = 0; i < elem; i++){ *(ptr + i) = val; } return ptr; } void show_array(const int ar[], int n){ //展示数组 int cnt = 0; for(int i = 0; i < n; i++){ printf("%d ",ar[i]); cnt++; if ((cnt + 1) % 8 == 0) printf("\n"); } return; }

输出结果:

Enter the number of elements: 3 Enter the initialization value: 2 2 2 2 Enter the number of elements (<1 to quit):

例2:要求输入指定数量(n)个单词,将其存放并逐词输出。

1 #include <stdio.h> 2 #include <string.h> 3 #include <stdlib.h> 4 #define LEN 256 5 6 int main(void) 7 { 8 char **pt; //指向指针的指针,即指向数个字符串的指针 9 int i, n, length; 10 char temp[LEN]; 11 12 printf("How many words do you wish to enter? "); 13 scanf("%d", &n); 14 if ((pt = (char **)malloc(n * sizeof(char *))) != NULL) 15 { 16 printf("Enter %d words now:\n", n); 17 for (i = 0; i < n; i++) 18 { 19 scanf("%255s", temp); 20 length = strlen(temp) + 1; 21 pt[i] = (char *)malloc(length * sizeof(char)); 22 //采用malloc()存放 23 if (NULL == pt[i]) 24 { 25 printf("Memory allocation failed!\n"); 26 exit(EXIT_FAILURE); 27 } 28 strcpy(pt[i], temp); 29 //将temp内容拷贝至pt[i] 30 } 31 printf("Here are your words:\n"); 32 for (i = 0; i < n; i++) 33 { 34 puts(pt[i]); 35 free(pt[i]); 36 pt[i] = NULL; 37 } 38 free(pt); 39 pt = NULL; 40 //释放pt指向的内存后再释放pt为NULL指针 41 } 42 else 43 { 44 printf("Memory allocation failed!\n"); 45 exit(EXIT_FAILURE); 46 } 47 48 return 0; 49 }

输出结果:

How many words do you wish to enter? 3 Enter 3 words now: hello world alion Here are your words: hello world alion

3|0文件输入输出

3|1fopen函数

该函数声明在stdio.h中,它的第一个参数是待打开文件的名称(确切的说是一个包含该文件名的字符串地址),第二个参数是一个字符串,指定待打开文件的模式:

程序成功打开文件后,fopen()将返回文件指针file pointer,其他I/O函数可以使用这个指针指向该文件。

3|2getc()和putc()函数

这两个函数与getchar()putchar()类似,但是要告诉这两个函数使用哪一个文件。

1 int ch; // 用int类型的变量EOF 2 FILE * fp; 3 fp = fopen("wacky.txt", "r"); 4 ch = getc(fp); // 获取初始输入 5 while (ch != EOF) 6 { 7 putchar(ch); // 处理输入 8 ch = getc(fp);// 获取下一个输入 9 } 10 11 // 简化一下 12 int ch; 13 FILE * fp; 14 fp = fopen("wacky.txt", "r"); 15 while ((ch = getc(fp) != EOF) 16 { 17 putchar(ch); // 处理输入 18 }

3|3fclose()函数

fclose(fp)函数关闭fp指定的文件,必要时刷新缓冲区。对于较正式的程序,应该检查是否成功关闭文件。如果成功关闭,fclose()函数返回0,否则返回EOF。

if (fclose(fp) != 0) printf("Error in closeing file %s\n", argv[1]);//argv[I]表示文件名

3|4指向标准文件的指针

3|5随机访问:fseek()和ftell()

有了fseek()函数,就可以把文件看成数组,在fopen()打开的文件中直接移动到任意字节处。

1 /* reverse.c -- 倒序显示文件中的内容 */ 2 #include <stdio.h> 3 #include <stdlib.h> 4 #define CNTL_Z '\032' /* DOS文本文件中的文件结尾标记 */ 5 #define SLEN 81 6 int main(void) 7 { 8 char file[SLEN]; 9 char ch; 10 FILE *fp; 11 long count, last; 12 13 puts("Enter the name of the file to be processed:"); 14 scanf("%80s", file); 15 if ((fp = fopen(file, "rb")) == NULL) 16 { 17 printf("reverse can't open %s\n", file); 18 exit(EXIR_FAILURE) 19 } 20 21 fseek(fp, 0L, SEEK_END); /* 定位到文件末尾 */ 22 last = ftell(fp); 23 for (count = 1L; cout <= last; count++) 24 { 25 fseek(fp, -count, SEEK_END); /* 回退 */ 26 ch = getc(fp); 27 if (ch != CNTL_Z && ch != '\r') /* MS-DOS文件 */ 28 putchar(ch); 29 } 30 putchar('\n'); 31 fclose(fp); 32 return 0; 33 }

3|6fprintf()和fscanf()函数

fprintf(stdout, "%s\n", "Succ"); while (fscanf(fp, "%s", words) == 1) rewind(fp); /* 返回到文件开始处 */

__EOF__

本文作者Study Blog
本文链接https://www.cnblogs.com/alion/p/16056254.html
关于博主:评论和私信会在第一时间回复。或者直接私信我。
版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!
声援博主:如果您觉得文章对您有帮助,可以点击文章右下角推荐一下。您的鼓励是博主的最大动力!
posted @   C₅H₁₂O₄季戊四醇  阅读(89)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· Manus的开源复刻OpenManus初探
· 写一个简单的SQL生成工具
· AI 智能体引爆开源社区「GitHub 热点速览」
· C#/.NET/.NET Core技术前沿周刊 | 第 29 期(2025年3.1-3.9)
点击右上角即可分享
微信分享提示