《C言语 基础知识》入门案例

前言

为了更加学习Java 虚拟机的知识,于是决定重新学习C语言知识。

第一个程序

#include <stdio.h>

int main() {
    printf("Hello world!\n");
    return 0;
}

运行结果:

改变一下输出方式:

#include <stdio.h>

int main() {
    printf("\n\
Hello\n\
world!\n");
    return 0;
}

运行结果:

\单独使用表示延续下一行的代码。

下面是转义字符的对照表:

转义字符意义ASCII码值(十进制)
\a 响铃(BEL) 007
\b 退格(BS) ,将当前位置移到前一列 008
\f 换页(FF),将当前位置移到下页开头 012
\n 换行(LF) ,将当前位置移到下一行开头 010
\r 回车(CR) ,将当前位置移到本行开头 013
\t 水平制表(HT)  009
\v 垂直制表(VT) 011
\' 单引号 039
\" 双引号 034
\\ 反斜杠 092

C语言关键字:

关键字说明
auto 声明自动变量
break 跳出当前循环
case 开关语句分支
char 声明字符型变量或函数返回值类型
const 定义常量,如果一个变量被 const 修饰,那么它的值就不能再被改变
continue 结束当前循环,开始下一轮循环
default 开关语句中的"其它"分支
do 循环语句的循环体
double 声明双精度浮点型变量或函数返回值类型
else 条件语句否定分支(与 if 连用)
enum 声明枚举类型
extern 声明变量或函数是在其它文件或本文件的其他位置定义
float 声明浮点型变量或函数返回值类型
for 一种循环语句
goto 无条件跳转语句
if 条件语句
int 声明整型变量或函数
long 声明长整型变量或函数返回值类型
register 声明寄存器变量
return 子程序返回语句(可以带参数,也可不带参数)
short 声明短整型变量或函数
signed 声明有符号类型变量或函数
sizeof 计算数据类型或变量长度(即所占字节数)
static 声明静态变量
struct 声明结构体类型
switch 用于开关语句
typedef 用以给数据类型取别名
unsigned 声明无符号类型变量或函数
union 声明共用体类型
void 声明函数无返回值或无参数,声明无类型指针
volatile 说明变量在程序执行中可被隐含地改变
while 循环语句的循环条件

C99 新增关键字

_Bool _Complex _Imaginary inline restrict

C11 新增关键字

_Alignas _Alignof _Atomic _Generic _Noreturn
_Static_assert _Thread_local      

数据类型

类型存储大小值范围
char 1 字节 -128 到 127 或 0 到 255
unsigned char 1 字节 0 到 255
signed char 1 字节 -128 到 127
int 2 或 4 字节 -32,768 到 32,767 或 -2,147,483,648 到 2,147,483,647
unsigned int 2 或 4 字节 0 到 65,535 或 0 到 4,294,967,295
short 2 字节 -32,768 到 32,767
unsigned short 2 字节 0 到 65,535
long 4 字节 -2,147,483,648 到 2,147,483,647
unsigned long 4 字节 0 到 4,294,967,295

 

#include <stdio.h>

int main() {
    int a;
    char b;
    float c;
    double d;

    a = 520;
    b = 'F';
    c = 3.14;
    d = 3.1415926;

    printf("int 类型%d \n",a);
    printf("char 类型%c \n",b);
    printf("float 类型%.2f \n",c);    //.2 是精确到小数点后两位
    printf("double 类型%11.9f \n",d);  // 11.9 表示总共11位,小数9位。

    return 0;
}

运行结果:

define的案例

#define NAME "天天向上"

int main() {
    printf("好好学习,%s\n",NAME);

    return 0;
}

运行结果:

#include <stdio.h>

#define PI 3.14

int main ()
{
    printf("%s",PI);
#undef PI  // 终止PI的作用域, 后面的代码就不可以使用PI了。
    return 0;
}

嵌套宏:

#include <stdio.h>

#define PI 3.14
#define R 6371
#define V PI * R * R * R * 4/3
int main ()
{
    printf("%f",V);
    return 0;
}

运行结果:

define 的其他用法:

#include <stdio.h>

#define MAX(x,y) ((x>y) ? (x) : (y))
int main ()
{
    printf("较大的数为:%d",MAX(3,5));
    return 0;
}

运行结果:

#include <stdio.h>

#define STR(s) # s

int main ()
{
    printf("%s",STR(HELLO));
    return 0;
}

运行结果:

#include <stdio.h>

#define STR(s,s1) s ## s1

int main ()
{
    printf("%d",STR(2,3));
    return 0;
}

运行结果:

long long int 和sizeof案例

#include <stdio.h>

int main() {
    long long int a ;
    a = 1000000000000000;
    printf("long long int:%lld\n",a);
    printf("long long int:%d\n", sizeof(a));
    return 0;
}

运行结果:

unsigned和signed案例 

是否带符号位,不带符号位可以存更大的正数。

#include <stdio.h>

int main() {

    signed int a ;
    unsigned int b;
    a = 2147483647;
    b = 4294967284;
    printf("int:%d\n",a);
    printf("unsigned int:%ud\n",b);
    return 0;
}

运行结果:

char 和 ASCII表

#include <stdio.h>

int main() {

    char a = 'a';
    printf("char:%d,int:%c\n",a,a);
    return 0;
}

运行结果:

字符数组:

#include <stdio.h>

int main() {

    char a[6] = {'a','b','c','d','e','\0'};
    printf("char:%s\n",a);
    return 0;
}

运行结果:

字符串

#include <stdio.h>

int main() {

    char a[] = "abcde";
    printf("char:%s\n",a);
    return 0;
}

