C语言笔记:重学输入和输出

news2024/11/15 12:10:20

   ACM金牌带你零基础直达C语言精通-课程资料

 本笔记属于船说系列课程之一,课程链接:ACM金牌带你零基础直达C语言精通icon-default.png?t=N7T8https://www.bilibili.com/cheese/play/ep159068?csource=private_space_class_null&spm_id_from=333.999.0.0

你也可以选择购买『船说系列课程-年度会员』产品『船票』,畅享一年内无限制学习已上线的所有船说系列课程:船票购买入口icon-default.png?t=N7T8https://www.bilibili.com/cheese/pages/packageCourseDetail?productId=598

做题网站OJ:HZOJ - Online Judge

Leetcode :力扣 (LeetCode) 全球极客挚爱的技术成长平台

一.三个标准流:stdin、stdout、stderr

标准输出流(stdout)

        对应的文件表示符为:1

        对于为什么打印一行字符串为什么会默认打印倒终端中,因为操作系统把标准输出流定向到了终端环境中。

        程序可以使用标准输出函数(如 printfputs 等)将数据输出到 stdout,从而在终端上显示结果。

标准输入流(stdin)

        对应的文件表示符为:0

        默认在终端环境中进行读取数据。

        用户可以通过键盘向程序提供输入,该输入会被发送到 stdin 中。程序可以使用标准输入函数(如 scanffgets 等)从 stdin 中读取数据。

标准错误输出流(stderr)

        对应的文件表示符为:2

        默认输出定向是终端环境中。

        程序可以使用标准错误输出函数(如 fprintf(stderr, ...))将错误信息输出到 stderr,从而在终端上显示错误。

三个流的缓冲区

代码演示:

1.对于3种流的最基本的使用:
#include<stdio.h>

int main() {
    //利用标准输出流输出
    printf("hello world\n");// stdout
    int n;
    //利用标准输入流进行读取数据
    scanf("%d", &n);// stdin
    printf("n = %d\n", n);
    //利用了标准错误输出流进行输出数据
    perror("out of range\n");//stderr

    return 0;
}

代码执行结果:

2.对于缓冲区的认识:

这段代码是可以执行的:

#include<stdio.h>



int main() {
    printf("alskaskldjaslkdjlaskld123");
    *((int *)(0)) = 5;
    return 0;
}

执行结果:

可以看到终端上没有打印printf函数内的内容,但不能说明printf函数那句代码是有错误的,只是内容还在输出缓冲区里面,还没有进行输出,程序就执行崩溃了。

继续往下看:

在printf函数内容种最后加上一个换行符(\n),看输出结果:

因为遇到换行符 \n 时会触发缓冲区的刷新,即将缓冲区中的数据输出到终端中。

这就体现了缓存区的作用。

另一种方法就是使用fflush进行对内容输出:

#include<stdio.h>

int main() {
    printf("alskaskldjaslkdjlaskld123\n");
    //stdout在操作系统种也是文件
    //利用fflush函数进行对stdout文件进行冲刷,也就是刷新他的缓冲区
    //然后内容就会打印到终端上
    fflush(stdout);
    *((int *)(0)) = 5;
    return 0;
}

执行结果:

窥探标准流fscanf和fprintf

程序中如何使用:

#include<stdio.h>

int main() {
    //向标准输出流种输出hello world
    fprintf(stdout, "hello world\n");
    //向标准输入流种读入数据
    int n;
    fscanf(stdin, "%d", &n);
    //向标准错误输出流种打印n的值
    fprintf(stderr, "n = %d\n", n);
    return 0;
}

执行结果:

标准流的重定向:

如何讲输出内容重定向输出到一个文件中?

两种方式

第一种方法:

是用freopen函数进行重定向:

如何使用:

#include<stdio.h>


