質問
したがって、次のような多項式があります。-4x^ 0 + x ^ 1 + 4x ^ 3-3x ^ 4
これをスペースと「+」でトークン化して、-4x ^ 0、x ^ 1、4x ^ 3、-、3x ^ 4
マイナス記号:-4、1、0、4、-3の係数を取得するにはどうすればよいですか
xは表示される唯一の変数であり、これは常に順番に表示されます
指数を指数とする配列に係数を格納することを計画しています
そのため:-4はインデックス0、1はインデックス1、0はインデックス2、4はインデックス3、-3はインデックス4になります
解決
" -4x ^ 0"、" x ^ 1"などにトークン化したら、strtol()を使用してテキスト表現を数値に変換できます。 strtolは最初の数字以外の文字で自動的に停止するため、「x」で停止します。 strtolは、それを停止した文字へのポインターを提供します。そのため、妄想的になりたい場合は、その文字がxであることを確認できます。
暗黙の1を処理する必要があります(つまり、「x ^ 1」で特別に)。私はこのようなことをします:
long coeff;
if (*token == 'x')
{
coeff = 1;
}
else
{
char *endptr;
coeff = strtol(token, &endptr, 10);
if (*endptr != 'x')
{
// bad token
}
}
他のヒント
Start with "-4x^0 + x^1 + 4x^3 - 3x^4"
Split after ^number: "-4x^0", " + x^1", " + 4x^3", " - 3x^4"
Now everything behind an ^ is an exponent, everything before the x is an coefficient
編集:係数(符号を含む)を取得する簡単な方法:
Init coefficient with 0, sign with '+'
Go through each character before the x from left to right
If it's a number ('0'..'9'), coefficient = coefficient * 10 + number
If it's '-', set sign to '-'
文字列をスキャンして「x」を探し、空白が見つかるまで係数の各文字を逆方向に保存します。例:
for (int i=0; i<s.length(); ++i)
{
if (s[i] == 'x')
{
string c;
for (int j=i-1; j>=0 && s[j]!=' '; --j)
c = s[j] + c;
cout << "coefficient: " << c << endl;
}
}
簡単な解決策として、私のアプローチは再帰降下パーサーを作成することです。文字列内を前方に移動し、必要なコンポーネントを抽出します。このような式のパーサーを記述するための多くの例があります。
ライブラリを使用する場合は、使用するアプローチの種類に応じて、boost :: regexまたはboost :: spiritを使用できます。
単純なトークナイザーを作成します。数値トークン( / [-0123456789] [0123456789] + /
)、指数トークン( / x ^(:: number ::)/
)を定義します。空白と +
を無視します。
トークンは、文字列の最後まで期待どおりに継続的に読み取られます。次に、必要な形式(整数など)でトークンを吐き出します。
int readNumber(const char **input) {
/* Let stdio read it for us. */
int number;
int charsRead;
int itemsRead;
itemsRead = sscanf(**input, "%d%n", &number, &charsRead);
if(itemsRead <= 0) {
// Parse error.
return -1;
}
*input += charsRead;
return number;
}
int readExponent(const char **input) {
if(strncmp("x^", *input, 2) != 0) {
// Parse error.
return -1;
}
*input += 2;
return readNumber(input);
}
/* aka skipWhitespaceAndPlus */
void readToNextToken(const char **input) {
while(**input && (isspace(**input) || **input == '+')) {
++*input;
}
}
void readTerm(const char **input. int &coefficient, int &exponent, bool &success) {
success = false;
readToNextToken(input);
if(!**input) {
return;
}
coefficient = readNumber(input);
readToNextToken(input);
if(!**input) {
// Parse error.
return;
}
exponent = readExponent(input);
success = true;
}
/* Exponent => coefficient. */
std::map<int, int> readPolynomial(const char *input) {
std::map<int, int> ret;
bool success = true;
while(success) {
int coefficient, exponent;
readTerm(&input, coefficient, exponent, success);
if(success) {
ret[exponent] = coefficient;
}
}
return ret;
}
これはおそらく、何らかの抽象化を備えたクラスでうまくいくでしょう(たとえば、プレーンな文字列の代わりにストリームから読み取る)。