You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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$

问题分析

  1. 指针sizeof误用:get_input()中sizeof(input)获取的是指针本身的大小(通常是4或8字节),而非malloc分配的100字节空间大小。当输入内容超过指针大小的字节数时,read()只会读取前几个字节,剩余内容留在输入缓冲区中。
  2. 未处理输入缓冲区残留:剩余的输入内容会在下次循环时被read()直接读取,导致主循环无需等待用户输入就提前执行,重复输出提示符。
  3. 字符串未加结束符:read()不会自动在读取的内容末尾添加\0,可能导致后续字符串操作异常。
  4. 笔误:原代码中const chat是拼写错误,应为const char。

解决方法

  1. 替换sizeof(input)为实际分配的缓冲区大小(比如100),或定义宏来统一管理缓冲区大小。
  2. 根据read()的返回值,为读取的内容添加字符串结束符\0。
  3. 读取完成后,清理输入缓冲区中剩余的字符(比如换行符和未读完的内容)。
  4. 修正拼写错误。

修改后的代码

#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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.17 22:18:12