Giter Site home page Giter Site logo

lcthw's Introduction

LCTHW (Learn C The Hard Way)

我的C语言学习之路

学习环境: Ubuntu 19.04 系统及其自带 gedit 文本编辑器和 Terminal

参考资料:《Learn C The Hard Way》及其中文版《笨办法学C语言》

在 Terminal 中批量将 ex1-9.c 重命名为 ex01-09.c:rename 's/ex/ex0/' ex?.c

日志

  • 2019.9
    • 9.21 开启学习项目
    • 9.22 创建 repo
    • 9.30 完成 ex 1 - 16
  • 2019.10
    • 10.7 完成 ex 1 - 16 复习和笔记整理
    • 项目暂停了,有空再会 :P

笔记目录

ex01 取出尘封的编译器

  • 包含头文件#include <stdio.h>
  • main函数,使用puts打印一行字
  • 在 Terminal 中构建make ex01并运行./ex01程序
  • 删除已构建的程序rm ex01
  • 在 Terminal 中使用man阅读函数文档

ex02 现在 make 就是你的 python

使用 Makefile:

  • 批量(以显示所有警告的方式)构建
  • 批量删除

ex03 格式化打印

  • 声明变量并初始化type name = value;
  • 使用printf打印格式化字符串
  • 格式化占位符%和转义序列\

ex04 引入 Valgrind

  • 使用valgrind ./ex04运行并 debug 程序

ex05 C程序的结构

分解代码并说明每一个部分的作用:

  • include将一个文件的内容导入到这个文件
  • .h头文件中有可供使用的函数们
  • 两种注释方式:// .../* ... */
  • main函数各个部分:
    • int返回值类型
    • (int argc, char *argv[])接收的两个参数
    • {}任何函数的开头和结尾
    • return 0;返回语句
  • 变量声明和初始化
  • printf函数可以带可变数量个参数

ex06 变量类型

类型 声明 格式化占位符
整数 int name %d
浮点数 float/double name %f
字符(单引号) char name %c
字符串/字符数组(双引号) char name[] %s

ex07 更多变量 一些算术

类型 声明 格式化占位符 范围
长整数 long name %ld - 2 ^ 63 ~ 2 ^ 63 - 1
无符号长整数 unsigned long name %lu 0 ~ 2 ^ 64 - 1
  • %e以科学计数法的形式打印
  • \0空字符:
    • 可与一个数相乘得到\0
    • %c什么也不打印
    • %d打印数字0
    • %sTerminal 会有 Warning,打印(null)
  • %% 打印百分号

ex08 大小和数组

  • 在C语言中,字符串就是字符数组
  • 声明数组并初始化type name[] = {..., ..., ...}
  • 字符串/字符数组初始化后,其末尾会自动添加一个空字符\0
  • 字符串/字符数组还可以这样简便地初始化char name[] = "...";
  • sizeof函数:
    • 返回typename所占内存字节数
    • 可用\ld\lu打印
    • int的大小为 4,char的大小为 1
    • 数组大小为其单个元素大小乘以元素个数
    • 字符串/字符数组使用第二种初始化的方式,其大小会加 1,可能是算上了自动加上的空字符\0,但使用第一种初始化的方式就不会加 1,为什么呢?
  • 数组name的第 n+1 项name[n],n 从 0 开始
  • 如果 n+1 超出了数组长度,name[n]随机返回一个值
  • 可以用name[n] = value;为数组第 n+1 个元素重新赋值
  • \"打印引号

ex09 数组和字符串

  • 初始化长度为 n 的数组type name[n] = {...};, 未指定的元素默认初始化为数字0或空字符\0
  • 又一种初始化字符串/字符数组的方法:使用指针type *name = "...";,但是里面的字符/元素无法被重新赋值
  • 将指定长度字符串的最后一个字符初始化为\0以外的字符,或将字符串末尾空字符\0重新赋值为其他字符会产生 bug

ex10 字符串数组 循环

  • main函数接收的两个参数:
    • argc是运行程序时用户输入的字符串个数
    • argv是字符串数组,储存用户输入的字符串们
    • argv的第一个元素argv[0]"./ex10"
  • for循环:
