"Rookie Tutorial" C language learning

"Rookie Tutorial" C language learning

For details, please refer to https://www.runoob.com/cprogramming/c-tutorial.html

//
// Created by pengxiangzhou on 2021/1/23.
//

#ifndef C_DS_C_BASIC_H
#define C_DS_C_BASIC_H

#endif //C_DS_C_BASIC_H
#include <stdio.h>  // 预处理器指令以#开头,标准输入输出库函数

/*
 * 双引号可以输入中文
 * 注释用//

 * ****常量,字符常量/字符串常量
 * 定义符号常量,预处理的时候直接将所有的price替换为20,但是值不能被改变
 * 八进制用0开头,十六进制用0X/0x开头,第一位是符号位
 * 字符变量和字符串常量是不同的量,字符串常量存储时末尾含有\0

 * ASCII码
    char a,b;
    a = 'a';   //转化成ascii码
    b = 'b';
    a = a - 32;
    b = b - 32;
    printf("%c, %c\n%d,%d\n",a,b,a,b);  // %c:字符型;%d:整型

 * ****自动转换和强制转换
 * 所有的浮点运算都是以双精度进行的,即使是仅含float单精度运算的表达式都要转换成double类型的
 * char(字节(八位))和short型都要转换成int(4 个字节),char,short-int-unsigned-long-double
 * 字符型赋予整型,由于字符型为一个字节,而整型为二个字节,故将字符的ascii码值放在整型量的第八位,高八位为0
 *整数型赋予字符型,只把第八位赋予字符量

 * ****左右结合性
 * 结合性是根据代码的执行顺序,加(减)法运算符具有右(左)结合性,乘法和除法具有左结合性

 * ****自增、自减
 * ++i/--i, i自增/减1后再参与其他的运算;i++/i--,i参与运算后,i的值域再自增/减1

 * ****判断
 * (num%2==0)?printf("偶数"):printf("奇数");

 * **** c语句包括
 * 表达式语句(表达式;),函数调用语句(函数名、实际参数;),控制语句(条件判断/循环/转向语句,goto/break/continue/return)
 * 复合语句(多个语句有{}组成),空语句(只有分号;什么都不执行),eg,只要从键盘输入的字符不是会车就重新输入:while(getchar() !='\n'){;}

 * **** printf
int i = 8;
//printf把函数内的运算执行一遍,再一次赋值
//有bug:printf("%d\n,%d\n,%d\n,%d\n,%d\n,%d\n", i , ++i , --i , ++i , --i , ++i);
 * ****输入输出char
    char  a = 'B', b='o';
    putchar(a);putchar(b);putchar('\n'); putchar(a);putchar(b);
    char c;
    c = getchar();
    printf('Please input an word');
    putchar(c);

 * **** 指针
**** 简单例子
int  var = 20;    实际变量的声明
int  *ip;
ip = &var;
var 变量的地址: &var
在指针变量中存储的地址 :ip
使用指针访问值:*ip
**** NULL 指针
int  *ptr = NULL;
ptr 的地址是 0x0: 内存地址 0是操作系统保留的,它表明该指针不指向一个可访问的内存位置。
 * **** 指针的运算
指针的每一次递增,它其实会指向下一个元素的存储单元。
指针的每一次递减,它都会指向前一个元素的存储单元。
指针在递增和递减时跳跃的字节数取决于指针所指向变量数据类型长度,比如 int 就是 4 个字节。
在程序中使用指针代替数组,因为变量指针可以递增,而数组不能递增,数组可以看成一个指针常量。
让数组存储指向 int 或 char 或其他数据类型的指针:指针数组
需要指向整数的指针数组,把 ptr 声明为一个数组,由 MAX 个整数指针组成: int *ptr[MAX];
*/

/*指针数组*/

#include <stdio.h>

const int MAX = 3;

int main1 ()
{
    
    
    int  var[] = {
    
    10, 100, 200};
    int  i, *ptr;

    /* 指针中的数组地址 */
    ptr = &var[0];  // 可写 ptr = var;,因为数组名代表数组的首地址,两个表达式等价
    for ( i = 0; i < MAX; i++)
    {
    
    

        printf("存储地址:var[%d] = %p\n", i, ptr );
        printf("存储值:var[%d] = %d\n", i, *ptr );

        /* 指向下一个位置 */
        ptr++;
    }
    return 0;
}

