strtok,char **和记忆

时间:2015-02-13 02:53:32

标签: c++ bash strtok

所以我正在开发自己的非常棒的shell(rash),但是当我对字符串进行标记时,我会遇到一些棘手的事情。

似乎某种程度上,即使函数结束(堆栈上没有其他内容),前一次调用仍然有一些遗留问题。

这是我的代码:

int  breakitup (std::string hamma){
    char cstr2[1024];
    char*  pch;
    char* bargv[1024];
    bargv[0] = (char*)"";
    strcpy(cstr2, hamma.c_str());

    //===DEBUGGER PRINT==vv
    std::cerr << "Cstring passed in: ";
    puts(cstr2);
    //===================^^

    pch = strtok(cstr2, " ");

    for( int p = 0; pch != NULL; p++){
        bargv[p] = pch;
        pch = strtok(NULL, " ");
    }

    //===DEBUGGER PRINT==vv
    std::cerr <<"Resulting tokens:\n";
    for(int i = 0; i < 2; i++){
        std::cerr << "*";
        puts(bargv[i]);
    }
    std::cerr << "=======================\n\n";
    //===================^^

    return fcall(bargv);
}

我一直在使用带有2个参数的命令(以避免调试器中明显的段错误)。

对于此示例,我输入:

ls -a
echo hello!
ls
exit (quit rash)

$ ./bin/rshell
rash$ ls -a

===DEBUGGER PRINT===
%ls -a: 0
1ls -a
Cstring passed in: ls -a
Resulting tokens:
*ls
*-a
=======================

.  ..  bin  famcho  fanny  .git  ls  ls.o  lsy  Makefile  .notrshell  obj  readme  README.md  rshell.cpp  shelly  supershell
rash$ echo hello!

===DEBUGGER PRINT===
%echo hello!: 0
1echo hello!
Cstring passed in: echo hello!
Resulting tokens:
*echo
*hello!
=======================

hello!
rash$ ls

===DEBUGGER PRINT===
%ls: 0
1ls
Cstring passed in: ls
Resulting tokens:
*ls
*hello!
=======================

ls: cannot access hello!: No such file or directory
rash$ exit

===DEBUGGER PRINT===
%exit: 0
1exit
Cstring passed in: exit
Resulting tokens:
*exit
*hello!
=======================

Ar revoir!

我在一个广泛的标题下问了这个问题,因为我只能想象char**strtok()的内存问题。但是,嘿,你可能比我更清楚!

1 个答案:

答案 0 :(得分:1)

您的代码存在许多问题。大多数都可以通过使用C ++提供的功能来解决。

您开始使用std::string,但随后进入了&#34; C模式&#34;并且以C ++的方式消除了所有使用安全性和易用性。

因此,使用C ++构造对代码进行基本重写将如下所示:

#include <string>
#include <sstream>
#include <vector>
#include <iostream>
//...
int fcall(std::vector<std::string>& bargv)
{
   //...  you fill this in here
   return 0;
}
//...
//...
int  breakitup (const std::string& hamma)
{
    std::vector<std::string> bargv;
    std::istringstream strm(hamma);
    std::string s;
    while (strm >> s)
    {
        bargv.push_back(s);
        std::cout << s << "\n";
    }
    return fcall(bargv); 
}

int main()
{
    breakitup("This is   a test  string");
}

直播示例:http://ideone.com/zZAgFd

std::istringstreamstd::vector的使用消除了对strtok和手动内存管理的需求。此外,没有缓冲区溢出问题,因为没有硬编码限制。输入字符串可以有1个单词或10,000个单词,用空格分隔,该功能仍然有效。