【问题标题】:strtok() not reading past the first input piecestrtok() 没有读取第一个输入片段
【发布时间】:2021-02-10 03:01:24
【问题描述】:

我正在尝试为操作系统类编写 Linux shell 替代品,但无法解析输入字符串。我可以读取字符串输入的第一行,但是一旦到达任何空格分隔符,它就会完全跳过其他所有内容并进入新的提示符。下面是我想要处理的代码。

while(1){

    //Flush I/O streams to prevent duplicate '#' printing each new line
    fflush(stdout);
    fflush(stdin);

    printf("# ");

    //Take in the input and store it in an auxiliary variable.
    scanf("%s", input);

    strcpy(commandInput, input);

    char *ptr = strtok(commandInput, delimiter); //Parse the command and check what it is below.

    if(strcmp(commandInput, "byebye") == 0){ //End the shell program
        
        exit(1);

    } else if(strcmp(commandInput, "whereami") == 0){ //Get the current working directory

        getCurrentDirectory();
        break;

    } else if(strcmp(commandInput, "movetodir") == 0){
        
        //Store the new directory name once returned 
        strcpy(currentDirectory, changeDirectory());

        break;

    } else {
        //Handles any invalid input strings of any length

        printf("%s\n", ptr);
        while(ptr != NULL){

            printf("%s\n", ptr);
            ptr = strtok(NULL, delimiter);

        }
    }
}

例如,下面是我输入一个在标记之间有空格的随机字符串时得到的输出:

# hi there
hi
hi
# byebye

它也应该在“那里”打印出来,但它永远不会到达它。任何帮助将不胜感激!

【问题讨论】:

  • 不要input 流上执行fflush——它会做一些古怪的事情,所以请消除fflush(stdin);
  • 这是做什么的?我本以为大部分时间都清除输入和输出流会很好。
  • 输入流没用/UB。它的唯一有效用途是在输出流上强制 缓冲 输出。充其量,它什么也不做。在最坏的情况下,它会破坏输入缓冲区。有很多 SO 问题/答案可以解释原因。另见man fflush

标签: c shell tokenize strtok


【解决方案1】:

正如我提到的[在我的顶级评论中],input 流上执行fflush

你正在做:

scanf("%s",input);

这只会获得给定行上的 first 标记。因此,如果输入行是(例如)hello world,则scanf 只会将hello 放入input

替换为:

fgets(input,sizeof(input),stdin);

要说明fgets 留在缓冲区中的换行符,请确保delimiter 类似于:

const char *delimiter = " \t\n";

【讨论】:

  • 我讨厌scanf。为胜利而战。
  • 我也讨厌它。我今天/昨天刚刚看到一条评论推荐fgets,并建议scanf 对“新”程序员有太多副作用。我所有的[礼貌]克制添加(例如)“或任何程序员”;-)我认为它是在学校教授的[作为一种方便/快捷方式]但是我已经看到 [方式] 太多 SO 问题 [被无辜、易受影响的年轻程序员 :-) 滥用]
  • 我觉得我们应该发布一个非常简单的库,它更像 Basic 的 INPUT 语句。使用起来会容易得多。
  • 我的第一语言是 Fortran IV [我的第二语言是 Basic],大约在 1972 年。我对 scanf 的印象是它试图用 READ 模仿 Fortran 的 FORMAT 语句。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-11-23
  • 1970-01-01
  • 2017-03-25
  • 2016-08-16
  • 2021-01-19
  • 1970-01-01
相关资源
最近更新 更多