运行结果:

extern 关键字用法

文件:addtwonum.c

#include <stdio.h>
/*外部变量声明*/
extern int x ;
extern int y ;
int addtwonum()
{
    return x+y;
}

主函数:

#include <stdio.h>

/*定义两个全局变量*/
int x=1;
int y=2;
int addtwonum();
int main(void)
{
    int result;
    result = addtwonum();
    printf("result 为: %d\n",result);
    return 0;
}

运行结果:

const 关键字

#include <stdio.h>

int main()
{
    const int  LENGTH = 10;
    const int  WIDTH  = 5;
    const char NEWLINE = '\n';
    int area;

    area = LENGTH * WIDTH;
    printf("value of area : %d", area);
    printf("%c", NEWLINE);

    return 0;
}

运行结果:

math函数

#include <stdio.h>
#include <math.h>

int main()
{
    int i = pow(2,3);
    printf("value of area : %d", i);
    return 0;
}

运行结果:

if 语句

#include <stdio.h>

int main()
{
    int a = 1;
    if(a == 1){
        printf("a == 1");
    }
    return 0;
}

运行结果:

int a ;
scanf("%d",&a);    -- 输入函数

if else 

#include <stdio.h>

int main()
{
    int a ;
    scanf("%d",&a);
    if(a == 1){
        printf("a == 1");
    }else{
        printf("a != 1");
    }
    return 0;
}

运行结果:

switch 表达式

#include <stdio.h>

int main()
{
    int a;
    printf("input integer number: ");
    scanf("%d",&a);
    switch(a)
    {
        case 1:printf("Monday\n");
            break;
        case 2:printf("Tuesday\n");
            break;
        case 3:printf("Wednesday\n");
            break;
        case 4:printf("Thursday\n");
            break;
        case 5:printf("Friday\n");
            break;
        case 6:printf("Saturday\n");
            break;
        case 7:printf("Sunday\n");
            break;
        default:printf("error\n");
    }
}

运行结果:

while 循环

#include <stdio.h>

int main ()
{
    /* 局部变量定义 */
    int a = 10;

    /* while 循环执行 */
    while( a < 20 )
    {
        printf("a 的值: %d\n", a);
        a++;
    }

    return 0;
}

运行结果:

do while 循环

#include <stdio.h>

int main ()
{
    /* 局部变量定义 */
    int a = 10;

    /* do 循环执行,在条件被测试之前至少执行一次 */
    do
    {
        printf("a 的值: %d\n", a);
        a = a + 1;
    }while( a < 20 );

    return 0;
}

运行结果:

getchar 函数

#include <stdio.h>

int main ()
{
    int count ;
    printf("请输入字符串:");
    while(getchar() != '\n'){
        count++;
    }
    printf("你输入了%d个字符",count);
    return 0;
}

运行结果:

for 循环

#include <stdio.h>

int main ()
{
    /* for 循环执行 */
    for( int a = 10; a < 20; a = a + 1 )
    {
        printf("a 的值: %d\n", a);
    }

    return 0;
}

运行结果:

break

#include <stdio.h>

int main ()
{
    /* 局部变量定义 */
    int a = 10;
    /* while 循环执行 */
    while( a < 20 )
    {
        printf("a 的值: %d\n", a);
        a++;
        if( a > 15)
        {
            /* 使用 break 语句终止循环 */
            break;
        }
    }
    return 0;
}

运行结果:

continue

#include <stdio.h>

int main ()
{
    /* 局部变量定义 */
    int a = 10;

    /* do 循环执行 */
    do
    {
        if( a == 15)
        {
            /* 跳过迭代 */
            a = a + 1;
            continue;
        }
        printf("a 的值: %d\n", a);
        a++;

    }while( a < 20 );

    return 0;
}

运行结果:

goto

#include <stdio.h>

int main ()
{
    /* 局部变量定义 */
    int a = 10;

    /* do 循环执行 */
    LOOP:do
    {
        if( a == 15)
        {
            /* 跳过迭代 */
            a = a + 1;
            goto LOOP;
        }
        printf("a 的值: %d\n", a);
        a++;
    
    }while( a < 20 );

    return 0;
}

运行结果:

函数

#include <stdio.h>

/* 函数声明 */
int max(int num1, int num2);

int main() {
    int i ;
    i = max(1,2);
    printf("i = %d",i);
}

int max(int num1, int num2)
{
    /* 局部变量声明 */
    int result;

    if (num1 > num2)
        result = num1;
    else
        result = num2;

    return result;
}

运行结果:

数组

#include <stdio.h>

int main ()
{
    /* 局部变量定义 */
    int a[5] = {1,2,3,4,5};
    for (int i = 0; i < 5; i++) {
        printf("%d\n" , a[i]);
    }

    return 0;
}

运行结果:

数组支持指定元素初始化。

字符串

#include <stdio.h>
#include <string.h>

int main ()
{
    /* 局部变量定义 */
    char a[] = "I love you";
    printf("sizeof str = %d\n",sizeof(a));
    printf("strlen str = %u\n",strlen(a));
    return 0;
}

运行结果

strcpy    -- 拷贝字符串
strncpy   -- 拷贝N位字符串
strcat   -- 拼接字符串
strcmp -- 比较字符串

二维数组

#include <stdio.h>

int main ()
{
    /* 局部变量定义 */
    int a[3][3] = {1,2,3,4,5,6,7,8,9};
    for (int i = 0; i < 3; ++i) {
        for (int j = 0; j < 3; ++j) {
            printf("a[%d][%d]=%d ",i,j,a[i][j]);
        }
        printf("\n");
    }
    return 0;
}

运行结果:

