桓楠百科网

编程知识、经典语录与百科知识分享平台

C语言进阶之回调函数详解

大家好,我是柠檬哥

欢迎关注@程序员柠檬橙编程路上不迷路,私信发送以下关键字获取编程资源:


发送

C语言中的数组:声明、初始化和操作

大家好,今天给大家介绍C语言中的数组:声明、初始化和操作,文章末尾附有分享大家一个资料包,差不多150多G。里面学习内容、面经、项目都比较新也比较全!

#C语言完整基础教程#第11节函数说明

C语言的函数是什么?

先看一下这段代码,我把排序写在了main函数里面。如果说我现在有更多的功能都写在main函数,你肯定会阅读不下去这个代码。

函数是一组一起执行一个任务的语句,每个C程序都至少有一个函数,即主函数main(可以把一些代码分配到不同的函数中。函数还有很多叫法,比如方法、子程序等。暂停先看一下定义,第二行和第三行是函数的声明,函数声明的写法就是函数的返回类型+函数名+形式参数+分号。函数第12行和第21行是我写的两个不同功能的函数。这里的结构就是:返回类型+函数名+形式参数+方法体。12行的返回类型是个一个整数,21行void表示无返回值。

Python 这么高级的编程语言,怎么还能写出内存泄漏?

点赞、收藏、加关注,下次找我不迷路

C语言实现2048小游戏

以下是使用C语言实现的2048小游戏代码:

#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <conio.h> // 用于Windows平台的_getch()

#define SIZE 4
#define TARGET 2048

// 游戏板结构体
typedef struct
{
    int board[SIZE][SIZE];
    int score;
    int game_over;
    int win;
} Game;

// 方向枚举
enum Direction
{
    UP,
    DOWN,
    LEFT,
    RIGHT
};

void display(const Game *game);
int check_game_over(const Game *game);
void add_new_tile(Game *game);
void move(Game *game, enum Direction dir);

// 初始化游戏
void init_game(Game *game)
{
    // 清空棋盘
    for (int i = 0; i < SIZE; i++)
    {
        for (int j = 0; j < SIZE; j++)
        {
            game->board[i][j] = 0;
        }
    }
    game->score = 0;
    game->game_over = 0;
    game->win = 0;

    // 生成两个初始数字
    add_new_tile(game);
    add_new_tile(game);
}

// 添加新数字(90%概率生成2,10%生成4)
void add_new_tile(Game *game)
{
    int empty_cells[SIZE * SIZE][2];
    int count = 0;

    // 查找所有空格子
    for (int i = 0; i < SIZE; i++)
    {
        for (int j = 0; j < SIZE; j++)
        {
            if (game->board[i][j] == 0)
            {
                empty_cells[count][0] = i;
                empty_cells[count][1] = j;
                count++;
            }
        }
    }

    if (count > 0)
    {
        // 随机选择一个空格子
        int index = rand() % count;
        int value = (rand() % 10 < 9) ? 2 : 4; // 概率分配
        game->board[empty_cells[index][0]][empty_cells[index][1]] = value;
    }
}

// 打印游戏界面
void display(const Game *game)
{
    system("cls"); // 清屏(Windows)

    printf("Score: %d\n", game->score);
    printf("-------------------------\n");

    for (int i = 0; i < SIZE; i++)
    {
        printf("|");
        for (int j = 0; j < SIZE; j++)
        {
            if (game->board[i][j] == 0)
            {
                printf("    |");
            }
            else
            {
                printf("%4d|", game->board[i][j]);
            }
        }
        printf("\n-------------------------\n");
    }
}

// 检查游戏是否结束
int check_game_over(const Game *game)
{
    // 检查是否有空格子
    for (int i = 0; i < SIZE; i++)
    {
        for (int j = 0; j < SIZE; j++)
        {
            if (game->board[i][j] == 0)
                return 0;
        }
    }

    // 检查是否有相邻相同数字
    for (int i = 0; i < SIZE; i++)
    {
        for (int j = 0; j < SIZE; j++)
        {
            int current = game->board[i][j];
            // 检查右侧和下侧
            if (j < SIZE - 1 && current == game->board[i][j + 1])
                return 0;
            if (i < SIZE - 1 && current == game->board[i + 1][j])
                return 0;
        }
    }

    return 1;
}

// 移动并合并数字(核心逻辑)
void move(Game *game, enum Direction dir)
{
    int moved = 0;
    int temp_board[SIZE][SIZE];

    // 复制当前棋盘状态
    for (int i = 0; i < SIZE; i++)
    {
        for (int j = 0; j < SIZE; j++)
        {
            temp_board[i][j] = game->board[i][j];
        }
    }

    // 根据方向处理移动
    switch (dir)
    {
    case LEFT:
        for (int i = 0; i < SIZE; i++)
        {
            int pos = 0;
            int last_merged = -1;

            for (int j = 0; j < SIZE; j++)
            {
                if (temp_board[i][j] != 0)
                {
                    if (pos > 0 && temp_board[i][pos - 1] == temp_board[i][j] && last_merged != pos - 1)
                    {
                        // 合并
                        temp_board[i][pos - 1] *= 2;
                        game->score += temp_board[i][pos - 1];
                        temp_board[i][j] = 0;
                        last_merged = pos - 1;
                        moved = 1;
                    }
                    else
                    {
                        if (pos != j)
                            moved = 1;
                        temp_board[i][pos] = temp_board[i][j];
                        pos++;
                    }
                }
            }

            // 填充右侧空白
            while (pos < SIZE)
            {
                if (temp_board[i][pos] != 0)
                    moved = 1;
                temp_board[i][pos++] = 0;
            }
        }
        break;
        
    case DOWN:
        // 按列处理,从下往上扫描
        for (int j = 0; j < SIZE; j++)
        {                           // 遍历每一列
            int pos = SIZE - 1;     // 从最底行开始填充
            int last_merged = SIZE; // 初始化最后合并位置(超出范围)

            for (int i = SIZE - 1; i >= 0; i--)
            { // 从下往上扫描
                if (temp_board[i][j] != 0)
                { // 发现非空单元格
                    // 检查是否可以合并
                    if (pos < SIZE - 1 &&                             // 确保不是第一个元素
                        temp_board[pos + 1][j] == temp_board[i][j] && // 值相同
                        last_merged != pos + 1)
                    { // 防止重复合并

                        // 执行合并
                        temp_board[pos + 1][j] *= 2;
                        game->score += temp_board[pos + 1][j]; // 更新分数
                        temp_board[i][j] = 0;                  // 清空当前位置
                        last_merged = pos + 1;                 // 记录合并位置
                        moved = 1;                             // 标记发生移动
                    }
                    else
                    {
                        // 无法合并则移动元素
                        if (pos != i)
                        { // 位置发生变化
                            temp_board[pos][j] = temp_board[i][j];
                            temp_board[i][j] = 0; // 清空原位置
                            moved = 1;
                        }
                        pos--; // 更新填充位置
                    }
                }
            }

            // 填充上方空白(非必需但更安全)
            while (pos >= 0)
            {
                if (temp_board[pos][j] != 0)
                    moved = 1;
                temp_board[pos--][j] = 0;
            }
        }
        break;
        
    case RIGHT:
        // 按行处理,从右往左扫描
        for (int i = 0; i < SIZE; i++)
        {                           // 遍历每一行
            int pos = SIZE - 1;     // 从最右列开始填充
            int last_merged = SIZE; // 初始化最后合并位置(超出范围)

            for (int j = SIZE - 1; j >= 0; j--)
            { // 从右往左扫描
                if (temp_board[i][j] != 0)
                { // 发现非空单元格
                    // 检查是否可以合并
                    if (pos < SIZE - 1 &&                             // 确保不是第一个元素
                        temp_board[i][pos + 1] == temp_board[i][j] && // 值相同
                        last_merged != pos + 1)
                    { // 防止重复合并

                        // 执行合并
                        temp_board[i][pos + 1] *= 2;
                        game->score += temp_board[i][pos + 1]; // 更新分数
                        temp_board[i][j] = 0;                  // 清空当前位置
                        last_merged = pos + 1;                 // 记录合并位置
                        moved = 1;                             // 标记发生移动
                    }
                    else
                    {
                        // 无法合并则移动元素
                        if (pos != j)
                        { // 位置发生变化
                            temp_board[i][pos] = temp_board[i][j];
                            temp_board[i][j] = 0; // 清空原位置
                            moved = 1;
                        }
                        pos--; // 更新填充位置
                    }
                }
            }

            // 填充左侧空白(非必需但更安全)
            while (pos >= 0)
            {
                if (temp_board[i][pos] != 0)
                    moved = 1;
                temp_board[i][pos--] = 0;
            }
        }
        break;

    case UP:
        // 按列处理,从上往下扫描
        for (int j = 0; j < SIZE; j++)
        {                         // 遍历每一列
            int pos = 0;          // 从最顶行开始填充
            int last_merged = -1; // 初始化最后合并位置(无效位置)

            for (int i = 0; i < SIZE; i++)
            { // 从上往下扫描
                if (temp_board[i][j] != 0)
                { // 发现非空单元格
                    // 检查是否可以合并
                    if (pos > 0 &&                                    // 确保不是第一个元素
                        temp_board[pos - 1][j] == temp_board[i][j] && // 值相同
                        last_merged != pos - 1)
                    { // 防止重复合并

                        // 执行合并
                        temp_board[pos - 1][j] *= 2;
                        game->score += temp_board[pos - 1][j]; // 更新分数
                        temp_board[i][j] = 0;                  // 清空当前位置
                        last_merged = pos - 1;                 // 记录合并位置
                        moved = 1;                             // 标记发生移动
                    }
                    else
                    {
                        // 无法合并则移动元素
                        if (pos != i)
                        { // 位置发生变化
                            temp_board[pos][j] = temp_board[i][j];
                            temp_board[i][j] = 0; // 清空原位置
                            moved = 1;
                        }
                        pos++; // 更新填充位置
                    }
                }
            }

            // 填充下方空白(非必需但更安全)
            while (pos < SIZE)
            {
                if (temp_board[pos][j] != 0)
                    moved = 1;
                temp_board[pos++][j] = 0;
            }
        }
        break;
        // 其他方向处理类似(代码略)
        // ...
    }

    // 更新棋盘状态
    if (moved)
    {
        for (int i = 0; i < SIZE; i++)
        {
            for (int j = 0; j < SIZE; j++)
            {
                game->board[i][j] = temp_board[i][j];
            }
        }
        add_new_tile(game);
        game->game_over = check_game_over(game);
    }
}

// 获取用户输入
enum Direction get_input()
{
    int c = _getch();
    switch (c)
    {
    case 72:
        return UP; // 方向键上
    case 80:
        return DOWN; // 方向键下
    case 75:
        return LEFT; // 方向键左
    case 77:
        return RIGHT; // 方向键右
    case 'q':
        exit(0); // 退出游戏
    default:
        return get_input(); // 无效输入重新获取
    }
}

int main()
{
    srand(time(NULL)); // 初始化随机种子

    Game game;
    init_game(&game);

    while (!game.game_over && !game.win)
    {
        display(&game);
        enum Direction dir = get_input();
        move(&game, dir);

        // 检查是否达成2048
        for (int i = 0; i < SIZE; i++)
        {
            for (int j = 0; j < SIZE; j++)
            {
                if (game.board[i][j] == TARGET)
                {
                    game.win = 1;
                    break;
                }
            }
        }
    }

    display(&game);
    if (game.win)
    {
        printf("Congratulations! You've reached %d!\n", TARGET);
    }
    else
    {
        printf("Game Over! Final score: %d\n", game.score);
    }

    return 0;
}

[信捷PLC] 信捷PLC之C函数编程(一)

前言

写PLC程序,越来越觉得结构化文本编程语言(ST)给PC编程带来的便利,在处理一些数据上,可以写的更加灵活。所以,在项目PLC选型上,我都会优先选择支持结构化文本的PLC。

国内有些厂商推出了一些较为高端一些的PLC,开发环境集成在Codesys平台(例如禾川、信捷);也有的PLC的开发环境集成在Visual Studio平台中(例如倍福)。

奇葩代码!让C语言老师看了想吐血

以下是一些让C语言老师感到非常气愤的极其低级错误的C语言代码示例:

缺少分号:

int a = 5 // 缺少分号

int b = 10;

忘记在语句结束处添加分号是一个非常常见的错误,但它会导致编译错误。

设计模式:单例模式及C及C++实现示例

单例模式:确保唯一实例

单例模式是一种创建型设计模式,它确保一个类只有一个实例,并提供一个全局访问点。 它是最简单和最常用的设计模式之一,本文介绍C语言及C++实现的3种单例模式代码。

C语言正则表达式简单实现

以下是C语言实现正则表达式的代码:

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

bool isMatch(char* s, char* p) {
    int m = strlen(s);
    int n = strlen(p);
    
    // 检查模式p的合法性,避免无效的'*'
    for (int i = 0; i < n; ++i) {
        if (p[i] == '*' && (i == 0 || p[i-1] == '*')) {
            return false;
        }
    }
    
    // 创建动态规划表,dp[i][j]表示s的前i个字符和p的前j个字符是否匹配
    bool *dp = (bool *)calloc((m+1) * (n+1), sizeof(bool));
    if (!dp) {
        return false; // 内存分配失败,但题目通常保证不会出现
    }
    
    // 初始化基础情况:空字符串匹配空模式
    dp[0] = true;
    
    // 初始化第一行,处理模式p可以匹配空字符串的情况(如"a*")
    for (int j = 1; j <= n; ++j) {
        if (p[j-1] == '*') {
            dp[j] = dp[j-2]; // 匹配0次的情况
        }
    }
    
    // 填充dp表
    for (int i = 1; i <= m; ++i) {
        for (int j = 1; j <= n; ++j) {
            if (p[j-1] == '*') {
                // 处理'*'的情况,考虑匹配0次或多次
                bool matchZero = dp[i*(n+1) + (j-2)];
                bool matchMore = (p[j-2] == '.' || s[i-1] == p[j-2]) && dp[(i-1)*(n+1) + j];
                dp[i*(n+1)+j] = matchZero || matchMore;
            } else {
                // 处理普通字符或'.'的情况
                bool currentMatch = (p[j-1] == '.' || s[i-1] == p[j-1]);
                dp[i*(n+1)+j] = currentMatch && dp[(i-1)*(n+1) + (j-1)];
            }
        }
    }
    
    bool result = dp[m*(n+1) + n];
    free(dp);
    return result;
}


void test(const char *s, const char *p, bool expected) {
    bool result = isMatch((char*)s, (char*)p);
    printf("s=\"%s\", p=\"%s\" -> %s (Expected %s)\n", 
           s, p, 
           result ? "true" : "false", 
           expected ? "true" : "false");
}

int main() {
    // 完全匹配
    test("aa", "aa", true);
    
    // '.' 匹配任意字符
    test("ab", "a.", true);
    
    // '*' 匹配零次
    test("a", "ab*", true);        // b* 匹配零次
    
    // '*' 匹配多次
    test("aaa", "a*", true);       // a* 匹配三次
    test("ab", "a*b", true);       // a* 匹配一次
    
    // 复杂组合
    test("aab", "c*a*b", true);    // c* 匹配零次,a* 匹配两次
    test("mississippi", "mis*is*p*.", false); // 无法匹配
    
    // 无效模式
    test("a", "a**", false);       // 连续 '*' 非法
    
    // 空字符串
    test("", "", true);            // 空字符串匹配空模式
    test("", "a*", true);          // a* 匹配零次
    
    // 边界情况
    test("a", ".*", true);         // .* 匹配任意字符
    
    return 0;
}

C语言排序方法——冒泡排序详解!你学会了吗?

冒泡排序法的基本思路为:每次将相邻的两个数比较,将小的调在前面。举个例子,如果有6个数:9,8,5,4,2,0。第一次先将最前面的两个数9和8对调。第二次将第2个数和第3个数对调(9和5)······如此共进行5次得到8,5,4,2,0,9的顺序,可以看到:最大的数9已经沉到了最底下成为了最下面的一个数,而小的数“上升”。

<< < 69 70 71 72 73 74 75 76 77 78 > >>
控制面板
您好,欢迎到访网站!
  查看权限
网站分类
最新留言