博客

  • Day3-字符串和格式化输入输出

    1. 字符串

    字符串是一个或多个字符的序列。双引号不是字符串的一部分,它的作用仅是告诉编译器它括起来的内容是字符串。

    1.1 char类型数组和null字符

    字符串末尾的\0是空字符,C语言用它标记字符串的结束,其ASCII码值是0。C语言中字符串一定以空字符结尾,因此char数组一定要比带存储字符串的字符数多1。

    数组是同类型数据元素的有序序列。

    1.2 使用字符串

    sizeof以字节为单位给出对象的大小,strlen给出字符串中的字符长度。虽然1字节存储1字符,但是并不能将两者混用。

    假设char[40] name存储字符串“Caldm”,sizeof返回的值是40,而strlen返回的值是5。即使直接传递字符串字面量,sizeof的结果也会比strlen的值大,因为sizeof把字符串末尾不可见的空字符\0也计算在内了。

    2. 常量和C预处理器

    为什么符号常量更好?

    • 常量名比数字表达的信息更多
    • 当程序中多处使用常量,且需要更改常量时,使用符号常量只需要修改符号常量的定义,不用再程序中逐一修改

    如何创建符号常量?

    方法一:声明一个变量,然后将变量修改为所需的常量。
    这样做依然可能在程序运行过程中修改它的值,更好的做法是使用C预处理器

    方法二:使用C预处理器 #define 常量名 常量值

    命名规则:

    • 常量名应当采用全大写字母+下划线连接
    • 也可在名称前带c_k_前缀来表示常量(比较少见)

    2.1 const限定符

    const关键字(C90新增)用于限定一个变量为只读(在C语言中,使用const类型限定符声明的是变量,不是常量)。

    2.2 符号常量

    C头文件limits.hfloat.h分别提供了整数类型和浮点数类型大小限制相关的详细信息。每个头文件都提供了一系列供实现使用的符号常量。

    3. printf()scanf()

    printf()scanf()是输入/输出函数,简称I/O函数。C最开始吧输入/输出留给编译器的实现者,但C90和C99标准规定了这些函数的标准版本。

    3.1 printf()函数

    printf()函数打印数据的指令要与待打印数据的类型相匹配,例如%d打印整数,%f打印单精度浮点数(float),这些符号被称为转换说明(conversion specification),它们指定了如何把数据转换成可显示的形式。

    printf()的标记

    标记意义
    -待打印项左对齐
    +显示符号,正数显示+,负数显示-
    空格前导填充空格
    #把结果转换为另一种格式。如果是%o格式,则以0开始,%x%X格式,则以0x0X开始;对于所有浮点格式,#保证即使没有小数部分,也将打印一个小数点字符;对于%g%G,防止结果后面的0倍删除
    0对于数值格式,用前导0填充字段宽度;对于整数格式,如果出现-标记或指定精度,则虎落该标记

    printf()的修饰符

    修饰符意义
    标记可以不使用标记或使用多个标记
    数字最小字段宽度。
    如果字段小于指定宽度,则会进行填充,填充内容受标记影响,默认为空格;
    如果字段大于指定宽度,则使用能完整显示的最小宽度
    .数字精度。
    对于%e%E%f,表示小数点右边数字的位数
    对于%g%G转换,表示有效数字的最大位数
    对于%s转换,表示待打印字符的最大数量
    对于整型转换,表示待打印数字的最小位数
    如有必要,使用前导0来达到这个位数
    ..0相同
    h和整型转换说明一起使用,表示short intunsigned short int类型的值
    hh和整型转换说明一起使用,表示signed charunsigned char类型的值
    j和整型转换说明一起使用,表示intmax_tuintmax_t类型的值,这些类型定义在stdint.h
    l和整型转换说明一起使用,表示long intunsigned long int类型的值
    和浮点转换说明一起使用,表示double long类型的值
    ll和整型转换说明一起使用,表示long long intunsigned long long int类型的值(C99)
    t和整型转换说明一起使用,表示ptrdiff_t类型的值,ptrdiff_t是两个指针差值的类型(C99)
    z和整型转换说明一起使用,表示size_t类型的值。size_tsizeof返回的类型(C99)

    3.2 使用scanf()

    scanf()函数使用指向变量的指针,不过这里先不写指针方面的内容。只需要记住:

    1. 如果用scanf()读取基本变量类型的值,需要在变量名前加一个&
    2. 如果用scanf()吧字符串读入字符数组中,不要使用&

    ANSI C中的scanf()的转换说明

    转换说明含义
    %c把输入解释成字符
    %d把输入解释成有符号的十进制整数
    %e%f%g%a
    %E%F%G%A
    把输入解释成浮点数(C99标准新增了%a%A
    %i把输入解释成有符号十进制整数
    %o把输入解释成有符号八进制整数
    %p把输入解释成指针(地址)
    %s把输入解释成字符串,从第1个非空白字符开始,到下一个非空白之前的所有字符都是输入
    %u把输入解释成无符号十进制整数
    %x%X把输入解释成有符号十六进制整数

    可以在转换说明中使用修饰符。若要使用多个修饰符,则必须按表中顺序书写

    转换说明含义
    *抑制赋值
    数字最大字段宽度。输入达到最大字段宽度处,或第1次遇到空白字符时停止
    hh把整数作为signed charunsigned char类型读取
    ll把整数作为long longunsigned long long类型读取(C99新增)
    hlL%hd%hi表明把对应的值储存为short int类型
    %ho%hx%hu表明把对应的值储存为unsigned short int类型
    %ld%li表明把对应的值储存为long类型
    %lo%lx%lu表明把对应的值储存为unsigned long类型
    %le%lf%lg表明把对应的值储存为double类型
    efg前面使用L,表明把对应的值储存为long double类型,如果没有修饰符,diox表明把对应的值储存为int类型,fg表明把对应的值储存为float类型
    j在整型转换说明后面时,表明使用intmax_tuintmax_t类型(C99新增)
    z在整型转换说明后面时,表明使用sizeof的返回类型(C99新增)
    t在整型转换说明后面时,表明使用两个指针差值的类型(C99新增)

    3.2.1 从scanf()角度看输入

    假设scanf()根据一个%d转换说明读取一个整数,那它会先读取第一个非空白字符,如果该字符是数字或符号,便存下该字符,继续读取下一个字符,直到遇到非数字字符,此时scanf()会将非数字字符放回输入,这样程序下一次读取输入时,会从被放回的这个字符开始读取。

    如果使用字段宽度,那么则在字段结尾或第1个空白字符处停止读取。

    如果遇到的第一个非空白字符不是数字,比如'A',那么会不赋值给变量,如果scanf()中全部是%d,那么读取就会一直卡在字符'A'上,无法越过。

    3.2.2 格式字符串中的普通字符

    scanf()函数允许吧普通字符放在格式字符串中。除空格字符外的普通字符必须与输入字符串严格匹配。

    scanf("%d,%d", &n, &m);
    

    scanf()函数将其解释为用户将输入一个数字、一个逗号和一个数字。也就是说用户必须用逗号分隔输入的两个数字。

    格式字符串中的空格意味着跳过下一个输入项前面的所有空白,这包括“没有空白”的情况。

    3.2.3 scanf()返回值

    scanf()返回成功读取的项数

    3.3 printf()scanf()*修饰符

    printf()中使用*修饰符来代替字段宽度,可以通过它让程序来指定字段宽度,而不需要你事先预设。这点同样可以应用于浮点值指定精度和字段宽度。

    #include <stdio.h>
    int main(void) {
        unsigned width, precision;
        int number = 256;
        double weight = 242.5;
        
        printf("Enter a field width:\n");
        scanf("%d", &width);
        printf("The number is : %*d\n", width, number);
        printf("Now there a width and a precision:\n");
        scanf("%d %d", &width, &precision);
        printf("Weight = %*.*f\n", width, precision, weight);
        printf("Done!\n");
        return 0;
    }
    

    scanf()中,把*放在%和转换字符之间时,会使得scanf()跳过相应的输出项。

    #include <stdio.h>
    int main(void) {
        int n;
        printf("Please enter three integers:\n");
        scanf("%*d %*d %d", &n);
        printf("The last integer was %d\n", n);
        return 0;
    }
    
  • DAY-2 处理数据

    C++命名规则

    • 名称中只能使用字母数字下划线_)。
    • 名称的第一个字符不能是数字
    • 字符区分大小写
    • 不能使用C++关键字作为名称。
    • 以两个下划线或以下划线和大写字母开头的名称被保留给实现使用。以一个下划线开头的名称被保留给实现,作为全局标识符。
    • C++对名称的长度没有限制,名称中所有的字符都有意义,但有些平台有长度限制

    基本数据类型

    基本数据类型主要有两大类:整型浮点型。整型中主要有shortintlonglong long,这些都是带符号类型,能够表示正负,在这些类型前加unsigned就是无符号类型,unsigned shortunsigned int(或unsigned)、unsigned longunsigned long long

    浮点型主要有三类,分别是floatdoublelong double(C90新增)

    整型字面量的进制表示

    进制表示方式
    二进制前两位为 0b0B
    八进制第一位数字为 0,第二位数字为 1~7
    十进制第一位数字为 0~9
    十六进制前两位为 0x0X

    C++如何确定常量的类型

    对于十进制字面值,C++从intlonglong long中选择能存储该常量的最小类型

    对于八进制十六进制字面值,C++会从intunsigned intlongunsigned longlonglong longunsigned long long中选择能存储该常量的最小类型

    char 类型

    char在默认情况下既不是没有符号,也不是有符号。是否有符号由C++实现决定。

    如果将char看做数值类型,那么char是否有符号的差异就比较重要了。

    signed char能表示-128到127,而unsigned char能表示0到255

    printf转换符

    转换符意义
    a, A十六进制形式输出浮点数(C99 新增)。
    x, X十六进制形式输出无符号整数(不输出前缀Ox)
    d十进制形式输出带符号整数(正数不输出符号)
    u以十进制形式输出无符号整数
    o八进制形式输出无符号整数(不输出前缀0)
    f小数形式输出单、双精度实数
    e, E指数形式输出单、双精度实数
    g, G%f%e中较短的输出宽度输出单、双精度实数
    lu32位无符号整数
    llu64位无符号整数
    跟形式有关的
    转换符意义
    c输出单个字符
    s输出字符串
    p输出指针地址
    不是数字类型的
  • DAY-1 开始学习C++

    总结

    C++程序是由一个或多个被称为函数的模块组成的。

    程序从main()函数开始执行,因此该函数必不可少。

    函数由函数头函数体组成。

    • 函数头指出函数返回值的类型
    • 函数期望通过参数传递给它的信息的类型。

    函数体由一对花括号({})中的C++语句组成

    C++语句种类:

    • 声明语句:定义函数中使用变量的名称和类型
    • 赋值语句:使用赋值运算符(=)给变量赋值
    • 消息语句:将消息发送给对象,激发某种行动
    • 函数调用:执行函数。被调用的函数执行完毕后,程序返回到函数调用语句后面的语句
    • 函数原型:声明函数的返回类型,函数接受的参数数量和类型
    • 返回语句:将一个值从被调用的函数那里返回到调用函数中

    练习

    1. C++程序的模块叫作什么?%% 函数 %%
    2. 下面的预处理器指令是做什么用的?
      #include <iostream>
      答:iostream是C++程序中的预处理器指令,该指令的作用是将头文件iostream的内容包含到该指令所在的位置。
    3. 下面的语句是做什么用的?
      using namespace std;
      答:这是一条using指令,也叫命名空间指令。它指示编译器,在此指令之后的作用域内,若遇到没有明确指定命名空间的名称,则默认到std命名空间中查找。
    4. 什么语句可以用来打印短语“Hello, World”,然后开始新的一行?
      答:cout << "Hello, World" << endl;
    5. 什么语句可以用来创建名为cheeses的整数变量?
      答:使用声明语句,int cheeses;
    6. 什么语句可以将32赋值给变量cheeses中?
      答:使用赋值语句,cheeses = 32;
    7. 什么语句可以用来将从键盘输入的值读入变量cheeses中?
      答:cin >> cheeses;
    8. 什么语句可以用来打印“We have X varieties of cheese.”,其中X为变量cheeses的值。
      答:cout << "We have " << cheeses << " varieties of cheese.";
    9. 下面的函数原型指出了关于函数的哪些信息?
      int froop(double t);
      void rattle(int n);
      int prune(void);
      答:int froop(double t);中指出了froop函数返回一个int类型的值,该函数接受一个double类型的参数;void rattle(int n);中指出了rattle函数没有返回值,该函数接受一个int类型的参数;int prune(void);中指出了该函数返回一个int类型的值,同时该函数不接受参数。
    10. 定义函数时,在什么情况下不必使用关键字return
      答:当函数的返回类型是void时,函数体内可以不使用return语句。
    11. 假设您编写的main()函数包含如下代码: cout << "Please enter your PIN: "; 而编译器指出cout是一个未知标识符。导致这种问题的原因很可能是什么?指出3种修复这种问题的方法。
      答:导致问题的原因很可能是没有使用using指令,其次可能是为使用未使用预处理器编译指令包含头文件iostream
      修复方法:
    • 若包含头文件iostream,则在函数内部添加using namespace std;
    • 若包含头文件iostream,则在全局添加using namespace std;
    • 修改原代码为std::cout << "Please enter your PIN: ";
  • 存储数据与展示数据不同时的处理方法

    在开发表单中,常常遇到存储的表单数据与显示给用户的内容不一致的情况。

    例如一个多选组件,表单数据中存储的是选择项的id,但是显示给用户的却是选择项的名称。

    对于这种情况,有两种处理方法。

    第一种是使用计算属性显示

    根据存储的数据id,查找对应的名称,再先是到表单上。

    使用的是计算属性,要确保不能修改它。

    如果要将名称显示到输入框组件上,可以加上disabled防止用户修改它。

    第二个是使用查找方法,实时查找

    编写一个根据id查找名称的方法,然后在渲染过程中使用它,类似:

    <ul>
      <li>{{getNameById(item.id)</li>
    </ul>

  • 《蛊真人》之谢晗沫

    在第一次看蛊的时候,方源在乐土洞天中提到谢晗沫这个名字,我瞬间联想到自己看过的另一篇文章。

    文章的标题已经记不得了,但情节是地震下,一位母亲与她刚出生几个月的婴儿被掩埋在废墟下,婴儿又渴又饿就要死了,于是这位母亲用自己的唾液喂他,最后救援队发现二人,只有婴儿活了下来。

    (我写日记时又去搜了这篇文章确认了下,不是喂的唾液,而是母乳和鲜血。文章的名字是“母爱短信”,汶川地震时的文章,但是却也有人说这篇文章是虚构的。)

    当时之所以会想到那篇文章,应该是将“晗”联想到“含”,“沫”联想到“唾液”了。

    (不过联想到唾液是不是有点恶心啊。而且小说中谢晗沫是一名鲛人,类似美人鱼,硬要联想的话,不应该将“沫”联想到海浪冲刷时产生的泡沫吗,而且童话故事小美人鱼的结局,也是小美人鱼也是走到海里,变成了泡沫。)

    不管总之是怎么联想的,当谢晗沫这个名字一出现的时候,这个人物就瞬间与母爱、善良、伟大联系在一起了。

    尤其是作者在前面的一千多章里多处铺垫方源的艰辛,遇到的所有人都在利用他,更主要的是方源亲口承认谢晗沫是自己的挚爱的时候,就更加觉得谢晗沫一定是一个好人了。

    最终给我的感受就是谢晗沫这个角色,虽然只是出现了一个名字,但是人物却是活起来了一般。

    遗憾的是小说中并没有写方源和谢晗沫之间的爱情故事,而谢晗沫做的事情,也只写了彻查寒潮族长贪腐那一段,即使是在末尾,谢晗沫也只是在心里感慨一句,“方源他,是知我的。”

    感慨完情节,来研究一下名字。

    “谢”,之前的“晗沫”二字让我联想到“母爱短信”这篇文章,“谢”这个字增添了一种“感恩”、“感激”的意思。

    “晗”,可拆分为日、今、口,日对月,今对古,口对圆,而方源的全名正好是古月方源,正好对应方源的名字。

    “沫”,这让我想到泡沫、短暂、绚烂,在小说中谢晗沫的戏份不多,在两千多章节中,出现谢晗沫的章节不到十五章,并且这不到十五章中,每一章写到谢晗沫的也只有一小部分,对比全文的内容量来说,对读者来说,谢晗沫的出场、退场都是短暂的。

    但谢晗沫也是绚烂的,在重新选拔鲛人圣女的最后比拼歌舞的环节,谢晗沫和方源成为全场所有人视线的焦点,谢晗沫从方源的三首曲子,《白月光》、《水调歌头》、《沧海一声笑》中了解方源,认为方源是与自己同类的人,是知己的。

    而方源是畅快的,遇到谢涵沫时,方源已经活了三百多岁了,三百多年来,他一直遭遇挫折困顿,心中继续了太多的郁气,以至于在最开始陷入黑油之中,即将死亡时,他的内心也十分平静,甚至带着一丝放松,觉得自己终于可以休息了,永远地休息了,他穿越到蛊界三百多年,过得太苦太累了。

    在最后一首《沧海一声笑》中,方源意气风发,心中积蓄的郁气一扫而空。

    这里引用一段原文:

    我在世俗红尘中摸爬滚打,我出世我入世。我过着我自己的生活,我按照我的心意活着,哪怕浪潮颠簸得我起起伏伏、上上下下、生生死死,我也从不感到委屈哀怨惧怕担忧,我品味此中滋味,我仍旧会痴痴笑笑。

    我有真性情。

    我是真人!

    我觉得“泡沫”这个意象也同样代表这方源与谢晗沫这段爱情的结局,童话故事中小美人鱼走进海中变成了泡沫。在小说中,谢晗沫是鲛人,而且是鲛人圣庭的圣女,方源是人族,普通的鲛人与异族通婚都会成为两族合理打压的对象,更别说谢晗沫还是圣女了,并且方源遇到谢晗沫时,方源的实力低微,只有三转级别。

    所以最后的结局要么是谢晗沫不得不与方源分别,或者是谢晗沫与方源私奔,然后被鲛人和人族追杀,谢晗沫或被拘拿或被杀死,而方源也在东海待不下去,去到西漠。