int a[3][3] = {{1,2,3},{4,5,6},{7,8,9}};   -- 也可以这么写

指针

#include <stdio.h>

int main ()
{
    int a = 3;
    int *pa = &a;
    printf("pa = %d \n",pa);
    printf("*pa = %d \n",*pa);
    *pa = 4;
    printf("*pa = %d \n",*pa);
    return 0;
}

运行结果:

指令案例2

#include <stdio.h>

int main ()
{
    char a;
    char *pa = &a;
    printf("请输入一个字符:");
    fflush(stdout);
    scanf("%c",&a);
    printf("a = %c\n",a);
    getchar();
    printf("请输入另一个字符:");
    fflush(stdout);
    scanf("%c",pa);
    printf("a = %c\n",a);
    return 0;
}

运行结果:

指针案例3

#include <stdio.h>

int main ()
{
    char str[128];
    printf("请出入姓名:");
    fflush(stdout);
    scanf("%s",str);
    printf("str = %s",str);
    return 0;
}

运行结果:

字符串 str 本身就已经是地址了, 所以scanf 的时候不需要加&。

案例4

#include <stdio.h>

int main ()
{
    char str[128];
    printf("请出入姓名:");
    fflush(stdout);
    scanf("%s",str);
    printf("str = %p\n",str);
    printf("str = %p",&str[0]);
    return 0;
}

运行结果:

指针案例5

#include <stdio.h>

int main ()
{
    int a[5] ;
    int *pa = a;
    printf("%p %p %p %p %p \n",&a[0],&a[1],&a[2],&a[3],&a[4]);
    *(pa) = 5;
    *(pa+1) = 4;     // pa+1 表示指向数组下一个元素的地址。
    *(pa+2) = 3;
    *(pa+3) = 2;
    *(pa+4) = 1;
    printf("%d %d %d %d %d \n",a[0],a[1],a[2],a[3],a[4]);
    return 0;
}

运行结果:

指针案例6

#include <stdio.h>

int main ()
{
    int a[5] ;
    printf("%p %p %p %p %p \n",&a[0],&a[1],&a[2],&a[3],&a[4]);
    *(a) = 5;
    *(a+1) = 4;
    *(a+2) = 3;
    *(a+3) = 2;
    *(a+4) = 1;
    printf("%d %d %d %d %d \n",a[0],a[1],a[2],a[3],a[4]);
    return 0;
}

运行结果:

指针案例7

#include <stdio.h>
#include <string.h>

int main ()
{
    char *str = "I Love You";
    int a = strlen(str);
    for (int i = 0; i < a; ++i) {
        printf("%c" ,str[i]);
    }
    return 0;
}

运行结果:

指令案例8:实现strlen函数

#include <stdio.h>

int main ()
{
    char str[] = "I Love You";
    char *target = str;
    int count;
    while(*(target++) != '\0'){
        count++;
    }
        printf("%d" ,count);

    return 0;
}

运行结果:

指针案例9:指针数组

#include <stdio.h>

int main ()
{
    char *p[3] = {
            "I Love You.",
            "good good study , day day up.",
            "no pain, no gain."
    };
    for (int i = 0; i < 3; ++i) {
        printf("%s\n",p[i]);
        printf("%p\n",p[i]);

    }
    return 0;
}

运行结果:

指针案例10 :数组指针

#include <stdio.h>

int main ()
{
    int tmp[3] = {1,2,3};
    int (*p)[3] = &tmp;
    for (int i = 0; i < 3; ++i) {
        printf("%d\n",*(*p+i));
    }
    return 0;
}

运行结果:

指针案例11:二维数组和指针

#include <stdio.h>

int main ()
{
    int array[3][3] = {0,1,2,3,4,5,6,7,8};
    printf("sizeof = %d\n",sizeof(int));
    printf("array = %p\n",array);
    printf("array+1 = %p\n",array+1);  // array+1 等于指向下一行数组的地址
    printf("*(array+1)+1 = %p\n",*(array+1)+1);  // array+1 等于指向下一行数组的地址

    return 0;
}

运行结果:

void 指针

#include <stdio.h>

int main ()
{
    int number = 1024;
    int *pNumber = &number;
    void *pa = &number;   // 任何类型的指针都可以指向void的指针

    char str[] = "hello";
    char *pStr = str;
    void *pb = str;
    printf("%p\n",pa);
    printf("%p\n",pNumber);

    printf("%p\n",pStr);
    printf("%p\n",pb);

    printf("%d\n",*(int *)pa);  // void 强转成int指针
    printf("%s\n",(char *)pb);  // void 强转成char指针
    
    return 0;
}

运行结果:

null 指针

#include <stdio.h>

int main ()
{
    int *pa;   // 任何类型的指针都可以指向void的指针
    int *pb = NULL;

    printf("%p\n",pa);
    printf("%p\n",pb);
    printf("%d\n",*pb);
    return 0;
}

运行结果:

指针不需要初始化的时候可以指向NULL。

指针的指针

#include <stdio.h>

int main ()
{
    int num = 520;
    int *p = &num;
    int **pp = &p;
    printf("%d",**pp);
    return 0;
}

运行结果:

指针指向指针的应用

#include <stdio.h>

int main ()
{
    char *p[3] = {
            "I Love You.",
            "good good study , day day up.",
            "no pain, no gain."
    };
    char **a;
    char **b[2];
    a = &p[2];
    b[0] = &p[0];
    b[1] = &p[1];

    printf(" %s\n",*a);
    printf("%s\n",*b[0]);
    printf("%s\n",*b[1]);

    return 0;
}

运行结果:

二维数组和指针

#include <stdio.h>

