所以我正在开发自己的非常棒的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()
的内存问题。但是,嘿,你可能比我更清楚!
答案 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");
}
std::istringstream
和std::vector
的使用消除了对strtok
和手动内存管理的需求。此外,没有缓冲区溢出问题,因为没有硬编码限制。输入字符串可以有1个单词或10,000个单词,用空格分隔,该功能仍然有效。