我最终尝试编写shell,因此我需要能够解析命令。我试图将每个单词和特殊符号转换为标记,同时忽略空格。当分隔标记的字符为|时,它起作用&安培; < >但是只要我使用一个空格字符,程序就会崩溃。那是为什么?
我是学生,我意识到我想出分离令牌的方式相当粗糙。我很抱歉。
#include <iostream>
#include <stdio.h>
#include <string>
#include <cctype>
using namespace std;
#define MAX_TOKENS 10
int main()
{
//input command for shell
string str;
string tokens[MAX_TOKENS] = { "0", "0", "0", "0", "0", "0", "0", "0", "0", "0" };
int token_index = 0;
int start_token = 0;
cout << "Welcome to the Shell: Please enter valid command: " << endl << endl;
cin >> str;
for (unsigned int index = 0; index < str.length(); index++)
{
//if were at end of the string, store the last token
if (index == (str.length() - 1)) tokens[token_index++] = str.substr(start_token, index - start_token + 1);
//if char is a whitespace store the token
else if (isspace(str.at(index)) && (index - start_token > 0))
{
tokens[token_index++] = str.substr(start_token, index - start_token);
start_token = index + 1;
}
//if next char is a special char - store the existing token, and save the special char
else if (str[index] == '|' || str[index] == '<' || str[index] == '>' || str[index] == '&')
{
//stores the token before our special character
if ((index - start_token != 0)) //this if stops special character from storing twice
{
//stores word before Special character
tokens[token_index++] = str.substr(start_token, index - start_token);
}
//stores the current special character
tokens[token_index++] = str[index];
if (isspace(str.at(index + 1))) start_token = index + 2;
else start_token = index + 1;
}
}
cout << endl << "Your tokens are: " << endl;
for (int i = 0; i < token_index; i++)
{
cout << i << " = " << tokens[i] << endl;
}
return 0;
}
答案 0 :(得分:1)
一些事情:
token_index
是否小于MAX_TOKENS
,然后在每次增量后再次使用它,否则会出现缓冲区溢出。如果您将tokens
更改为std::vector
,那么您可以使用at()
语法作为安全网。index - start_token
的类型为unsigned int
,因此永远不会少于0
。相反,你应该做index > start_token
测试。str.at(index)
超出范围,则index
会引发异常。但是你永远不会遇到异常;根据您的编译器,这可能看起来像程序崩溃。在main()
块中包装try...catch(std::exception &)
的代码。最后,这是一个很长的镜头,但我会提到它的完整性。最初在C89中,isspace
和其他is
函数必须采用非负参数。它们的设计使编译器可以通过数组查找实现它们,因此传入带有负值的带符号的char会导致未定义的行为。我不完全确定它是否在各种更高版本的C和C ++中“修复”,但即使标准要求它,你也可能有一个仍然不喜欢接收负面字符的编译器。要从代码中消除这种可能性,请使用isspace( (unsigned char)str.at(index) )
,甚至更好,使用C ++语言环境接口。