int main ()
{
    int array[3][3] = {0,1,2,3,4,5,6,7,8};
    int (*p)[3] = array;
    for (int i = 0; i < 3; ++i) {
        for (int j = 0; j < 3; ++j) {
            printf("%d ",*(*(p+i)+j));
        }
        printf("\n");
    }

    return 0;
}

运行结果:

常量指针

#include <stdio.h>

int main ()
{
    int num = 1024;
    const int cNum = 88;
    const int *pcNum = &cNum;
    printf("cnum = %d,&cnum = %p\n",cNum,&cNum);
    printf("*pcNum = %d, pcNum = %p\n",*pcNum,pcNum);

    pcNum = &num;
    num = 1025;

    printf("*pcNum = %d, pcNum = %p\n",*pcNum,pcNum);

    int num1 = 1024;
    int * const constNum = &num1;    // 常量指针,指针地址不能修改。
    *constNum = 1025;
    printf("*constNum = %d, constNum = %p",*constNum,constNum);

    const int * const constNum1 = &cNum;    // 常量指针,指针地址不能修改,指针解引用也不能修改。 cNum 也需要是常量,不然就可以被修改。 
    return 0;
}

运行结果:

函数与指针

#include <stdio.h>

/**
 * 函数声明(可以不写,推荐要写),并且要在使用函数之前
 * @param a
 * @param b
 * @return
 */
void swap(int *a,int *b);

/**
 * 函数实现
 * @param a
 * @param b
 * @return
 */
void swap(int *a,int *b){
    int temp ;
    temp = *a;
    *a = *b;
    *b = temp;
}

int main ()
{
    int a = 3;
    int b = 5;
    printf("a = %d, b = %d\n",a,b);
    swap(&a,&b);    // 使用指针a,b 内存中的值会进行交换。
    printf("a = %d, b = %d\n",a,b);
    return 0;
}

运行结果:

注意:数组传递,传递传的是数组首地址。  

可变参数的函数:

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

/**
 * 函数声明(可以不写,推荐要写),并且要在使用函数之前
 * @return
 */
int sum(int n, ...);

/**
 * 函数实现
 * @return
 */
int sum(int n, ...){
    int sum = 0;
    va_list  vap;
    va_start(vap,n);
    for (int i = 0; i < n; i++) {
        sum = sum + va_arg(vap,int);
    }
    va_end(vap);
    return sum;
}

int main ()
{
    int a = 3;
    int b = 5;
    printf("a = %d, b = %d\n",a,b);
    int tot = sum(3,1,2,3);
    printf("tot = %d\n",tot);
    return 0;
}

运行结果:

指针函数

#include <stdio.h>

char * getWord(char c);

char * getWord(char c){
    switch (c) {
        case 'A': return "apple";
        case 'B': return "banana";
        case 'C': return "cat";
        case 'D': return "dog";
        default: return "None";
    }
}

int main ()
{
    char input;
    printf("请输入一个字母:");
    fflush(stdout);
    scanf("%c",&input);
    printf("%s",getWord(input));
    return 0;
}

运行结果:

不要返回局部变量的指针。

函数指针

#include <stdio.h>

int square(int num);

int square(int num){
    return num*num;
}

int main ()
{
     int num;
    printf("请输入一个整数:");
    fflush(stdout);
    scanf("%d",&num);

    int (*p)(int num);
    p = &square;

    int squareNum = p(num);

    printf("%d",squareNum);
    return 0;
}

运行结果:

函数指针作为参数:

#include <stdio.h>

int square(int num);

int calc(int (*p)(int),int num);

int square(int num){
    return num*num;
}

int calc(int (*p)(int),int num){
    return p(num);
}

int main ()
{
     int num;
    printf("请输入一个整数:");
    fflush(stdout);
    scanf("%d",&num);

    int (*p)(int num);
    p = &square;

    int squareNum = calc(p,num);

    printf("%d",squareNum);
    return 0;
}

运行结果:

函数出参指针:

#include <stdio.h>

int add(int num1, int num2);
int sub(int num1, int num2);
int calc(int (*p)(int,int),int num1,int num2);
int (*select(char c))(int,int);

int add(int num1, int num2){
    return num1 + num2;
}

int sub(int num1, int num2){
    return num1 - num2;
}

int calc(int (*p)(int,int),int num1,int num2){
    return p(num1,num2);
}

int (*select(char c)) (int num1,int num2){
    switch (c) {
        case '+' : return &add;
        case '-' : return &sub;
    }
}

int main ()
{
    int num1 = 5,num2 = 3;
    char c;
    printf("请输入(+ or -):");
    fflush(stdout);
    scanf("%c",&c);

    int (*p)(int num1,int num2);

    int squareNum = calc(select(c),num1,num2);

    printf("%d",squareNum);
    return 0;
}

运行结果:

变量的作用域

局部变量和全局变量重名时, 局部会屏蔽全局变量。

static 关键字

#include <stdio.h>

static int a;

int main ()
{
    a = 1;
    printf("%d",a);
    return 0;
}

运行结果:

保护全局变量,不被其他文件使用。

#include <stdio.h>

static int a;

void function();

void function(){
    static int a = 0;
    printf("%d\n" ,a);
    a++;
}

int main ()
{
    for (int i = 0; i < 10; ++i) {
        function();
    }
    return 0;
}

运行结果:

内存分配malloc

#include <stdio.h>
#include <stdlib.h>

int main ()
{
    int *p;
    // 申请内存空间
    p = (int *)malloc(sizeof(int));
    if(p == NULL){
        printf("分配内存失败\n");
    }
    *p = 7;
    printf("%d\n",*p);
    free(p);   // 释放内存
    printf("%d\n",*p);
    printf("%p",p);
    return 0;
}

