网站首页 > 技术文章 正文
第1部分:在自定义Shell中读取用户输入(C编程)
在我的自定义shell项目的这一部分中,我将解释如何在C中动态读取用户输入。在shell环境中正确处理用户输入是至关重要的,因为命令的长度可能不同。我没有使用固定大小的缓冲区,而是实现了动态内存分配方法以获得更好的灵活性。
理解read_command函数
read_command() 函数负责:
动态读取用户输入
处理内存分配和重新分配以避免缓冲区溢出
确保输入字符串的正确终止
代码分解
#ifndef READ_COMMAND_H
#define READ_COMMAND_H
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define INT_BUFFER_SIZE 32 // 初始缓冲区大小
char *read_command();
#endif
o 头文件保护 (#ifndef READ_COMMAND_H): 防止多次包含。
o 常量定义 (INT_BUFFER_SIZE): 设置输入存储的初始缓冲区大小。
read_command()的实现
char *read_command()
{
char *command = malloc(INT_BUFFER_SIZE * sizeof(char));
if (!command)
{
perror("Memory allocation failed");
exit(EXIT_FAILURE);
}
o 内存分配 (malloc): 最初为存储用户输入分配 INT_BUFFER_SIZE 字节。
o 错误处理: 如果 malloc 失败,程序打印错误并退出。
int size = INT_BUFFER_SIZE;
int length = 0;
int c;
o size: 跟踪当前缓冲区大小。
o length: 跟踪实际读取的字符数。
o c: 存储从 getchar() 获取的输入字符。
处理动态输入增长
while ((c = getchar()) != '\n' && c != EOF)
{
if (length >= (size - 1))
{
size *= 2; // 需要时将缓冲区大小加倍
char *new_command = realloc(command, (size + 1));
if (!new_command)
{
free(command);
perror("Memory reallocation failed");
exit(EXIT_FAILURE);
}
command = new_command;
}
command[length++] = c;
}
1. 动态扩展内存 (realloc)
o 如果输入超过分配的大小,缓冲区会加倍 (size *= 2)。
o realloc 尝试调整缓冲区大小;如果失败,释放内存并显示错误。
2. 存储字符
o 来自 getchar() 的每个字符按顺序存储在 command[length++] 中
完成输入
command[length] = '\0'; // 空终止字符串
return command;
o 空终止 (\0): 确保字符串正确终止,以便它可以作为有效的C字符串处理。
o 返回输入: 函数返回动态分配的字符串以供进一步使用。
为什么采用这种方法?
避免缓冲区溢出: 与 scanf 或 gets 不同,此方法根据需要动态扩展。
高效的内存管理: realloc 优化内存分配,而不是预分配大块内存。
更好的灵活性: 可以处理长命令而无需任意限制。
猜你喜欢
- 2025-09-04 JAVA入门教程-第2章 基本编程概念
- 2025-09-04 C++基础语法梳理:算法丨十大排序算法(二)
- 2025-09-04 C语言段错误(Segmentation Fault)全面解析:原理、调试与预防
- 2025-09-04 山脊图——多组数据对比的好方法——R语言绘制
- 2025-09-04 编译器动手实践之:实现C语言函数定义的语法解析
- 2025-09-04 SOLIDWORKS语言切换:如何从英文切换到中文
- 2025-09-04 我如何用C语言构建简单Shell(三)_c语言编写shell
- 2025-09-04 程序员上手 Rust 2 年后感悟:它的确强大,但想要取代 C 还远着呢
- 2025-09-04 rust 每次发送请求时调用Arc::new(peer) 会影响性能吗?
- 2025-09-04 大语言模型学习Python中用__new__()创建实例
- 最近发表
-
- count(*)、count1(1)、count(主键)、count(字段) 哪个更快?
- 深入探索 Spring Boot3 中 MyBatis 的 association 标签用法
- js异步操作 Promise fetch API 带来的网络请求变革—仙盟创梦IDE
- HTTP状态码超详细说明_http 状态码有哪些
- 聊聊跨域的原理与解决方法_跨域解决方案及原理
- 告别懵圈!产品新人的接口文档轻松入门指南
- 在Javaweb中实现发送简单邮件_java web发布
- 优化必备基础:Oracle中常见的三种表连接方式
- Oracle常用工具使用 - AWR_oracle工具有哪些
- 搭载USB 3.1接口:msi 微星 发布 990FXA Gaming 游戏主板
- 标签列表
-
- cmd/c (90)
- c++中::是什么意思 (84)
- 标签用于 (71)
- 主键只能有一个吗 (77)
- c#console.writeline不显示 (95)
- pythoncase语句 (88)
- es6includes (74)
- sqlset (76)
- apt-getinstall-y (100)
- node_modules怎么生成 (87)
- chromepost (71)
- flexdirection (73)
- c++int转char (80)
- mysqlany_value (79)
- static函数和普通函数 (84)
- el-date-picker开始日期早于结束日期 (76)
- js判断是否是json字符串 (75)
- asynccallback (71)
- localstorage.removeitem (74)
- vector线程安全吗 (70)
- java (73)
- js数组插入 (83)
- mac安装java (72)
- 查看mysql是否启动 (70)
- 无效的列索引 (74)