for(INITIALIZER; TEST; INCREMENTER) {
CODE;
}
  • 自增语句i++相当于i = i + 1i--则是自减
  • 声明字符串数组并初始化char *name[] = {"...", "...", ...};,其中的元素可被重新赋值
  • 未设置或无效的指针NULL赋值给字符串数组中的一个元素,打印(null)

ex11 while 循环和布尔表达式

  • 在 C 语言中没有真正的“布尔”类型,0 代表 false,其他值代表true
  • while循环:
while(TEST) {
CODE;
}
  • 应优先选择for循环,因为while循环需要额外写初始化语句并让 i 增加,容易出错

ex12 if, else if, else

  • if语句:
if(TEST) {
CODE;
} [else if(TEST) {
CODE;
} else {
CODE;
}]
  • 布尔运算符:
符号 含义 符号 含义 符号 含义
== 等于 < 小于 &&
!= 不等于 >= 大于等于 ||
> 大于 <= 小于等于 !
  • 提前终止循环break;

ex13 switch 语句

  • 非正常终止程序的返回语句return 1;
  • switch语句:
switch(SOMETHING) {
	case ONE_THING:
		CODE;
		break;
	[case SECOND_THING: // fallthrough
	case THIRD_THING:
		CODE;
		break;
	...]
	default:
		CODE;
}
  • 如果能够简化,用if语句替代
  • ASCII 码:
字符 ASCII 码
(space) 32
0~9 48 ~ 57
A~Z 65 ~ 90
a~z 97 ~ 122
  • 转换大小写:直接让字符减去或加上 32

ex14 编写并使用函数

  • 如果一个函数还未被定义就被使用,可以做前向声明type name([type argument1, ...]);
  • 函数定义:
type name([type argument1, ...]) {
	CODE;
	[return ...;]
}
  • 头文件ctype.h里的函数:
函数 作用
isalpha 判断是否是字母
isdigit 判断是否是数字
isalnum 判断是否是字母或数字
isblank 判断是否是空格或 tab
  • 头文件string.h里的函数strlen:返回一个字符串包含的字符数(不包括末尾的\0)

ex15 指针 可怕的指针

  • 指针语料库:
语句 含义
type *ptr type类型,名为ptr的指针
*ptr ptr所指位置的值
*(ptr + i) (ptr所指位置加上i)的值
&thing thing的地址
type *ptr = &thing type类型,名为ptr的指针指向thing的地址
ptr++ 自增ptr所指位置
  • 三种使用指针遍历其指向的数组的方法:
    1. *(ptr + i)i从 0 到 n-1
    2. ptr[i]i从 0 到 n-1,和数组的语法一样
    3. ptr++,不使用 i,自增 n-1 次
  • 指针不是数组,sizeof(ptr)返回指针大小,而非所指数组大小
  • %p打印指针所指地址

ex16 结构体和指向它们的指针

  • 定义结构体:
struct name {
	type element;
	...
};
  • 结构体中类型为字符串的成员要以指针方式定义:char *element;
  • 头文件stdlib.h里的函数:
    • malloc(size)向系统申请分配一块大小为size的内存,并返回一个指向它的指针
    • free(ptr)释放malloc返回的指针ptr所指的内存
  • 头文件assert.h里的函数assert(ptr != NULL);:确保malloc申请到了有效的内存并返回的不是NULL指针,如是NULL,程序将终止
  • 头文件string.h里的函数strdup:复制字符串,用于初始化给结构体中字符串类型的成员,和malloc所做的类似,并将原来的字符串复制到新创建的内存
  • 在堆上(使用指针)实例化结构体:
    1. 声明结构体:struct name *who;
    2. 使用malloc函数申请内存并将返回的指针初始化给*who
    3. 初始化结构体成员:who->element = ...;(*who).element = ...;
    4. 如果结构体中的成员element是字符串类型,释放who所占空间之前,要用free函数释放who->element所占空间
    5. 退出程序前用free函数释放who占的空间
  • 在栈上(不使用指针)实例化结构体:
    1. 声明结构体:struct name who;
    2. 声明结构体成员:who.element = ...;

lcthw's People

Contributors

lctfwyt avatar

Watchers

 avatar

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.