运行结果:

malloc 案例2

#include <stdio.h>
#include <stdlib.h>

int main ()
{
    int *p = NULL;
    int num = 10 ;

    p = (int *)malloc(num * sizeof(int));
    p[0] = 1;
    p[1] = 2;
    p[2] = 2;
    p[3] = 2;
    p[4] = 2;
    p[5] = 2;
    p[6] = 2;
    p[7] = 2;
    p[8] = 2;
    p[9] = 2;
    for (int j = 0; j < 10; ++j) {
        printf("%d\n",p[j]);
    }
    free(p);
    return 0;
}

运行结果:

malloc 案例3

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int main ()
{
    int *p = NULL;
    int num = 5 ;

    p = (int *)malloc(num * sizeof(int));
    // 初始化数组的值。
    memset(p,0,num * sizeof(int));
    for (int j = 0; j < num; ++j) {
        printf("p = %d\n",p[j]);
    }
    free(p);

    int *p1 = (int *)calloc(num, sizeof(int));
    for (int j = 0; j < num; ++j) {
        printf("p1 = %d\n",p1[j]);
    }
    return 0;
}

运行结果:

realloc 

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int main ()
{
    int num = 5;
    int *p1 = (int *)malloc(num*sizeof(int));
    int *p2 = (int *)malloc(10*sizeof(int));
    memcpy(p2,p1,10);  // p1 拷贝给 p2
    free(p2);

    // 复制并且扩张内存空间。
    int *p3 = (int *)realloc(p1,10*sizeof(int));
    free(p3);
    free(p1);
    return 0;
}

动态扩展内存空间

#include <stdio.h>
#include <stdlib.h>

int main ()
{
    int num;
    int count = 0;
    int *p = NULL;
    do{
        printf("请输入数字,-1 表示结束\n");
        fflush(stdout);
        scanf("%d",&num);
        count++;
        p = (int *)realloc(p,count*sizeof(int));
        if(p == NULL){
            exit(1);
        }
        p[count-1] = num;
    }while(num != -1);

    for (int i = 0; i < count; ++i) {
        printf("%d\n",p[i]);
    }

    return 0;
}

运行结果:

地址越界案例:

#include <stdio.h>

int main ()
{
    char a = 0;
    char b = 0;
    int *p = (int *)&b;
    *p = 258;   // 地址越界,导致b不能完整保存258。

    printf("%d,%d",a,b);
    return 0;
}

运行结果:

内联函数

#include <stdio.h>

inline int square(int);

inline int square(int x){
    return x * x;
}

int main ()
{
    for (int i = 0; i < 100; ++i) {
        printf("square(%d) = %d",i,square(i));
    }
    return 0;
}

结构体

#include <stdio.h>
#include <string.h>

struct Book{
    char title[128];
    char author[40];
    char publisher[40];
    float price;
    unsigned int date;
} book;

int main ()
{
    strcpy(book.author, "lili");
    book.date = 19910709;
    book.price = 3.5;
    strcpy(book.publisher, "my");
    strcpy(book.title, "C语言");

    printf("作者:%s\n",book.author);
    printf("日期:%d\n",book.date);
    printf("价格:%f\n",book.price);
    printf("出版社:%s\n",book.publisher);
    printf("书名:%s\n",book.title);
    return 0;
}

运行结果:

char 类型需要放在一起, 因为存在对其填充。

结构体取值:

#include <stdio.h>

struct Book{
    char title[128];
    char author[40];
    char publisher[40];
    float price;
    int date;
} book = {
        "C语言",
        "lili",
        "my",
        3.5,
        19910709
};

int main ()
{
    struct Book *book1;
    book1 = &book;
    printf("作者:%s\n",(*book1).author);
    printf("日期:%d\n",(*book1).date);
    printf("价格:%f\n",(*book1).price);
    printf("出版社:%s\n",(*book1).publisher);
    printf("书名:%s\n",(*book1).title);

    printf("作者:%s\n",book1 -> author);
    printf("日期:%d\n",book1 -> date);
    printf("价格:%f\n",book1 -> price);
    printf("出版社:%s\n",book1 -> publisher);
    printf("书名:%s\n",book1 -> title);
    return 0;
}

运行结果:

函数传递结构体

#include <stdio.h>

struct Date{
    int year;
    int month;
    int day;
};

struct Book{
    char title[128];
    char author[40];
    char publisher[40];
    float price;
    struct Date date;
};

struct Book inPut(struct Book book);

struct Book inPut(struct Book book){
    printf("请输入书名:");
    fflush(stdout);
    scanf("%s",book.title);

    printf("请输入作者:");
    fflush(stdout);
    scanf("%s",book.author);

    printf("请输入售价:");
    fflush(stdout);
    scanf("%f",&book.price);

    printf("请输入出版日期(yyyy-mm-dd):");
    fflush(stdout);
    scanf("%d-%d-%d",&book.date.year,&book.date.month,&book.date.day);

    printf("请输入出版社:");
    fflush(stdout);
    scanf("%s",book.publisher);
    return book;
}

