文件学习9

//C语言之字符函数与预处理

//1. 改变文件(光标)位置的函数及参数?

//fseek(FILE * stream, int offset, int mode);

//mode: SEEK_SET 0, SEEK_CUR 1, SEEK_END 2

//rewind(FILE * stream);

//fsetpos(FILE* stream, streampos*);

//2. 如何验证文件是否已到尾部?

//feof(FILE * stream);

//fgetc() == EOF

//3. 打开文件的模式?

//w, w + , r, r + , a, a +

//一、字符函数

//对于字符串或字符数组的操作相关的函数,如字符串的长度、查找字符、拼接、复制、分隔...

//字符处理函数都在 <string.h> 头文件中。

//1.1 字符串的查找函数

// 从_String 字符串查找 子串subString的位置,如果没有找到则返回NULL。

char* strstr(char* const _String,

const char* subString);

// 从_String 字符串查找 c字符的位置,未找到则返回NULL

// 从左到右的方式查找

char* strchr(char* const _String, char c);

// 从_String 字符串查找 c字符的位置,未找到则返回NULL

// 从右到左的方式查找

char* strrchr(char* const _String, char c);

//如

#include <stdio.h>

#include <string.h>

int main() {

char arr[128] = "123abcd998877";

// 查找子串

char* p1 = strstr(arr, "999");

if (p1 != NULL) {

printf("%s\n", p1);

}

// 查找字符

char* p2 = strchr(arr, 'c');

if (p2 != NULL) {

printf("p2 =%s\n", p2);

}

// 从右边开始查找字符,返回右边第一次出现的位置

char* p3 = strrchr(arr, '7');

if (p3 != NULL) {

printf("p3 =%s\n", p3);

}

return 0;

}

//1.2 字符串拼接与分隔函数

// 将src的内容拼接到dest内容之后,返回dest

char* strcat(char* dest, const char* src);

// 将src的前n个字符内容拼接到dest内容之后,返回dest

char* strncat(char* dest,

const char* src, size_t n);

// 按delimiters给定的所有分隔符对dest进行切割

// 切割的原理,将分隔符转成\0,遇到重复(可能是不同的分隔符)的则跳过,最后没有可切割时,则返回

//NULL, 表示完成了。

char* strtok(char* dest, const char* delimiters);

//如: 字符串的拼接

#define _CRT_SECURE_NO_WARNINGS

int main() {

char s1[128] = "123";

//s2指针指向的常量区的"abc"空间,

// 其空间内容是不可以修改的

char* s2 = "abc";

// 将s2的内容拼接到s1内容的后面,即修改s1空间

char* p1 = strcat(s1, s2);

printf("p1 is %s\n", p1);

char* s3 = "907";

// 将s3的前2个字符拼接到s1空间中

strncat(s1, s3, 2);

printf("p1 is %s\n", p1);

return 0;

}

//如2: 字符串的切割

#define _CRT_SECURE_NO_WARNINGS

int main() {

char s1[128] = "1,2.3#4@5.@6,@#7*8";

// 切割s1字符串,并指定切割的所有可能的字符串

// 切割的原理是将分隔符修改为 \0, 如果连续出现的,

// 只会修改第一个字符为\0, 之后则跳过重复的分隔符

// 切割失败时,表示字符串切割完成,则返回NULL

char* p = strtok(s1, ",.#@*");

while (p != NULL) {

printf("%s ", p); // 将上一次切割内容打印

// 因为第一次切割时,字符串内的内容并没有切割结束

// 因此第二次切割时,则会沿着上一次的结果继续切割

// 所以,第一个参数为NULL, 表示没有新位置,继上一次位置向后继续分隔

p = strtok(NULL, ",.#@*");

}

return 0;

}

//练习: 将s1数组的内容按行分隔,并读取每一行的pid 证件号和phone手机号。

char s1[1024] = "1001,19978651243\n1002,19978651244\n1004,19978655243\n1004,19978651943\n1005, 19778651243\n1006, 15978651243\n1007, 19978651990\n1008, 15578651240\n";

//完整示例:

int main() {

char s1[1024] =

"1001,19978651243\n1002,19978651244\n1004,19978655243\n1004,19978651943\n1005,19778651243\n1006, 15978651243\n1007, 19978651990\n1008, 15578651240\n";

char* line = strtok(s1, "\n");

char* lines[32];

int i = 0;

// 1. 先读取所有行的位置

while (line != NULL) {

lines[i++] = line;

line = strtok(NULL, "\n");

}

// 2. 针对每一行进行分隔

for (int k = 0; k < i; k++) {

char* pid = strtok(lines[k], ",");

char* phone = strtok(NULL, ",");

printf("pid(%s), phone(%s)\n", pid, phone);

}

//3. 验证s1的内容是否修改

printf("s1 is %s\n", s1);

return 0;

}

