拓冰建站拓冰建站
首页 / 资讯中心 / 正文

C语言笔记:隐藏光标函数实现与详细注释(TaoToken 开发环境配置)

1. 光标乱闪到底怎么回事从 Windows 控制台 API 说起写 C 语言控制台程序时你可能遇到过这种画面一个while(1)循环不停刷新屏幕字符位置明明算好了可那个白色小方块光标却在原地一闪一闪把刚打印出来的图案切掉一块。做贪吃蛇、推箱子、打字练习这类小项目时这种闪烁特别影响观感玩家一眼就看出这是个没打磨过的半成品。这个光标不是你的代码画上去的它是 Windows 控制台Console自带的一个 UI 元素。控制台在创建时默认会显示光标并且让它跟随当前输出位置移动。你调用printf或putchar输出字符光标就跟着往后走你调用system(cls)清屏光标又回到左上角继续闪。它和你的绘图逻辑是两套独立的东西所以哪怕你把画面重绘得再干净光标该闪还是闪。要理解怎么隐藏它得先知道 Windows 给控制台留了一套 API。核心是windows.h里的两个东西一个是CONSOLE_CURSOR_INFO结构体用来描述光标的大小和可见性另一个是SetConsoleCursorInfo函数用来把这份描述应用到某个控制台句柄上。句柄从哪来用GetStdHandle(STD_OUTPUT_HANDLE)拿到标准输出的句柄就行。CONSOLE_CURSOR_INFO结构体长这样typedef struct _CONSOLE_CURSOR_INFO { DWORD dwSize; // 光标大小取值 1~100表示占字符格高度的百分比 BOOL bVisible; // 光标是否可见TRUE 可见FALSE 隐藏 } CONSOLE_CURSOR_INFO;关键就在bVisible这个字段。把它设成FALSE也就是 0光标就隐藏了。很多人第一次写会写成{1, 0}第一个 1 是dwSize第二个 0 是bVisible意思就是光标大小 1%不可见。这个写法能用但可读性差后面我会给出更清晰的版本。那为什么标题里要扯到 TaoToken 开发环境配置因为隐藏光标只是控制台开发里的一小块真正写项目时你还会遇到编译环境、依赖管理、代码补全、AI 辅助写注释这些事。我自己的习惯是把开发环境和 AI 编码通道统一起来用 TaoToken 的 API 通道接 Claude Code 或 Cline 这类工具写 C 代码时让它帮我补注释、查 API 用法省得每次翻 MSDN。下面会先讲清楚隐藏光标函数的完整实现和逐行注释再讲怎么在 TaoToken 统一 Key/API 通道下把开发环境配好最后跑一个验证程序确认光标真的消失了。这篇适合谁看如果你正在学 C 语言、准备写控制台小游戏、或者被光标闪烁烦到过那基本就是给你写的。不需要你懂 Windows 内核只要会#include和调用函数就能跟上。核心检索词就三个C语言、隐藏光标函数、注释我会围绕它们把每一步都落到可复制的代码上。2. TaoToken 前置准备统一 Key 与 API 通道怎么配在写隐藏光标函数之前先把开发环境理顺。我试过把 AI 编码工具一个个单独配 KeyClaude Code 一套、Cline 一套、Codex 又一套时间久了根本记不住哪个 Key 对应哪个工具换机器还得重新翻。后来改成用 TaoToken 做统一入口一个 Key 走所有工具配置集中管理迁移时复制一份配置文件就行。TaoToken 在这里扮演的角色是统一的 API 通道你从它这里拿一个 Key然后把 Claude Code、Cline、Codex 这些工具的 Base URL 都指向同一个地址模型 ID 按需选。这样你写 C 代码时不管用哪个工具问SetConsoleCursorInfo的参数顺序是什么走的都是同一条通道不用来回切换账号。先拿 Key。打开官网 https://taotoken.net/?utm_sourcetaotoken_aicg_blog_endutm_mediumcsdnutm_campaignrewriteutm_content 注册登录后进控制台在 API Keys 页面创建一个新 Key。创建时给它起个能认出来的名字比如c-console-dev方便以后区分。Key 只在创建时完整显示一次复制下来存到安全的地方别直接写进要提交到 Git 的代码里。拿到 Key 之后不同工具的配置方式不一样但核心三件套是一样的Base URL、Key、Model ID。Base URL 用https://taotoken.net/api注意这个地址不带 UTM 参数是给程序调用的。Model ID 看你要用哪个模型比如 Claude 系列、GPT 系列在控制台的模型列表里能查到当前可用的。如果你用 Claude Code配置通常写在它的 settings 文件里形如{ env: { ANTHROPIC_BASE_URL: https://taotoken.net/api, ANTHROPIC_API_KEY: 你的_TaoToken_Key, ANTHROPIC_MODEL: claude-sonnet-4-20250514 } }如果你用 Cline 这类 VS Code 插件它走的是 OpenAI 兼容格式在插件设置里填{ apiProvider: openai, openAiBaseUrl: https://taotoken.net/api, openAiApiKey: 你的_TaoToken_Key, openAiModelId: claude-sonnet-4-20250514 }如果你用 Codex它的认证信息一般在auth.json里结构大致是{ OPENAI_API_KEY: 你的_TaoToken_Key, OPENAI_BASE_URL: https://taotoken.net/api }三件套里最容易出错的是 Base URL 结尾要不要带斜杠、要不要带/v1。TaoToken 的 API 地址是https://taotoken.net/api具体到某个工具时有的工具会自动补/v1有的不会。如果配完报 404先检查这里。另一个常见坑是 Key 复制时带了空格肉眼看不出来粘贴到配置里就认证失败。配好之后建议先用一个最简单的请求验证通道通不通。可以用 curlcurl https://taotoken.net/api/v1/chat/completions \ -H Authorization: Bearer 你的_TaoToken_Key \ -H Content-Type: application/json \ -d { model: claude-sonnet-4-20250514, messages: [{role: user, content: 用一句话说明 SetConsoleCursorInfo 的作用}] }如果返回里有正常的choices字段和模型回复说明通道没问题。这一步别跳过后面写 C 代码时如果 AI 工具没反应你能快速判断是通道问题还是工具配置问题。环境配好之后回到 C 语言本身。隐藏光标函数不依赖任何 AI 工具它是纯 Windows API 调用但有了统一的 AI 通道你写注释、查参数、排查编译错误会快很多。下面进入正题。3. 可复制配置hide_cursor 函数源码与逐行注释现在给出完整的隐藏光标函数。我把它拆成两个版本一个是最简版直接对应你常见的{1, 0}写法另一个是带完整注释和错误处理的工程版适合放进实际项目。两个都能直接编译你按需选。先看最简版也就是很多笔记里流传的写法#include windows.h void HideCursor() { CONSOLE_CURSOR_INFO cursor_info {1, 0}; SetConsoleCursorInfo(GetStdHandle(STD_OUTPUT_HANDLE), cursor_info); }这段能跑但{1, 0}这种初始化方式对新手不友好你不知道 1 和 0 分别是什么。而且它没检查GetStdHandle是否返回了有效句柄也没检查SetConsoleCursorInfo的返回值。在正常控制台里没问题但如果程序被重定向输出到文件句柄可能无效函数就静默失败了。下面是工程版逐行注释#include windows.h #include stdio.h /* * HideCursor - 隐藏 Windows 控制台光标 * * 原理通过 GetStdHandle 获取标准输出句柄 * 再用 SetConsoleCursorInfo 把光标的 bVisible 字段设为 FALSE。 * * 返回成功返回 0失败返回 -1 并打印错误码。 */ int HideCursor(void) { /* 1. 获取标准输出的句柄。 * STD_OUTPUT_HANDLE 是 windows.h 里定义的常量 * 代表标准输出设备这个逻辑句柄。 */ HANDLE hOut GetStdHandle(STD_OUTPUT_HANDLE); /* 2. 检查句柄是否有效。 * INVALID_HANDLE_VALUE 表示获取失败 * NULL 表示当前进程没有标准输出比如被重定向。 */ if (hOut INVALID_HANDLE_VALUE || hOut NULL) { fprintf(stderr, GetStdHandle failed, error%lu\n, GetLastError()); return -1; } /* 3. 准备光标信息结构体。 * dwSize 设为 1表示光标占字符格高度的 1% * bVisible 设为 FALSE表示不可见。 * 这里用显式字段赋值比 {1, 0} 更清楚。 */ CONSOLE_CURSOR_INFO cursorInfo; cursorInfo.dwSize 1; cursorInfo.bVisible FALSE; /* 4. 把这份信息应用到控制台。 * 第二个参数传结构体地址函数会读取里面的字段。 */ if (!SetConsoleCursorInfo(hOut, cursorInfo)) { fprintf(stderr, SetConsoleCursorInfo failed, error%lu\n, GetLastError()); return -1; } return 0; }几个细节值得说清楚。dwSize的取值范围是 1 到 100表示光标高度占字符格的百分比。你设成 1 是为了让光标即使被意外显示出来也只是一条细线不刺眼。bVisible是BOOL类型FALSE就是 0TRUE是 1。用FALSE而不是 0是为了让读代码的人一眼看懂意图。GetStdHandle返回的句柄类型是HANDLE在 64 位程序里它是指针大小的整数别用int去接会截断。SetConsoleCursorInfo的第二个参数是PCONSOLE_CURSOR_INFO也就是指向结构体的指针所以传cursorInfo。如果你想让光标重新显示写一个对应的ShowCursor函数就行把bVisible改成TRUEint ShowCursorOn(void) { HANDLE hOut GetStdHandle(STD_OUTPUT_HANDLE); if (hOut INVALID_HANDLE_VALUE || hOut NULL) return -1; CONSOLE_CURSOR_INFO cursorInfo; cursorInfo.dwSize 25; /* 恢复成常见的 25% 高度 */ cursorInfo.bVisible TRUE; if (!SetConsoleCursorInfo(hOut, cursorInfo)) return -1; return 0; }注意函数名别和 Windows 自带的ShowCursor冲突。Windows 的ShowCursor是操作一个内部显示计数器和SetConsoleCursorInfo不是一回事混用会出怪问题。我习惯把自定义的命名成ShowCursorOn或RestoreCursor避免撞名。编译命令用 MinGW 或 MSVC 都行。MinGW 下gcc hide_cursor.c -o hide_cursor.exeMSVC 下在开发者命令提示符里cl hide_cursor.c如果你在 VS Code 里写把windows.h的头文件路径配好MinGW 一般自带不用额外设置。编译时如果报undefined reference to SetConsoleCursorInfo检查是不是链接了kernel32MinGW 默认会链MSVC 也默认链一般不会遇到。4. 验证请求与成功结果跑一个会闪的循环对比光看代码不够得跑起来看效果。我准备了一个对比程序先让光标正常显示跑 3 秒再调用HideCursor隐藏然后进入一个不停重绘的循环你能直观看到光标消失前后的区别。#include windows.h #include stdio.h #include time.h int HideCursor(void) { HANDLE hOut GetStdHandle(STD_OUTPUT_HANDLE); if (hOut INVALID_HANDLE_VALUE || hOut NULL) return -1; CONSOLE_CURSOR_INFO cursorInfo; cursorInfo.dwSize 1; cursorInfo.bVisible FALSE; if (!SetConsoleCursorInfo(hOut, cursorInfo)) return -1; return 0; } /* 把光标移到指定位置方便重绘 */ void GotoXY(int x, int y) { COORD pos { (SHORT)x, (SHORT)y }; SetConsoleCursorPosition(GetStdHandle(STD_OUTPUT_HANDLE), pos); } int main(void) { printf(光标显示中观察 3 秒...\n); Sleep(3000); if (HideCursor() ! 0) { printf(隐藏光标失败\n); return 1; } system(cls); printf(光标已隐藏下面开始重绘循环按 CtrlC 退出\n); Sleep(1500); int frame 0; while (1) { GotoXY(0, 2); printf(帧号: %d , frame); GotoXY(0, 3); printf([##########]); Sleep(200); } return 0; }编译运行gcc cursor_demo.c -o cursor_demo.exe cursor_demo.exe预期结果分三段。第一段程序打印提示后停 3 秒你能看到光标在提示文字后面闪。第二段调用HideCursor后清屏打印光标已隐藏此时光标应该不见了。第三段进入while(1)循环帧号每 200 毫秒加一方块图案原地重绘画面上没有任何光标闪烁。如果你看到帧号在跳但光标不闪说明隐藏成功。这里用到了GotoXY它靠SetConsoleCursorPosition把输出位置定到指定坐标这样重绘时不会一行行往下滚。坐标原点(0, 0)是控制台左上角x 向右增y 向下增。COORD结构体两个字段都是SHORT类型所以强转一下避免警告。如果你在 TaoToken 配好的 AI 工具里写这段代码可以让它帮你检查GetLastError的返回值含义。比如隐藏失败时打印的错误码丢给模型问Windows 错误码 6 是什么意思它会告诉你句柄无效。这种查错场景用统一通道很方便不用切浏览器。验证时有个细节如果你在 Windows Terminal 里跑而不是传统 conhost 控制台光标行为可能略有不同。Windows Terminal 对CONSOLE_CURSOR_INFO的支持是兼容的隐藏效果正常但某些版本下dwSize的视觉表现会有差异。如果发现隐藏不彻底把dwSize设成 1 再试或者确认你跑的是原生 exe 而不是在 IDE 的内嵌终端里。IDE 内嵌终端有时会拦截控制台 API导致设置不生效换成双击 exe 或从 cmd 启动就正常了。成功跑通之后你可以把这个HideCursor函数抽到一个console_util.h里项目里多处#include复用。记得头文件里加#pragma once或 include guard避免重复包含。5. 本篇常见错排查401、local proxy failed、reading choices 与 OAuth这一节把两类问题放一起讲一类是 C 代码本身的编译运行错误一类是 TaoToken 通道配置错误。两类都会让你卡住但排查思路完全不同。先说 C 代码这边。最常见的报错是undefined reference to SetConsoleCursorInfo。这通常发生在你用了非 Windows 的编译器比如在 Linux 的 gcc 下编译。windows.h是 Windows 专有头文件Linux 上没有这个函数自然也不存在。解决办法是在 Windows 环境下编译或者用 MinGW 交叉编译。如果你确实在 Windows 上还报这个错检查是不是把windows.h拼错了或者项目里有个同名的windows.h把它覆盖了。第二个常见问题是光标隐藏了但画面还是闪。这往往不是光标的问题而是你的重绘方式导致的。如果你用system(cls)每帧清屏再重画整个屏幕会闪一下这是清屏本身造成的和光标无关。解决办法是用GotoXY定位后覆盖写或者用双缓冲先画到内存再一次性输出。隐藏光标解决的是小白块闪烁不是整屏闪烁这两个要分清。第三个是HideCursor调用后没效果。先确认你调用的是自己写的函数而不是 Windows 的ShowCursor。Windows 的ShowCursor(FALSE)是减少内部显示计数不是直接隐藏控制台光标行为不一样。另外确认SetConsoleCursorInfo的返回值如果返回 0用GetLastError()看错误码。错误码 6 是句柄无效通常是GetStdHandle失败错误码 87 是参数错误检查结构体字段有没有越界。再说 TaoToken 通道这边。配 AI 工具时401 是最常见的。报错长这样{ error: { message: Invalid API key, type: invalid_request_error } }401 基本就是 Key 不对。检查三件事Key 有没有复制完整首尾别漏字符、Key 有没有多余空格、Key 是不是已经过期或被删除。TaoToken 控制台里能看到 Key 的状态如果显示已禁用重新创建一个。第二个常见报错是local proxy failed或connection refused。这通常出现在你本地配了代理但代理没启动或者工具的 Base URL 写成了localhost某个端口。检查你的工具配置里 Base URL 是不是https://taotoken.net/api别写成http://127.0.0.1:xxxx。如果你之前配过别的中转地址记得改过来。第三个是reading choices相关报错比如cannot read property choices of undefined。这说明请求发出去了但返回的 JSON 结构里没有choices字段。常见原因是模型 ID 写错了服务端返回了一个错误对象而不是正常的补全结果。检查 Model ID 是不是控制台里列出的可用模型别自己拼一个不存在的名字。另一个原因是请求体格式不对比如messages字段拼错、model字段缺失。第四个是 OAuth 相关报错比如OAuth token expired或authentication failed。如果你用的是 Claude Code 这类走 OAuth 的工具它可能优先读本地的 OAuth 凭证而不是你配的 API Key。解决办法是在工具设置里明确指定用 API Key 模式或者清掉旧的 OAuth 缓存。Claude Code 的配置里ANTHROPIC_API_KEY和 OAuth 是两套机制同时存在时可能冲突建议只保留 API Key 那套。为了让你快速对照我把常见报错和排查方向列成表报错关键词可能原因排查动作401 Invalid API keyKey 错误或过期重新复制 Key检查空格local proxy failedBase URL 指向本地代理改成 https://taotoken.net/apireading choicesModel ID 错误或请求体格式错核对模型列表检查 JSON 字段OAuth token expiredOAuth 与 API Key 冲突清 OAuth 缓存只用 API Keyundefined reference非 Windows 环境编译换 Windows MinGW/MSVC光标仍闪烁用了 system(cls) 整屏清改用 GotoXY 覆盖写排查时有个通用技巧先用 curl 单独测通道排除工具本身的干扰。curl 通了说明 Key 和 Base URL 没问题再去查工具配置。curl 不通就先解决通道问题别在工具里瞎改。6. 语义一致 CTA把环境配好继续写你的控制台项目隐藏光标这件事本身不复杂一个函数十几行就搞定但它背后牵扯的是 Windows 控制台 API 的使用习惯。你把GetStdHandle、SetConsoleCursorInfo、CONSOLE_CURSOR_INFO这三个东西弄明白后面做控制台游戏时改光标大小、改颜色、改窗口标题都是同一套思路。我建议你把HideCursor和GotoXY一起放进一个console_util.h以后每个控制台项目开头#include一下省得重复写。开发环境这边如果你还没配 TaoToken 的统一通道可以现在花几分钟弄好。拿 Key 的入口在控制台的 API Keys 页面地址是 https://taotoken.net/api-keys?utm_sourcetaotoken_aicg_blog_endutm_mediumcsdnutm_campaignrewriteutm_content 。配好之后写 C 代码时遇到不认识的 API直接问 AI 工具比翻文档快。接入的具体写法可以参考接入文档https://taotoken.net/doc?utm_sourcetaotoken_aicg_blog_endutm_mediumcsdnutm_campaignrewriteutm_content 里面有各工具的配置示例。如果你只是想先验证一下模型能不能用不想动本地工具配置可以直接在网页里对话https://taotoken.net/chat?utm_sourcetaotoken_aicg_blog_endutm_mediumcsdnutm_campaignrewriteutm_content 。把SetConsoleCursorInfo的用法贴进去问看它答得对不对心里有个底。要是你打算长期写 C 项目、经常用 AI 辅助编码和查错那更适合走 Coding Plan把额度集中管理https://taotoken.net/coding-plan?utm_sourcetaotoken_aicg_blog_endutm_mediumcsdnutm_campaignrewriteutm_content 。我自己的用法是控制台小工具用网页对话快速问正式项目用 Claude Code 接通道写两边共用一个 Key不用来回切账号。最后回到代码本身。你现在手里有一个能直接编译的HideCursor有逐行注释有验证程序有排错表。下一步就是把它用起来写个贪吃蛇或者做个打字练习把光标隐藏掉看看画面是不是干净多了。遇到新问题先看错误码再用 curl 测通道基本都能定位。
分享:

看完干货,该让你的企业上线了

免费需求沟通 · 48 小时内出具建站方案 · 河南本地可上门