int main ()
{

    struct Book book1,book2;
    printf("=============输入第一本书的信息============\n");
    book1 = inPut(book1);
    printf("=============输入第二本书的信息============\n");
    book2 = inPut(book2);
    printf("=============打印第一本书的信息============\n");
    printf("第一本书的作者:%s\n",book1.author);
    printf("第一本书的日期:%d-%d-%d\n",book1.date.year,book1.date.month,book1.date.day);
    printf("第一本书的价格:%f\n",book1.price);
    printf("第一本书的出版社:%s\n",book1.publisher);
    printf("第一本书的书名:%s\n",book1.title);
    printf("=============打印第二本书的信息============\n");
    printf("第二本书的作者:%s\n",book2.author);
    printf("第二本书的日期:%d-%d-%d\n",book2.date.year,book2.date.month,book2.date.day);
    printf("第二本书的价格:%f\n",book2.price);
    printf("第二本书的出版社:%s\n",book2.publisher);
    printf("第二本书的书名:%s\n",book2.title);
    return 0;
}

运行结果:

函数传递结构体的指针:

#include <stdio.h>

struct Date{
    int year;
    int month;
    int day;
};

struct Book{
    char title[128];
    char author[40];
    char publisher[40];
    float price;
    struct Date date;
};

void inPut(struct Book *book);

void inPut(struct Book *book){
    printf("请输入书名:");
    fflush(stdout);
    scanf("%s",book -> title);

    printf("请输入作者:");
    fflush(stdout);
    scanf("%s",book -> author);

    printf("请输入售价:");
    fflush(stdout);
    scanf("%f",&book -> price);

    printf("请输入出版日期(yyyy-mm-dd):");
    fflush(stdout);
    scanf("%d-%d-%d",&book -> date.year,&book -> date.month,&book -> date.day);
    printf("&book = %p:\n",&book);
    printf("book = %p:\n",book);
    printf("请输入出版社:");
    fflush(stdout);
    scanf("%s",book -> publisher);
}

int main ()
{

    struct Book book1;
    printf("=============输入第一本书的信息============\n");
    inPut(&book1);
    printf("=============打印第一本书的信息============\n");
    printf("第一本书的作者:%s\n",book1.author);
    printf("第一本书的日期:%d-%d-%d\n",book1.date.year,book1.date.month,book1.date.day);
    printf("第一本书的价格:%f\n",book1.price);
    printf("第一本书的出版社:%s\n",book1.publisher);
    printf("第一本书的书名:%s\n",book1.title);
    return 0;
}

运行结果:

使用malloc给结构体申请空间:

#include <stdio.h>
#include <stdlib.h>

struct Date{
    int year;
    int month;
    int day;
};

struct Book{
    char title[128];
    char author[40];
    char publisher[40];
    float price;
    struct Date date;
};

void inPut(struct Book *book);

void inPut(struct Book *book){
    printf("请输入书名:");
    fflush(stdout);
    scanf("%s",book -> title);

    printf("请输入作者:");
    fflush(stdout);
    scanf("%s",book -> author);

    printf("请输入售价:");
    fflush(stdout);
    scanf("%f",&book -> price);

    printf("请输入出版日期(yyyy-mm-dd):");
    fflush(stdout);
    scanf("%d-%d-%d",&book -> date.year,&book -> date.month,&book -> date.day);
    printf("&book = %p:\n",&book);
    printf("book = %p:\n",book);
    printf("请输入出版社:");
    fflush(stdout);
    scanf("%s",book -> publisher);
}

int main ()
{

    struct Book *book1;

    book1 = (struct Book *)malloc(sizeof(struct Book));
    if(book1 == NULL){
        exit(1);
    }
    printf("=============输入第一本书的信息============\n");
    inPut(book1);
    printf("=============打印第一本书的信息============\n");
    printf("第一本书的作者:%s\n",book1 -> author);
    printf("第一本书的日期:%d-%d-%d\n",book1 -> date.year,book1 -> date.month,book1 -> date.day);
    printf("第一本书的价格:%f\n",book1 -> price);
    printf("第一本书的出版社:%s\n",book1 -> publisher);
    printf("第一本书的书名:%s\n",book1 -> title);

    free(book1);
    return 0;
}

运行结果:

单链表

#include <stdio.h>
#include <stdlib.h>

struct Book{
    char author[40];
    struct Book *next;
};

void inPut(struct Book *book);

void inPut(struct Book *book){
    printf("请输入作者:");
    fflush(stdout);
    scanf("%s",book -> author);
}

void addBook(struct Book **library);

void addBook(struct Book **library){
    struct Book *book1, *tmp;

    book1 = (struct Book *)malloc(sizeof(struct Book));
    if(book1 == NULL){
        exit(1);
    }

    inPut(book1);

    if(*library != NULL){
        tmp = *library;
        *library = book1;
        book1->next = tmp;
    } else {
        *library = book1;
        book1->next = NULL;
    }
}

int main ()
{
    struct Book *library, *book;
    library->next = NULL;
    library = NULL;     // 不知道为什么这边或不清空会出现一个Q
    addBook(&library);
    addBook(&library);

    book = library;
    while(book != NULL){
        printf("第一本书的作者:%s\n",book->author);
        book = book->next;
    }
    return 0;
}

运行结果:

删除单链表节点

#include <stdio.h>
#include <stdlib.h>

struct Node{
    int a;
    struct Node *next;
};

void insertNode(struct Node **node,int input);

void insertNode(struct Node **node,int input){
    struct Node *previous; // 比input小的节点
    struct Node *current;  // 当前节点(比input大的节点)
    struct Node *new;  // 新加入的指针

    current = *node;
    previous = NULL;
    while(current != NULL && current->a < input){
        previous = current;
        current = current->next;
    }

    new = (struct Node *)malloc(sizeof(struct Node));
    if(new == NULL){
        exit(1);
    }

    new->a = input;
    new->next = current;

    if(previous == NULL){
        *node = new;
    }else{
        previous->next = new;
    }
}

void deleteNode(struct Node **node ,int input);

