首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >理解strtok()

理解strtok()
EN

Stack Overflow用户
提问于 2018-09-23 19:12:22
回答 2查看 85关注 0票数 0

以下是代码:

代码语言:javascript
复制
#include <string>
#include <string.h>
#include <algorithm>
#include <iostream>
#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>
#include <vector>

using namespace std;

const string PROMPT = "prompt> ";
const char PIPE_DEL[3] = "||";

bool checkInput(char []);


bool checkInput(char cmd[]){
    string command = cmd;
    transform(command.begin(), command.end(), command.begin(), ::tolower);
    if (command == "q" || command == "quit")
        return true;
    else
        return false;   
}




int main(){
    int iteration = 0;
    while (true){
        char command[1024];
        pid_t pid;

        cout << '\n' << iteration << '\n';
        cout << PROMPT;
        cin >> command;

        if ( checkInput(command) )
            break;

        char* token = strtok(command, PIPE_DEL);
        vector<string> commands;
        commands.push_back(token);


        cout << "command 1: " << commands[0] << "\n";
        iteration ++;

    }
    return 0;
}

1)“”被算作分隔符!如果我错了,请纠正我,但唯一算作分隔符的是第二个参数中字符串中的内容。这里的情况并非如此,因为我的分隔符字符串中没有“”,但它被计算为“”。

( 2)为什么执行命令都不正常?如果有两个标记,程序将跳过一些代码。

以下是一些输出:

prompt>你好 命令1:你好 1

这是意料之中的。该分隔符中没有匹配的字符,然后打印出整个字符串。

prompt>你好世界 命令1:你好 1 prompt>命令1: world 2

这完全出乎意料。首先,“”不是分隔符。第二,为什么cin被跳过?为什么正在打印第一个分隔符的cout语句在cin之前运行?为什么输入是第二个令牌?例如,运行以下命令:

prompt> hello退出 命令1:你好 1

终止程序(如果cin读取“q”或“退出”,则程序终止)。这证明cin被忽视了,或者至少不像我预期的那样起作用了。cin应该停止,从控制台读取,并将其放入数组命令中。然而,由于strtok()修改了输入字符串,所以命令保存“退出”,但是这应该被覆盖。

char command1024;

3)最后输出

prompt> hello = world 命令1:你好 1 的实例后调用prompt>终止 'std::logic_error‘what():basic_string::_M_construct null not 有效中止

再说一遍,“”不是分隔符。令牌1应该是"hello“令牌2(如果我决定解析它)应该是”world“。这个错误不应该存在。

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2018-09-23 20:49:29

多亏了我的回答,我才能解决我所遇到的问题。以下是我所做的:

代码语言:javascript
复制
const string PROMPT = "prompt> ";
const string PIPE_DEL = "||";

bool checkInput(string);


bool checkInput(string command){
    transform(command.begin(), command.end(), command.begin(), ::tolower);
    if (command == "q" || command == "quit")
        return true;
    else
        return false;   
}


vector<string> getCommands(string command){
    vector<string> commands;

    size_t tokenStart = 0, tokenEnd;
    while ( (tokenEnd = command.find(PIPE_DEL, tokenStart)) != string::npos ){
        commands.push_back(command.substr(tokenStart, tokenEnd - tokenStart));
        tokenStart = tokenEnd + PIPE_DEL.length();
    }
    commands.push_back(command.substr(tokenStart, command.length()));

    return commands;
}




int main(){
    int iteration = 0;
    while (true){
        string command;
        pid_t pid;

        cout << '\n' << iteration << endl;
        cout << PROMPT;
        getline(cin, command);

        if ( checkInput(command) )
            break;

        vector<string> commands = getCommands(command);

        iteration ++;

    }
    return 0;
}

和以前一样,这里有字符数组,我严格地使用字符串对象。我还使用string类中的find函数来解析分隔符,而不是strtok()。最后,cin不能正确地解析空间。我把它换成了:

代码语言:javascript
复制
getline(cin, command);

但是,正如@Christophe所指出的,您也可以使用:

代码语言:javascript
复制
cin.getline(command,1024);

在这种情况下,命令是一个字符数组,而1024是要读取的字符数。

票数 1
EN

Stack Overflow用户

发布于 2018-09-23 20:09:33

有几个问题。

首先,提取器cin>>command;将在接收到的第一个空格处停止。如果你想得到一个完整的队伍,你需要做:

代码语言:javascript
复制
    cin.getline(command,1024);

然后,如果没有更多的输入或出现错误,您可能仍然面临问题,因为您总是执行以下内容,即使没有收到任何输入。最好的方法是重写循环逻辑,以便循环:

代码语言:javascript
复制
    while (cin.getline(command,1024)) { 
    ...
    }

那么strtok()就不会像您所期望的那样处理多个字符。实际上,它需要不同的分隔符,每个分隔符都可以作为标记的结尾。但是,您输入的令牌的末尾将仅为列表之一。

最后,您只将第一个令牌推到commands向量中。

备注:使用strtok()不是最好的主意。一个更好的选择是在代码中使用字符串,并使用算法查找分隔符,例如https://ideone.com/JQjU1T

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/52469415

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档