int main() {
    //参数一需要输出的新文件名
    //参数二以打开文件的什么模式
    //参数三需要重新定向的文件指针
    freopen("output.txt", "w", stdout); //r代表读文件,w代表写文件
    freopen("input.txt", "r", stdin); //r代表读文件,w代表写文件
    printf("hello freopen yes\n");
    char s[1000] = {0};
    //当读入到文件结尾时,循环结束
    while (scanf("%[^\n]", s) != EOF) {
        //getchar()从标准输入流中读取一个字符
        //这里为什么要使用到getchar()
        //因为在使用scanf时
        //里面的字符匹配集是非\n就读取
        //那么在最后遇到\n的时候结束读取
        //最后输入流中会存留一个\n
        //然后scanf一直不读取
        //最后造成了while死循环
        //所以在这需要使用一个getchar()来对\n进行处理掉
        getchar();

        printf("%s | hello world\n", s);
    }
    return 0;
}

input.txt(这个文件是需要自己创建,并在里面写东西的):

ni hao
CSDN 
GCC
Good

执行前,只有input.txt和源代码文件:

执行后(a.out是源代码编译后的可执行程序):

发现output.txt在执行程序后被创建出来,再看看output.txt中的内容:

和程序设计还有想法是一样的结果。

第二种方法:

在命令中执行重定向(只能在linux环境下可以使用)

需要用到的源代码:


#include<stdio.h>

int main() {
    char s[1000] = {0};
    while (scanf("%[^\n]", s) != EOF) {
        getchar();
        printf("%s | hello world\n", s);
    }

}

然后进行对源文件的编译:

在进行对执行文件的标准输出流重定向到output.txt文件中, 因为是输出所以需要指向目标文件

在输入的最后,需要手动打入一个文件结束,ctrl + D, 表示输入结束。

然后打开output.txt文件查看:

在试一下对执行文件的标准输入流重定向, 因为是需要读入所以需要目标文件是可执行程序,需要指向自己

用命令行重定向标准错误输出流:

#include<stdio.h>

int main() {
    char s[1000] = {0};
    int i = 1;
    while (scanf("%[^\n]", s) != EOF) {
        getchar();
        fprintf(stderr, "%d test\n", i++);
        printf("%s | hello world\n", s);
    }

}

执行命令:

2是表示标准错误流的文件表示符,然后讲标准错误输出流重定向到output_err.txt文件中.

执行效果:

 重学scanf

scanf函数读入缓存区

先用scanf读入两个整形:

现在在缓冲区中有一段内容,然后进行读取,知道读到第一个非法字符.

当读入到空格时,空格就是这个非法字符,此时停止,然后把123转为整形赋值给变量a

然后会跳过空白符,也就是空格,然后再进行读取,在次读到非数字字符时会进行停止,然后给变量b进行赋值.

最后结果,然后缓存区中只有换行符.

scanf读入%c

在当前缓存区中,%c会读取456前面的空格字符,而不是读入'4'这个字符.

下面用程序进行演示:

#include<stdio.h>
int main() {
    char c1, c2;
    int a, b;
    scanf("%d", &a);
    scanf("%c%c", &c1, &c2);
    scanf("%d", &b);
    printf("a = %d, b = %d\n", a, b);
    printf("c1 = %d, c2 = %d\n", c1, c2);
    return 0;
}

执行结果:

处理scanf读入残值的技巧

 利用getchar()吞掉一个字符

下面的代码演示:

getchar()的用法
#include<stdio.h>


int main() {
    int a, b;
    scanf("%d%d", &a, &b);
    //利用getchar吞掉换行符
    getchar();
    char c = 'x';
    scanf("%c", &c);
    printf("a = %d, b = %d, c = %c\n", a, b, c);
    return 0;
}

执行结果:

利用getchar() 吞掉\n符,准确的给字符c进行赋值.

二.实现一个printf函数

第一步:实现printf函数声明:

#include<stdio.h>
int my_printf(const char *format, ...) {

}

int main() {

    return 0;
}

第二步:实现输出"hello world"功能

还处理了一个问题%特殊情况处理.

#include<stdio.h>