//1.3 自定义切割字符的函数

#define _CRT_SECURE_NO_WARNINGS

#include <stdio.h>

#include <string.h>

// 从arr中查找delims中任意一个字符,并修改为\0

char* mytok(char* arr, const char* delims) {

static char* next;

char* p;

if (arr == NULL) {

p = next;

}

else {

p = arr;

}

if (p == NULL) return NULL;

int len = strlen(p);

// 从arr中查找到 delims中任意一个分隔符

int i = 0;

int finded = 0;

for (; !finded && i < len; i++) {

for (int j = 0; j < strlen(delims); j++) {

if (p[i] == delims[j]) { // 查到了分隔符的位置

p[i] = 0; // 分隔符置 \0

finded = 1; // 查到了

break;

}

}

}

if (finded)

next = p + i; // 记录下一次分隔的位置

else

next = NULL; // 分隔结束

return p;

}

int main() {

char s1[] = "1,2,3,4";

char* n1 = mytok(s1, ",");

while (n1 != NULL) {

printf("%s\n", n1);

n1 = mytok(NULL, ",");

}

//printf("n1 is %s\n",n1); // 要求: 1

//char* n2 = mytok(NULL, ",");

//printf("n2 is %s\n", n2);

return 0;

}

//1.4 字符串比较函数

// 字符串比较是指的是两者的字符串按每一次的字符ASCII值进行比较, 比较的结果(返回值)有三种情

//况:

// 0: 两者的字符的内容完整一样

// 1: 前者(s1)中比较的字符ASCII大于后者(s2)

// -1: 前者(s1)中比较的字符ASCII小于后者(s2)

int strcmp(const char* s1, const char* s2);

// 功能同上,只不过只比较 前n个字符

int strncmp(const char* s1, const char* s2, int n);

int main() {

char s1[128] = "abc123";

// 如果s1中每一个字符的ASCII都与

// 第二个字符串的每一个字符的ASCII相同的情况,则返回0

int ret1 = strcmp(s1, "abc123");

// s1和比较字符串按从左到右的顺序进行每一个字符比较

// 存在一个字符比比较的字符的ASCII小,则返回-1

int ret2 = strcmp(s1, "dbc123");

// 如果s1中的字符比后者要大小,则返回1

int ret3 = strcmp(s1, "aac123");

printf("ret1=%d,ret2=%d, ret3=%d\n", ret1, ret2, ret3);

char s2[32] = "abcdef";

printf("s1 == s2: %d\n", strcmp(s1, s2));

// 只比较s1和s2的前3个字符,结果是 0

printf("%d\n", strncmp(s1, s2, 3));

return 0;

}

//练习: 简易版本的翻译app

//从键盘输入英文单词,并输出其解释中文, 直到输入q, quit退出。 英文单词的翻译在 words.txt

//文件中。

//文件内容如下: 文件的编码格式 ANSI

//red:红, 红色

//yellow : 黄, 黄色

//book : 书, 书籍, 图书

//blank : 黑, 黑色

int main() {

FILE* fw = fopen("words.txt", "rb");

/*fseek(fw, 0, SEEK_END);

long len = ftell(fw);

fseek(fw, 0, SEEK_SET);

char* buf = (char*)malloc(len+1);

memset(buf, 0, len + 1);

fread(buf, 1, len, fw);*/

/*printf("file size is %ld\n", len);

printf("%s", buf);*/

char line[64] = "";

while (1) {

printf("查询的单词:");

fgets(line, 64, stdin);

//strtok(line, "\n");//去掉换行

line[strlen(line) - 1] = 0;

if (strncmp(line, "q", 1) == 0) break;

fseek(fw, 0, SEEK_SET);// 确保文件的光标在开始位置

while (!feof(fw)) {

char fline[128] = "";

fgets(fline, 128, fw); // 从文件中读取一行

if (strlen(fline) == 0) break;

char* word = strtok(fline, ":");

// printf("word: %s\n", word);

if (strcmp(line, word) == 0) {

printf("%s\n", strtok(NULL, ":"));

break;

}

}

if (feof(fw)) {

printf("暂无此单词的翻译,请稍等新的版本!\n");

}

}

//free(buf);

fclose(fw);

return 0;

}

//1.5 字符串复制与清零函数

// 将src的内容复制到dest开始的位置,并返回dest

char* strcpy(char* dest, const char* src);

// 将src的前n个字符内容复制到dest开始的位置,并返回dest

