我正在尝试在Linux中实现自己的shell。我从用户那里获取输入并解析它。但是当我在数组中复制我的标记时,它会出现分段错误。我无法解决这个问题。
这是我实施的代码
#include <iostream>
#include <sys/wait.h>
#include <unistd.h>
#include <string.h>
using namespace std;
int main ()
{
char * input;
string insert;
cout<<"My Shell $";
getline(cin,insert);
input= new char [insert.size()+1];
strcpy(input, insert.c_str());
char * token;
char * parsed[100];
int count;
token=strtok(input, " ");
while (token!=NULL)
{
strcpy(parsed[count],&(token[count]));
count++;
token=strtok(NULL, " ");
}
}
答案 0 :(得分:3)
#include <string.h>
没有
如果您想要C函数,请使用<cstring>
,将它们放在std::
命名空间中。
但你不想想要 C函数,你想要C ++ <string>
。相信我,你做到了。
using namespace std;
为了这个例子,我会让那个过去。在任何生产代码中摆脱这种特殊习惯。
getline(cin,insert);
好。你已经准备好做C ++了。
input= new char [insert.size()+1];
strcpy(input, insert.c_str());
坏。你只是将双手绑在背后。
char * parsed[100];
一个包含100个char指针的数组。只是指针,未初始化,指向无处。
int count;
未初始化。
token=strtok(input, " ");
℃。 颤动 ....
strcpy(parsed[count],&(token[count]));
未定义的行为。 count
未初始化,即使 恰好在0到99之间,parsed[count]
仍未指向有效内存,因此将内容复制到其中将做坏事。
此外,您的令牌位于token
,而不是token[count]
...
count++;
在未初始化时添加1是UB,仍然未初始化。 ; - )
}
你忘了delete [] input
。
让我建议一个不同的,更多的C ++ - ish方法,它仍然会给你指向每个标记的指针数组(如果你坚持的话):
getline( cin, input );
// turn spaces to null bytes
std::replace( input.begin(), input.end(), ' ', '\0' );
// need an additional one for the finds below to work
input.append( '\0' );
// vector takes away all of that manual memory management
std::vector< char * > parsed;
size_t i = 0;
// skip leading (ex-) spaces
while ( ( i = input.find_first_not_of( '\0', i ) ) != std::string::npos )
{
// push the pointer to the token on the vector
parsed.push_back( input.data() + i );
// skip to end of token
i = input.find( '\0', i );
}
此时,parsed
是vector
中char *
input
的代币input
(至少,只要parsed.size()
本身仍在范围)。您可以使用parsed.data()
检查其大小,并使用vector
将其作为“裸”数组访问,但我相信您会发现input
更方便。
如果您不想保留std::vector< char * > parsed;
,请替换
std::vector< std::string > parsed;
与
parsed.push_back( input.data() + i );
和
parsed.push_back( std::string( input.data() + i ) );
与
vector
您的if (list != null)
{
while (continue_)
{
i++;
Thread.Sleep(5000);
Thread thrd1 = new System.Threading.Thread(() => Test());
thrd1.Start();
}
}
中有令牌的副本。
这仍然是非常粗略的处理,请注意,因为引号内的偶数空格将被检测为“令牌结束”,但至少它是C ++,没有C字符串处理。
答案 1 :(得分:1)
变量int count未定义,意味着它可以是随机值,将其更改为int count = 0;
答案 2 :(得分:1)
您没有初始化变量count
,并且其值未定义(可能非常大,因此程序将无法从内存中读取)。您应该使用int count = 0;
。
数组parsed
中的元素未初始化,也未指向已分配的内存。您对strcpy
的调用行为也未定义。在致电parsed[count] = new char[strlen(token) + 1];
之前添加strcpy
。一切都完成后,不要忘记使用delete
。
最后,我认为您没有正确使用strtok
。你为什么用&(token[count])
?也许你应该用token
替换它。
答案 3 :(得分:0)
只需将您的计数变量初始化为0
答案 4 :(得分:0)
Please try to use this code. I tried in VS2010 and it is working fine now.
#include <iostream>
#include <string.h>
#include <string>
using namespace std;
int main (void)
{
char* input = NULL;
string insert;
cout<<"My Shell $";
/* getline(cin, insert);*/
std::getline(cin, insert);
input= new char[insert.size() + 1];
strcpy(input, insert.c_str());
char* token = NULL;
char* parsed[100] = {0};
int count = 0;
token = strtok(input, " ");
while ( token != NULL)
{
parsed[count] = token;
count++;
token = strtok(NULL, " ");
}
for ( int index = 0; index<count; index++ )
{
cout << parsed[index] << std::endl;
}
system("pause");
return 0;
}
答案 5 :(得分:-1)
请尝试以下代码#
#include <iostream>
#include <unistd.h>
#include <string.h>
using namespace std;
int main (void)
{
char* input = NULL;
string insert;
cout<<"My Shell $";
getline(cin, insert);
input= new char[insert.size() + 1];
strcpy(input, insert.c_str());
char* token = NULL;
char* parsed[100];
for (int index = 0; index < 100; index++)
{
parsed[index] = NULL;
}
int count = 0;
token = strtok(input, " ");
while ( token != NULL)
{
strcpy(parsed[count], &(token[count]));
count++;
token = strtok(NULL, " ");
}
return 0;
}