void deleteNode(struct Node **node ,int input){
    struct Node *previous; // 比input小的节点
    struct Node *current;  // 当前节点(比input大的节点)

    current = *node;
    previous = NULL;
    while(current !=NULL && current->a != input){
        previous = current;
        current = current ->next;
    }

    if(current == NULL){
        printf("没有找到匹配的节点");
        return;
    }else{
        if(previous == NULL){
            *node = current->next;
        }else{
            previous->next = current->next;
        }
    }
    free(current);
}

void printNode(struct Node **node);

void printNode(struct Node **node){
    struct Node *current;
    current = *node;
    while(current != NULL ){
        printf("%d ",current->a);
        current = current->next;
    }
    printf("\n");
}

int main(void){
    struct Node *head = NULL;
    int input;
    while(1){
        printf("请输入一个整数:");
        fflush(stdout);
        scanf("%d",&input);
        if(input == -1){
            break;
        }
        insertNode(&head,input);
        printNode(&head);
    }

    while(1){
        printf("请输入一个需要删除整数:");
        fflush(stdout);
        scanf("%d",&input);
        if(input == -1){
            break;
        }
        deleteNode(&head,input);
        printNode(&head);
    }
    return 0;
}

运行结果:

typedef 关键字

#include <stdio.h>

typedef int integer;  // 将int 取成integer别名

int main(void){
    integer a = 520;
    int b = 520;

    printf("a= %d\n",a);
    printf("b= %d\n",b);
    printf("");
    return 0;
}

运行结果:

给结构体取别名:

#include <stdio.h>
#include <stdlib.h>

typedef struct Date {
    int year;
    int month;
    int date;
} DATE;

int main(void){
    DATE *date = (DATE *)malloc(sizeof(DATE));
    date->year = 2017;
    date->month = 12;
    date->date = 31;
    printf("%d-%d-%d\n",date->year,date->month,date->date);
    return 0;
}

运行结果:

案例3

#include <stdio.h>

typedef int (*PTR_TO_ARRAY)[3];

int main(void){
    int array[] = {1,2,3};
    PTR_TO_ARRAY ptrToArray = &array;

    for (int i = 0; i < 3; ++i) {
        printf("%d\n",(*ptrToArray)[i]);
    }

    return 0;
}

运行结果:

共同体

共用体的对个成员使用同一个内存开始地址。 所以共用体,同时只能由一个成员被使用。

#include <stdio.h>
#include <string.h>

union Test{
    int i;
    double pi;
    char str[6];
};

int main(void){

    union Test test;

    test.i = 520;
    test.pi = 3.14;
    strcpy(test.str,"Hello");
    printf("address of test.1 : %p\n",&test.i);
    printf("address of test.1 : %p\n",&test.pi);
    printf("address of test.1 : %p\n",test.str);

    return 0;
}

运行结果:

枚举类型

#include <stdio.h>

int main(){
    enum week{ Mon = 1, Tues=2, Wed=3, Thurs=4, Fri=5, Sat=6, Sun=7 } day;
    scanf("%d", &day);
    switch(day){
        case Mon: puts("Monday"); break;
        case Tues: puts("Tuesday"); break;
        case Wed: puts("Wednesday"); break;
        case Thurs: puts("Thursday"); break;
        case Fri: puts("Friday"); break;
        case Sat: puts("Saturday"); break;
        case Sun: puts("Sunday"); break;
        default: puts("Error!");
    }
    return 0;
}

运行结果:

位域

#include <stdio.h>

int main(){

    struct Test{
        unsigned int a:1;
        unsigned int b:1;
        unsigned int c:2;
    };

    struct Test test;
    test.a = 0;
    test.b = 1;
    test.c = 2;

    printf("a = %d; b = %d;c = %d;\n",test.a,test.b,test.c);
    printf("size %d", sizeof(struct Test));

    return 0;
}

运行结果:

位域不能超过32位。 不能存比设置大的值。 位域最好使用int 。

位逻辑运算

#include <stdio.h>

int main(){

    int a = 0xFFFFFFFF;
    int mask = 0xABCDEF01;
    printf("0x%X\n" ,~a);
    printf("0x%X\n" ,mask^a);
    printf("0x%X\n" ,mask|a);
    printf("0x%X\n" ,mask&a);

    return 0;
}

运行结果:

c语言的逻辑运算符:

文件读写

#include <stdio.h>
#include <stdlib.h>

int main(){

    FILE *fp1;   // 读取的文件。
    FILE *fp2;   // 写入的文件
    int ch;
    if((fp1 = fopen("hello.txt","r")) == NULL){
        printf("打开文件失败!");
        exit(EXIT_FAILURE);
    }

    if((fp2 = fopen("write.txt","a")) == NULL){
        printf("打开文件失败!");
        exit(EXIT_FAILURE);
    }

    while((ch = fgetc(fp1)) != EOF){ // 判断读取的文件是否已经没有数据了,EOF表示读取失败了
        fputc(ch,fp2);
    }

    fclose(fp1);
    fclose(fp2);
    return 0;
}

运行结果:

hello.txt 的内容会复制到write文件夹里面。

文件读写案例2:

#include <stdio.h>
#include <stdlib.h>

int main(){

    FILE *fp;   // 写入的文件
    char buffer[1024];
    int ch;
    if((fp = fopen("mode.txt","w")) == NULL){
        printf("打开文件失败!");
        exit(EXIT_FAILURE);
    }

    fputs("你好!\n",fp);
    fputs("我很好!",fp);

    fclose(fp);  // 写入文件,关闭流

    if((fp = fopen("mode.txt","r")) == NULL){
        printf("打开文件失败!");
        exit(EXIT_FAILURE);
    }
    while(!(feof(fp))){ // 判断读取的文件是否已经没有数据了,EOF表示读取失败了
        fgets(buffer,1024,fp);
        printf("buffer = %s",buffer);
    }

    fclose(fp);
    return 0;
}