char* strncpy(char* dest, const char* src, int n);

// 将src空间的内容的n个字节复制到dest空间中,返回dest位置

void* memcpy(void* dest, const void* src, size_t n);

// 功能同memcpy, 但memmove是已过时的函数

void* memmove(void* dest, const void* src, size_t n);

// 设置size大小的dest空间的值为n, 如果n为0时,表示初始化空间

memset(void* dest, int n, size_t size);

//如1

int main() {

char dest[256] = "";

// 将后者的字符串复制到dest位置空间中

strcpy(dest, "123");

// 复制之后,返回新内容的开始位置 (传入的位置)

char* p = strcpy(dest + 3, "456");

printf("dest is %s\n", dest);

printf("p is %s\n", p);

const char* s1 = "hi,lucy!";

// 将s1的lucy内容复制到 dest空间中

strncpy(dest, s1 + 3, 4);

printf("dest is %s\n", dest);

return 0;

}

//如2

typedef struct { int x; int y; } Point;

int main() {

char name[32] = "";

const char* s1 = "disen";

const char* s2 = "hi,";

// 1. 复制字符串

memcpy(name, s2, 3);

memcpy(name + 3, s1, 5);

printf("name is %s\n", name);

// 2. 复制非char类型的数组

int arr[30] = { 0 };

const int a1[3] = { 1, 2, 3 };

memcpy(arr, a1, 3 * sizeof(int));

for (int i = 0; i < 30; i++) {

if (arr[i] != 0)

printf("%d ", arr[i]);

}

//3. 复制结构体类型变量的空间

Point p1 = { 2, 5 };

Point p2 = { 8, 9 };

memcpy(&p1, &p2, sizeof(Point));

printf("p1(%d,%d)\n", p1.x, p1.y);

return 0;

}

//如3

int main() {

char dest[128] = "";

const char* s1 = "good";

memmove(dest, s1, 4);

printf("dest is %s, s1 is %s\n", dest, s1);

return 0;

}

//二、预处理

//预处理是程序编译的四个重要阶段之一, 程序编译过程:

//第一阶段: 预处理 , 对程序文件中的 # 相关指令进行处理, 如 #学include , #define, #if,

//#endif

//第二阶段: 编译, 将预处理之后的文件内容进行编译成汇编程序,即包含各种的指令和数据,以

//及语法检查。

//第三阶段: 汇编, 将汇编程序 编译成二进制文件, 如.obj 。

//第四阶段 : 链接, 链接指定头文件中相关函数的定义所在的库文件(静态库, 动态库 DLL), 链接之

//后,生成可执行文件。

//2.1 #define 指令

//#define 定义宏

//#define 宏名

//#define 宏名 值

//#define 宏名(参数名,...) 表达式

//2.2 #ifdef 和 #ifndef 指令

//#ifdef 宏名 // 验证是否定义 宏

//#ifndef 宏名 // 验证宏是否没有定义

//如:

#include <stdio.h>

#define PI 3.1415926

#define mul(a, b) (a)*(b)

double area(double r) {

// PI 宏在预处理时,则迭代成 表达式值 3.1415926

#ifdef PI

return PI * r * r;

#else

return 3.16 * r * r;

#endif // PI

}

int main() {

printf("area is %.6f\n", area(5.0));

// 预处理的表达式: 10-2*8-5;

printf("%d\n", mul(10 - 2, 8 - 5));

return 0;

}

相关推荐
华农DrLai2 小时前
什么是自动Prompt优化?为什么需要算法来寻找最佳提示词?
人工智能·算法·llm·nlp·prompt·llama
野犬寒鸦2 小时前
从零起步学习JVM|| 第二章:JVM基本组成及JVM内存区域详解
服务器·开发语言·后端·学习·面试·职场和发展
黎阳之光2 小时前
十五五智赋新程 黎阳之光以AI硬核技术筑造产业数智底座
大数据·人工智能·算法·安全·数字孪生
2401_891482172 小时前
C++中的原型模式
开发语言·c++·算法
罗罗攀2 小时前
PyTorch学习笔记|张量的线性代数运算
人工智能·pytorch·笔记·学习·线性代数
皙然2 小时前
深度解析三色标记算法:JVM 并发 GC 的核心底层逻辑
java·jvm·算法
sali-tec2 小时前
C# 基于OpenCv的视觉工作流-章40-特征找图
图像处理·人工智能·opencv·算法·计算机视觉
wearegogog1232 小时前
毫米波MIMO系统仿真中混合预编码的交替最小化算法
算法·预编码算法
油泼辣子多加2 小时前
【DL】Transformer算法应用
人工智能·深度学习·算法·机器学习·transformer