const int MAX1 = 4;

int main2 ()
{
    
    
    const char *names[] = {
    
    
            "Zara Ali",
            "Hina Ali",
            "Nuha Ali",
            "Sara Ali",
    };
    int i = 0;

    for ( i = 0; i < MAX1; i++)
    {
    
    
        printf("Value of names[%d] = %s\n", i, names[i] );

    }
    return 0;
}

//指向指针的指针是一种多级间接寻址的形式,一个指针包含一个变量的地址。
//当我们定义一个指向指针的指针时,第一个指针包含了第二个指针的地址,第二个指针指向包含实际值的位置。
#include <stdio.h>

int main3 ()
{
    
    
    int  V;
    int  *Pt1;
    int  **Pt2;

    V = 100;

    /* 获取 V 的地址 */
    Pt1 = &V;

    /* 使用运算符 & 获取 Pt1 的地址 */
    Pt2 = &Pt1;

    /* 使用 pptr 获取值 */
    printf("var = %d\n", V );
    printf("Pt1 = %p\n", Pt1 );
    printf("*Pt1 = %d\n", *Pt1 );
    printf("Pt2 = %p\n", Pt2 );
    printf("**Pt2 = %d\n", **Pt2);

    return 0;
}

//C 语言允许您传递指针给函数,只需要简单地声明函数参数为指针类型即可。能接受指针作为参数的函数,也能接受数组作为参数
#include <stdio.h>
/* 函数声明 */
double getAverage(int *arr, int size);

int main4 ()
{
    
    
    /* 带有 5 个元素的整型数组  */
    int balance[5] = {
    
    1000, 2, 3, 17, 50};
    double avg;

    /* 传递一个指向数组的指针作为参数 */
    avg = getAverage( balance, 5 ) ;

    /* 输出返回值  */
    printf("Average value is: %f\n", avg );

    return 0;
}

double getAverage(int *arr, int size)
{
    
    
    int    i, sum = 0;
    double avg;

    for (i = 0; i < size; ++i)
    {
    
    
        sum += arr[i];
    }

    avg = (double)sum / size;

    return avg;
}


//通过传递指针给函数,可以直接修改原参数(实参),而不是引用实参到形参。
// *par是指针的定义;&sec是指针的取值(地址),返回的参数直接存在&sec地址,从而通过传递指针给函数,可以直接修改原参数
#include <stdio.h>
#include <time.h>

// 表达式中*par代表值,但是在函数定义中使用*par表示该参数是指针,&sec代表地址,指针的传参是个地址
void getSeconds(unsigned long *par);

int main5 ()
{
    
    
    unsigned long sec;


    getSeconds( &sec ); //?为什么不是sec,而是&sec

    /* 输出实际值 */
    printf("Number of seconds: %ld\n", sec );

    return 0;
}

void getSeconds(unsigned long *par)
{
    
    
    /* 获取当前的秒数 */
    *par = time( NULL );
    return;
}
//C 允许您从函数返回指针,必须声明一个返回指针的函数
//C 语言不支持在调用函数时返回局部变量的地址,除非定义局部变量为 static 变量
//static 变量的值存放在内存中的静态数据区,不会随着函数执行的结束而被清除,故能返回其地址。

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

/* 要生成和返回随机数的函数 */
int * getRandom( )  //int *函数返回的是一个int类型的指针,数组名r代表该数组的首地址
{
    
    
    static int  r[10];
    int i;

    /* 设置种子 */
    srand( (unsigned)time( NULL ) );
    for ( i = 0; i < 10; ++i)
    {
    
    
        r[i] = rand();
        printf("%d\n", r[i] );
    }

    return r;
}

/* 要调用上面定义函数的主函数 */
int main6 ()
{
    
    
    /* 一个指向整数的指针 */
    int *p;
    int i;

    p = getRandom();
    for ( i = 0; i < 10; i++ )
    {
    
    
        printf("*(p + [%d]) : %d\n", i, p); //传递的是数组的首地址,
        printf("*(p + [%d]) : %d\n", i, p+i); //传递的是数组的地址,int占四个字节
        printf("*(p + [%d]) : %d\n", i, *(p+i)); //传递的是数值
    }

    return 0;
}


