C语言Shell程序中read()引发带空格输入时提示符重复问题
C语言Shell程序中read()导致输入提示符重复的问题解决
问题描述
我用C语言开发Shell程序,需要在显示当前工作目录后获取用户输入。因为后续要处理信号,所以选用read()和write()而非标准IO函数。测试时发现,当输入内容包含空格时,输入提示符会重复出现,重复次数和输入中的空格数一致,推测问题出在read()调用,但不清楚具体解决方法。
原代码
#include "../include/msgs.h" #include <linux/limits.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <unistd.h> const char *cwd_err_msg = FORMAT_MSG("getcwd", GETCWD_ERROR_MSG); const char *read_err_msg = FORMAT_MSG("read", READ_ERROR_MSG); // 修正笔误:chat -> char char *get_input(); int main() { while (1) { char cwd[PATH_MAX]; // 错误检查 if (getcwd(cwd, sizeof(cwd)) == NULL) { perror(cwd_err_msg); } strncat(cwd, "$", 1); write(STDOUT_FILENO, cwd, strlen(cwd)); char *input = get_input(); free(input); } return 0; } char *get_input() { char *input = (char *)malloc(100 * sizeof(char)); if (read(STDIN_FILENO, input, sizeof(input)) == -1) { // 这里sizeof(input)是指针大小,错误 perror(read_err_msg); } return input; }
测试示例
/home/units/shell/build$test /home/units/shell/build$testing and testing /home/units/shell/build$/home/units/shell/build$/home/units/shell/build$
问题分析
- 指针sizeof误用:
get_input()中sizeof(input)获取的是指针本身的大小(通常是4或8字节),而非malloc分配的100字节空间大小。当输入内容超过指针大小的字节数时,read()只会读取前几个字节,剩余内容留在输入缓冲区中。 - 未处理输入缓冲区残留:剩余的输入内容会在下次循环时被
read()直接读取,导致主循环无需等待用户输入就提前执行,重复输出提示符。 - 字符串未加结束符:
read()不会自动在读取的内容末尾添加\0,可能导致后续字符串操作异常。 - 笔误:原代码中
const chat是拼写错误,应为const char。
解决方法
- 替换
sizeof(input)为实际分配的缓冲区大小(比如100),或定义宏来统一管理缓冲区大小。 - 根据
read()的返回值,为读取的内容添加字符串结束符\0。 - 读取完成后,清理输入缓冲区中剩余的字符(比如换行符和未读完的内容)。
- 修正拼写错误。
修改后的代码
#include "../include/msgs.h" #include <linux/limits.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <unistd.h> #define INPUT_BUF_SIZE 100 // 定义缓冲区大小宏 const char *cwd_err_msg = FORMAT_MSG("getcwd", GETCWD_ERROR_MSG); const char *read_err_msg = FORMAT_MSG("read", READ_ERROR_MSG); char *get_input(); int main() { while (1) { char cwd[PATH_MAX]; if (getcwd(cwd, sizeof(cwd)) == NULL) { perror(cwd_err_msg); } strncat(cwd, "$ ", 2); // 加个空格,提示符更美观 write(STDOUT_FILENO, cwd, strlen(cwd)); char *input = get_input(); if (input) { // 这里可以添加输入处理逻辑 free(input); } } return 0; } char *get_input() { char *input = malloc(INPUT_BUF_SIZE * sizeof(char)); if (!input) { perror("malloc"); return NULL; } ssize_t bytes_read = read(STDIN_FILENO, input, INPUT_BUF_SIZE - 1); // 留一个位置给结束符 if (bytes_read == -1) { perror(read_err_msg); free(input); return NULL; } // 添加字符串结束符 input[bytes_read] = '\0'; // 清理输入缓冲区中剩余的字符(如果输入超过缓冲区大小) if (bytes_read == INPUT_BUF_SIZE - 1 && input[bytes_read - 1] != '\n') { char c; while (read(STDIN_FILENO, &c, 1) > 0 && c != '\n'); } return input; }
内容的提问来源于stack exchange,提问作者Gyro
相关产品推荐
相关产品推荐