运行结果:

文件读取案例3:

#include <stdio.h>
#include <stdlib.h>
#include <time.h>

int main(){

    FILE *fp;   // 写入的文件
    struct tm *p;
    time_t t;

    time(&t);
    p = localtime(&t);

    if((fp = fopen("date.txt","w")) == NULL){
        printf("打开文件失败!");
        exit(EXIT_FAILURE);
    }

    fprintf(fp,"%d-%d-%d",1900+p->tm_year,1+p->tm_mon,p->tm_mday);
    fclose(fp);

    int year,month,day;
    if((fp = fopen("date.txt","r")) == NULL){
        printf("打开文件失败!");
        exit(EXIT_FAILURE);
    }

    fscanf(fp,"%d-%d-%d",&year,&month,&day);
    printf("%d-%d-%d",year,month,day);
    fclose(fp);
    return 0;
}

运行结果:

文件读取案例4:(fwrite和fread)

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

struct Date{
    int year;
    int month;
    int day;
};

struct Book{
    char title[128];
    char author[40];
    char publisher[40];
    struct Date date;
};

int main(){

    FILE *fp;   // 写入的文件
    struct Book *book_write, *book_read;

    book_write = (struct Book *)malloc(sizeof(struct Book));
    book_read = (struct Book *)malloc(sizeof(struct Book));
    if(book_write == NULL || book_read == NULL){
        printf("分配内存失败!");
        exit(1);
    }

    strcpy(book_write->title,"good good study");
    strcpy(book_write->author,"lili");
    strcpy(book_write->publisher,"bei jin");
    book_write->date.year = 2020;
    book_write->date.month = 1;
    book_write->date.day = 1;

    if((fp = fopen("struct.txt","wb")) == NULL){
        printf("打开文件失败!");
        exit(EXIT_FAILURE);
    }

    fwrite(book_write, sizeof(struct Book),1,fp);
    fclose(fp);

    if((fp = fopen("struct.txt","r")) == NULL){
        printf("打开文件失败!");
        exit(EXIT_FAILURE);
    }

    fread(book_read, sizeof(struct Book),1,fp);
    fclose(fp);

    printf("第一本书的作者:%s\n",book_read -> author);
    printf("第一本书的日期:%d-%d-%d\n",book_read -> date.year,book_read -> date.month,book_read -> date.day);
    printf("第一本书的出版社:%s\n",book_read -> publisher);
    printf("第一本书的书名:%s\n",book_read -> title);

    return 0;
}

运行结果:

文件读取案例5:(fseek 函数)切换读取开始位置 

#include <stdio.h>
#include <stdlib.h>

#define N 2

struct Stu{
    char name[40];
    int age;
}stu[N] ,sb;

int main(){

    FILE *fp;   // 写入的文件

    if((fp = fopen("source.txt","w")) == NULL){
        printf("打开文件失败!");
        exit(EXIT_FAILURE);
    }

    printf("请输入学生信息(姓名和年龄)");
    fflush(stdout);
    for (int i = 0; i < N; ++i) {
        scanf("%s %d",&stu[i].name,&stu[i].age);
    }

    fwrite(stu, sizeof(struct Stu),N,fp);
    fclose(fp);

    if((fp = fopen("source.txt","rb")) == NULL){
        printf("打开文件失败!");
        exit(EXIT_FAILURE);
    }

    fseek(fp, sizeof(struct Stu),SEEK_SET);
    fread(&sb, sizeof(struct Stu),1,fp);
    fclose(fp);
    printf("姓名:%s,年龄:%d。\n",sb.name,sb.age);
    return 0;
}

运行结果:

文件读取案例6:错误输出

#include <stdio.h>
#include <stdlib.h>

int main(){

    FILE *fp;   // 写入的文件
    int ch;

    if((fp = fopen("hello.txt","r")) == NULL){
        fputs("打开文件失败!",stderr);
        exit(EXIT_FAILURE);
    }

    while(1){
        ch = fgetc(fp);
        if(feof(fp)){
            break;
        }
        putchar(ch);
    }

    fputc('c',fp);
    if(ferror(fp)){
        fputs("出错了",stderr);
    }

    clearerr(fp);  // 清除错误指示器和eof指示器

    fclose(fp);
    return 0;
}

运行结果:

文件读取案例7:错误信息打印

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int main(){

    FILE *fp;   // 写入的文件

    if((fp = fopen("bucunzai.txt","r")) == NULL){
        printf("错误代码:%d\n", errno);
        perror("perror打印错误信息");
        fprintf(stderr, "fprintf打印标准错误输出:%s\n", strerror(errno));
        printf("printf打印标准输出:%s\n", strerror(errno));
        exit(EXIT_FAILURE);
    }

    fclose(fp);
    return 0;
}

运行结果:

文件读取案例8:刷新流

#include <stdio.h>
#include <string.h>

int main(){

    char buf[1024];

    memset(buf,'\0',sizeof(buf));

    setvbuf(stdout,buf,_IOFBF,1024);

    fprintf(stdout,"welcome to bbc\n");

    fflush(stdout);   // 刷新流

    fprintf(stdout,"welcome to abb\n");

    getchar();  // 阻塞,需要输入一个字符才可以执行

    fflush(stdout);   // 刷新流

    return 0;
}

运行结果:

 

posted @ 2021-04-06 22:23  加速丨世界  阅读(256)  评论(0编辑  收藏  举报