int *test_func()
{
    
    
    static int local_data;  //加static修饰
    local_data = 10;

    printf("Function local_data : %d\n", local_data);

    return &local_data;  //返回指针??
}

int main7()
{
    
    
    int *main_data = NULL;

    main_data = test_func();

    printf("Return data: %d\n", *main_data);

    return 0;
}

#include <stdio.h>

int max(int x, int y)
{
    
    
    return x > y ? x : y;
}

int main8(void)
{
    
    
    /* p 是函数指针 */
    int (* p)(int, int) = & max; // &可以省略
    int a, b, c, d;

    printf("请输入三个数字:");
    scanf("%d %d %d", & a, & b, & c);

    /* 与直接调用函数等价,d = max(max(a, b), c) */
    d = p(p(a, b), c);

    printf("最大的数字是: %d\n", d);

    return 0;
}
#include <stdlib.h>
#include <stdio.h>

// 回调函数
void populate_array(int *array, size_t arraySize, int (*getNextValue)(void))
{
    
    
    for (size_t i=0; i<arraySize; i++)
        array[i] = getNextValue();
}

// 获取随机值
int getNextRandomValue(void)
{
    
    
    return rand();
}

int main9(void)
{
    
    
    int myarray[10];
    /* getNextRandomValue 不能加括号,否则无法编译,因为加上括号之后相当于传入此参数时传入了 int , 而不是函数指针*/
    populate_array(myarray, 10, getNextRandomValue);
    for(int i = 0; i < 10; i++) {
    
    
        printf("%d ", myarray[i]);
    }
    printf("\n");
    return 0;
}



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

struct Books
{
    
    
    char  title[50];
    char  author[50];
    char  subject[100];
    int   book_id;
}book = {
    
    "C 语言", "RUNOOB", "编程语言", 123456};

int main10( )
{
    
    
    struct Books Book1;        /* 声明 Book1,类型为 Books */
    struct Books Book2;        /* 声明 Book2,类型为 Books */

    /* Book1 详述 */
    strcpy( Book1.title, "C Programming");
    strcpy( Book1.author, "Nuha Ali");
    strcpy( Book1.subject, "C Programming Tutorial");
    Book1.book_id = 6495407;

    /* Book2 详述 */
    strcpy( Book2.title, "Telecom Billing");
    strcpy( Book2.author, "Zara Ali");
    strcpy( Book2.subject, "Telecom Billing Tutorial");
    Book2.book_id = 6495700;

    /* 输出 Book1 信息 */
    printf( "Book 1 title : %s\n", Book1.title);
    printf( "Book 1 author : %s\n", Book1.author);
    printf( "Book 1 subject : %s\n", Book1.subject);
    printf( "Book 1 book_id : %d\n", Book1.book_id);

    /* 输出 Book2 信息 */
    printf( "Book 2 title : %s\n", Book2.title);
    printf( "Book 2 author : %s\n", Book2.author);
    printf( "Book 2 subject : %s\n", Book2.subject);
    printf( "Book 2 book_id : %d\n", Book2.book_id);

    return 0;
}

#include <stdio.h>
#include <string.h>
//Data 类型的变量可以存储一个整数、一个浮点数,或者一个字符串。
//这意味着一个变量(相同的内存位置)可以存储多个多种类型的数据。您可以根据需要在一个共用体内使用任何内置的或者用户自定义的数据类型。
union Data
{
    
    
    int i;
    float f;
    char  str[20];
};

int main11( )
{
    
    
    union Data data;

    printf( "Memory size occupied by data : %d\n", sizeof(data));

    return 0;
}

#include <stdio.h>
//C 语言支持递归,即一个函数可以调用其自身。使用递归时,要注意定义一个从函数退出的条件,否则会进入死循环。
double factorial(unsigned int i)
{
    
    
    if(i <= 1)
    {
    
    
        return 1;
    }
    return i * factorial(i - 1);
}
int  main12()
{
    
    
    int i = 15;
    printf("%d 的阶乘为 %f\n", i, factorial(i));
    return 0;
}


Guess you like

Origin blog.csdn.net/weixin_43464554/article/details/113256244