//这个宏定义是测试printf和my_printf区别
#define TEST(format, args...) {\
    int n1, n2;\
    n1 = printf(format, ##args);\
    n2 = my_printf(format, ##args);\
    printf("n1 = %d, n2 = %d\n", n1, n2);\
}

int my_printf(const char *format, ...) {
    #define PUTC(c) putchar(c), cnt += 1
    //cnt代表输出了多少个字符
    int cnt = 0;
    for (int i = 0; format[i]; i++) {
        switch (format[i]) {
            //如果当前字符是%,那么就需要对下个字符进行特殊处理
            case '%': {
                switch (format[i + 1]) {
                    //当有两个%时,那就需要打印一个%
                    case '%': {
                        PUTC(format[i + 1]);
                        //对于下个位置已经处理所以需要i+1
                        i++;
                    } break;
                }
            } break;
            default : PUTC(format[i]); break;
        }
        //putchar() 是向屏幕上打印一个字符
    }
    return cnt;
}

int main() {
    //测试printf和my_printf输出hello world
    TEST("hello world\n");
    //对于printf%%输出就是一个%
    //由于printf对%是特殊处理,那么对于my_printf也就需要特殊处理
    TEST("100%%\n");
    return 0;
}

执行结果:

第三步实现%s输出功能

#include <stdio.h>
#include <stdarg.h>

//这个宏定义是测试printf和my_printf区别
#define TEST(format, args...) {\
    int n1, n2;\
    n1 = printf(format, ##args);\
    n2 = my_printf(format, ##args);\
    printf("n1 = %d, n2 = %d\n", n1, n2);\
}

int my_printf(const char *format, ...) {
    #define PUTC(c) putchar(c), cnt += 1
    va_list args;//args表示变参列表
    va_start(args, format);//变参列表从format参数后面开始
    //cnt代表输出了多少个字符
    int cnt = 0;
    for (int i = 0; format[i]; i++) {//这里中间条件用到了format[i],当format[i] = '\0'时表示循环结束
        switch (format[i]) {
            //如果当前字符是%,那么就需要对下个字符进行特殊处理
            case '%': {
                switch (format[i + 1]) {
                    //当有两个%时,那就需要打印一个%
                    case '%': {
                        PUTC(format[i + 1]);
                        //对于下个位置已经处理所以需要i+1
                        i++;
                    } break;
                    //%后接s那么就是字符串的格式占位符
                    //然后这里就需要用到变参列表的解析
                    case 's': {
                        //获取变参列表的参数,并且该参数的类型为char *类型
                        const char *s = va_arg(args, const char *);
                        //获取到字符串后,进行打印字符串
                        for (int j = 0; s[j]; j++) PUTC(s[j]);
                        //s这个字符被处理掉了,不需要打印了,位置需要往后移
                        i++;
                    } break;
                }
            } break;
            default : PUTC(format[i]); break;
        }
        //putchar() 是向屏幕上打印一个字符
    }
    return cnt;
}

int main() {
    //测试printf和my_printf输出hello world
    TEST("hello world\n");
    //对于printf%%输出就是一个%
    //由于printf对%是特殊处理,那么对于my_printf也就需要特殊处理
    TEST("100%%\n");
    TEST("%s\n", "hello world 100 %%");
    return 0;
}

执行结果:

第四步实现%d输出功能

#include <stdio.h>
#include <inttypes.h>
#include <stdarg.h>
#include <math.h>
#include <limits.h>

//这个宏定义是测试printf和my_printf区别
#define TEST(format, args...) {\
    int n1, n2;\
    n1 = printf(format, ##args);\
    n2 = my_printf(format, ##args);\
    printf("n1 = %d, n2 = %d\n", n1, n2);\
}

int my_printf(const char *format, ...) {
    #define PUTC(c) putchar(c), cnt += 1
    va_list args;//args表示变参列表
    va_start(args, format);//变参列表从format参数后面开始
    //cnt代表输出了多少个字符
    int cnt = 0;
    for (int i = 0; format[i]; i++) {//这里中间条件用到了format[i],当format[i] = '\0'时表示循环结束
        switch (format[i]) {
            //如果当前字符是%,那么就需要对下个字符进行特殊处理
            case '%': {
                switch (format[i + 1]) {
                    //当有两个%时,那就需要打印一个%
                    case '%': {
                        PUTC(format[i + 1]);
                        //对于下个位置已经处理所以需要i+1
                        i++;
                    } break;
                    //%后接s那么就是字符串的格式占位符
                    //然后这里就需要用到变参列表的解析
                    case 's': {
                        //获取变参列表的参数,并且该参数的类型为char *类型
                        const char *s = va_arg(args, const char *);
                        //获取到字符串后,进行打印字符串
                        for (int j = 0; s[j]; j++) PUTC(s[j]);
                        //s这个字符被处理掉了,不需要打印了,位置需要往后移
                        i++;
                    } break;
                    //%后接d那么就是整形的格式占位符
                    case 'd': {
                        //获取变参列表的参数,并且该参数的类型为char *类型
                        const int num = va_arg(args, const int);
                        //这里就需要率到如何进行把每一位数字进行输出
                        //因为putchar只能打印单个字符
                        //那么就用数组将数字进行存储起来
                        int8_t arr[20];//int8_t表示只有8位带符号的整形数字,只占8bit位,头文件<inttype.h>
                        //现在进行对num数字每位进行存储在数组中
                        int n = num, ind = 0;
                        if (n < 0) PUTC('-');//n为负数时需要输出负号
                        do {
                            //从个位进行每位存储在数组中
                            arr[ind++] = n % 10;
                            n /= 10;
                        } while(n);//因为n = 0不会进入循环,那么就无法进行输出,所以使用do while循环先执行一次
                        //因为个位在第一位,所以需要倒过来输出
                        for (; ind > 0; ind--) {
                            //ind - 1是因为,当前ind位置是空的,最高位在ind - 1上
                            //当num为负数时需要,将他变为正数进行输出
                            if (num < 0) PUTC(-arr[ind - 1] + '0');
                            else PUTC(arr[ind - 1] + '0');
                        }
                        i++;//与之前的操作同理
                    }
                }
            } break;
            default : PUTC(format[i]); break;
        }
        //putchar() 是向屏幕上打印一个字符
    }
    return cnt;
}

int main() {
    //测试printf和my_printf输出hello world
    TEST("hello world\n");
    //对于printf%%输出就是一个%
    //由于printf对%是特殊处理,那么对于my_printf也就需要特殊处理
    TEST("100%%\n");
    TEST("%s\n", "hello world 100 %%");
    int a = 123;
    TEST("a = %d\n", a);
    a = 0;
    TEST("a = %d\n", a);
    a = INT_MAX;
    TEST("a = %d\n", a);
    a = INT_MIN;
    TEST("a = %d\n", a);
    return 0;
}

执行结果:

这里我只截取了关于实现%d输出功能的结果

可以发现我们实现的my_printf对于正数,负数,0都可以输出

第五步实现%x输出功能:

#include <stdio.h>
#include <inttypes.h>
#include <stdarg.h>
#include <math.h>
#include <limits.h>

//这个宏定义是测试printf和my_printf区别
#define TEST(format, args...) {\
    int n1, n2;\
    n1 = printf(format, ##args);\
    n2 = my_printf(format, ##args);\
    printf("n1 = %d, n2 = %d\n", n1, n2);\
}

char get_16_code(int n) {
    //当这一位小于10,在16进制中还是用数字表示
    if (n < 10) return n + '0';
    //当这一位大于10,在16进制中需要用字母表示
    //a 10, b 11, c 12, d 13, e 14, f 15
    return n - 10 + 'a';
}

int my_printf(const char *format, ...) {
    #define PUTC(c) putchar(c), cnt += 1
    va_list args;//args表示变参列表
    va_start(args, format);//变参列表从format参数后面开始
    //cnt代表输出了多少个字符
    int cnt = 0;
    for (int i = 0; format[i]; i++) {//这里中间条件用到了format[i],当format[i] = '\0'时表示循环结束
        //putchar() 是向屏幕上打印一个字符
        switch (format[i]) {
            //如果当前字符是%,那么就需要对下个字符进行特殊处理
            case '%': {
                switch (format[i + 1]) {
                    //当有两个%时,那就需要打印一个%
                    case '%': {
                        PUTC(format[i + 1]);
                        //对于下个位置已经处理所以需要i+1
                        i++;
                    } break;
                    //%后接s那么就是字符串的格式占位符
                    //然后这里就需要用到变参列表的解析
                    case 's': {
                        //获取变参列表的参数,并且该参数的类型为char *类型
                        const char *s = va_arg(args, const char *);
                        //获取到字符串后,进行打印字符串
                        for (int j = 0; s[j]; j++) PUTC(s[j]);
                        //s这个字符被处理掉了,不需要打印了,位置需要往后移
                        i++;
                    } break;
                    //%后接d那么就是整形的格式占位符
                    case 'd': {
                        //获取变参列表的参数,并且该参数的类型为char *类型
                        const int num = va_arg(args, const int);
                        //这里就需要率到如何进行把每一位数字进行输出
                        //因为putchar只能打印单个字符
                        //那么就用数组将数字进行存储起来
                        int8_t arr[20];//int8_t表示只有8位带符号的整形数字,只占8bit位,头文件<inttype.h>
                        //现在进行对num数字每位进行存储在数组中
                        int n = num, ind = 0;
                        if (n < 0) PUTC('-');//n为负数时需要输出负号
                        do {
                            //从个位进行每位存储在数组中
                            arr[ind++] = n % 10;
                            n /= 10;
                        } while(n);//因为n = 0不会进入循环,那么就无法进行输出,所以使用do while循环先执行一次
                        //因为个位在第一位,所以需要倒过来输出
                        for (; ind > 0; ind--) {
                            //ind - 1是因为,当前ind位置是空的,最高位在ind - 1上
                            //当num为负数时需要,将他变为正数进行输出
                            if (num < 0) PUTC(-arr[ind - 1] + '0');
                            else PUTC(arr[ind - 1] + '0');
                        }
                        i++;//与之前的操作同理
                    } break;
                    case 'x': {
                        //因为十六进制输出是不带符号的,所以需要用到无符号整形
                        unsigned int num = va_arg(args, unsigned int);
                        int8_t arr[20], ind = 0;
                        do {
                            //因为需要转换为16进制,所以需要对16进行取余
                            arr[ind++] = num % 16;
                            num /= 16;
                        } while(num);
                        for (; ind > 0; ind--) {
                            //实现一个方法将10进制转为16进制
                            PUTC(get_16_code(arr[ind - 1]));
                        }
                        i++;//同理
                    } break;
                }
            } break;
            default : PUTC(format[i]); break;
        }
    }
    return cnt;
}

int main() {
    //测试printf和my_printf输出hello world
    TEST("hello world\n");
    //对于printf%%输出就是一个%
    //由于printf对%是特殊处理,那么对于my_printf也就需要特殊处理
    TEST("100%%\n");
    TEST("%s\n", "hello world 100 %%");
    int a = 123;
    TEST("a = %d\n", a);
    a = 0;
    TEST("a = %d\n", a);
    a = INT_MAX;
    TEST("a = %d\n", a);
    a = INT_MIN;
    TEST("a = %d\n", a);
    TEST("123 = %x\n", 123);
    TEST("-1 = %x\n", -1);
    TEST("INT_MAX = %x\n", INT_MAX);
    TEST("INT_MIN = %x\n", INT_MIN);
    return 0;
}

执行结果:

总结:

        对于printf的功能,肯定没有实现完整,但是对于常用的用法都是实现了,在没有实现的用法,你可以下去自己尝试去实现那些功能.

本章小结:

        对于标准输出和输入在本章有了新的认识和理解,对于scanf和printf函数也有了新的认识.

        在最后的实现printf函数,看完课程后跟着船长实现了一遍,然后在自己通过自己的想法再来实现一遍,这样更加巩固了你所学的知识.

        最后加油,看最后加油,看到这里你已经超过百分之95的人了。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1546776.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

AI论文速读 | 具有时间动态的路网语义增强表示学习

论文标题&#xff1a; Semantic-Enhanced Representation Learning for Road Networks with Temporal Dynamics 作者&#xff1a; Yile Chen&#xff08;陈亦乐&#xff09; ; Xiucheng Li&#xff08;李修成&#xff09;; Gao Cong&#xff08;丛高&#xff09; ; Zhifeng Ba…

深入探讨iOS开发:从创建第一个iOS程序到纯代码实现全面解析

iOS开发作为移动应用开发的重要领域之一&#xff0c;对于开发人员具有重要意义。本文将深入探讨iOS开发的各个方面&#xff0c;从创建第一个iOS程序到纯代码实现iOS开发&#xff0c;带领读者全面了解iOS应用程序的开发流程和技术要点。 &#x1f4f1; 第一个iOS程序 在创建第…

第1章 实时3D渲染流水线

前言 本书所剖析的Unity 3D内置着色器代码版本是2017.2.0f3&#xff0c;读者可以从Unity 3D官网下载这些着色器代码。这些代码以名为builtin_shaders-2017.2.0f3.zip的压缩包的形式提供&#xff0c;解压缩后&#xff0c;内有4个目录和1个license.txt文件。 目录CGIncludes存放了…

【系统架构师】-基础知识整理

1、面向对象设计得四种关系 关系类型概念特点例子关联关系表示不同类的对象之间有联系&#xff0c;但是一方并不完全拥有另一方&#xff0c;也不对其生命周期负责。关联关系可以是单向的也可以是双向的。耦合度高通常用来表示不同类的对象之间的联系&#xff0c;如“使用”或“…

Kafka消费者:监听模式VS主动拉取,哪种更适合你?

欢迎来到我的博客&#xff0c;代码的世界里&#xff0c;每一行都是一个故事 Kafka消费者&#xff1a;监听模式VS主动拉取&#xff0c;哪种更适合你&#xff1f; 前言监听模式的实现监听器&#xff08;Listener&#xff09;的概念和作用使用监听器实现 Kafka 消费者的步骤和方法…

DDoS攻击升级,解读防御DDoS攻击的几大有效方法

前不久&#xff0c;Gcore发布了2023年第三、四季度DDoS攻击趋势报告&#xff0c;报告中指出DDoS攻击的规模以及复杂性持续增长&#xff0c;且这种增长是触目惊心的。全球每天大约发生23000次DDoS攻击&#xff0c;每39秒就会发生一次新的网络攻击&#xff0c;电信公司、政府部门…

javaSwing连连看游戏

一、简介 基于java的连连看游戏设计和实现&#xff0c;基本功能包括&#xff1a;消除模块&#xff0c;重新开始模块&#xff0c;刷新模块&#xff0c;选择难度模块&#xff0c;计时模块。本系统结构如下&#xff1a; &#xff08;1&#xff09;消除模块&#xff1a; 完成连连…

【MATLAB源码-第13期】基于matlab的4ASK的误码率BER和误符号率SER理论和实际对比仿真。

操作环境&#xff1a; MATLAB 2022a 1、算法描述 "4ASK" 是一种数字调制技术&#xff0c;代表4级振幅移移键控&#xff08;4-Level Amplitude Shift Keying&#xff09;调制。它是一种数字通信中常用的调制方式之一&#xff0c;用于将数字信号转换为模拟信号以便传…

map china not exists. the geojson of the map must be provided.

map china not exists. the geojson of the map must be provided. 场景&#xff1a;引入echarts地图报错map china not exists. the geojson of the map must be provided. 原因&#xff1a; echarts版本过高&#xff0c;ECharts 之前提供下载的矢量地图数据来自第三方&…

小白学视觉 | 图像上的 OpenCV 算术运算

本文来源公众号“小白学视觉”&#xff0c;仅用于学术分享&#xff0c;侵权删&#xff0c;干货满满。 原文链接&#xff1a;图像上的 OpenCV 算术运算 1 OpenCV 简介 图像可以进行算术运算&#xff0c;例如加法、减法和按位运算&#xff08;AND、OR、NOT、XOR&#xff09;。…

模拟器App抓包 - 证书双向验证绕过手段

希望和各位大佬一起学习&#xff0c;如果文章内容有错请多多指正&#xff0c;谢谢&#xff01; 个人博客链接&#xff1a;CH4SER的个人BLOG – Welcome To Ch4sers Blog 0x00 Frida 环境配置 1. 本地安装 Frida pip install frida pip install frida-tools2. 模拟器安装 Fr…

【详细讲解yarn的安装和使用】

&#x1f308;个人主页:程序员不想敲代码啊&#x1f308; &#x1f3c6;CSDN优质创作者&#xff0c;CSDN实力新星&#xff0c;CSDN博客专家&#x1f3c6; &#x1f44d;点赞⭐评论⭐收藏 &#x1f91d;希望本文对您有所裨益&#xff0c;如有不足之处&#xff0c;欢迎在评论区提…

leetcode 15.三数之和 JAVA 双指针法

题目 思路 双指针法 去重 为啥要去重呢&#xff1f;因为题目中说了要返回不重复的三元组。拿示例1来看&#xff0c;&#xff08;-1&#xff0c;0&#xff0c;1&#xff09;和&#xff08;0&#xff0c;1&#xff0c;-1&#xff09;虽然都等于0&#xff0c;但其实它们里面的数…

Unix环境高级编程-学习-08-自旋锁与屏障

目录 一、多线程相关文章链接 二、自由抒发 1、自旋锁 2、屏障 三、函数介绍 1、pthread_spin_init &#xff08;1&#xff09;声明 &#xff08;2&#xff09;作用 &#xff08;3&#xff09;参数 &#xff08;4&#xff09;返回值 &#xff08;5&#xff09;注意点 …

c语言文件操作(下)

目录 1.文件的随机读写1.1 fseek1.2 ftell1.3 rewind 2. 文件结束的判定2.1 文本文件读取结束的判断2.2 二进制文件读取结束的判断 3. 文件缓冲区 1.文件的随机读写 1.1 fseek 根据⽂件指针的位置和偏移量来定位⽂件指针。 函数原型&#xff1a; int fseek (FILE * stream,…

Python篇之网络编程,实现简单的服务端和客户端的内容传输

本小节内容&#xff1a;实现简单的信息交流 文章目录 一、 Socket介绍二、客户端与服务端三、在python中实现网络通信1. 服务端2. 客户端3. 连接测试 一、 Socket介绍 socket (简称 套接字) 模块是其内置的标准库之一&#xff0c;它实现了BSD sockets API&#xff0c;允许开发…

(分享)一个图片添加水印的小demo的页面,可自定义样式

有时候想给某张图片添加一个自己的水印&#xff0c;但是又懒的下载相应软件&#xff0c;用js canvas制作一个静态页面&#xff0c;对于单张图片添加自定义文字水印&#xff0c;大小 间距&#xff0c;角度可调。 页面如下&#xff1a; 选择图片&#xff0c;设置相应参数&#x…

深度学习模型部署(十二)CUDA编程-绪

CUDA 运行时 API 与 CUDA 驱动 API 速度没有差别&#xff0c;实际中使用运行时 API 较多&#xff0c;运行时 API 是在驱动 API 上的一层封装。​ CUDA 是什么&#xff1f;​ CUDA(Compute Unified Device Architecture) 是 nvidia 推出的一个通用并行技术架构&#xff0c;用它…

【LLM】大模型推理加速 KV-Cache

目录 模型推理过程KV Cache原理KV Cache的存储 模型推理过程 在了解KVCache之前&#xff0c;我们需要知道Transformer类大模型的推理过程。 对于LLM进行一次前向传播也就是生成一个token的过程可以被分解成以下步骤&#xff1a; 文本 T i n p u t T_{input} Tinput​经过Toke…

数据结构与算法分析引论1

1.解决问题的算法有很多&#xff0c;但是在输入不同的情况下&#xff0c;不同算法之间的差异也很大&#xff0c;我们总是追求一个更快、更有效的方法。比如说普通的依次查找和二分查找&#xff0c;两者的差异就很大。我们使用大O表示法来表示算法的速度。依次查找就是O(n)&…