// перечисление типов лексемы
enum PType
{
PType_Int, // коеффициенты и степени
PType_Var, // имена переменных
PType_Op // знаки операций
}
// структура для хранения лексемы
struct ParseResult
{
PType type;
union
{
char* sval;
int ival;
}
value;
}
// собственно, парсинг
ParseResult ParseToken (char *str) { ... }
Работа со строками в С
Привет. Есть задачка, нужно сделать прогу которая бы приводила подобные в многочлене произвольного вида. Например: 3x^2+4x^2+2x+3, ответ: 7x^2+2x+3. Вопрос, как можно узнать значения при коэффициентах х? Функция strchr(), не помогает. Как можно это реализовать или может есть другие простые фукнции, которые позволяют копировать из строки n символов начиная с позиции m?
Для преобразования строки в int - atoi.
Для копирования n символов одной строки в другую - strncpy.
Так как многочлен у Вас произвольного вида, наверное, лучше всего будет написать-таки парсер, который будет последовательно пробегать строку и сохранять лексемы в удобной структуре данных, а затем производить их обработку.
Код:
Как это будет работать:
Допустим, на вход даётся строка "5x^66+22", тогда при первом вызове ParseToken, она вернёт структуру ParseResult с {type = PType_Int, value.ival = 5}, при втором: {type = PType_Var, value.sval = "x"}, при третьем: {type = PType_Op, value.sval = "^"} и т.д.
Ну и хранить где-то надо сколько было пропарсенно символов или указатель строку, следующую за окончанием распарсенной лексемы - это можно тоже в ParseResult впихнуть.
Если бы у меня была куча времени, я бы Вам набросал пример самой функции, но его, к сожалению нет.
Код:
char Text[100];
char z[1];
for (int i = 0; i < strlen(Text); i++)
if (Text == 'x') // Если нашли x, то
z[0] = Text[i - 1]; // Копируем значение левее х.
char z[1];
for (int i = 0; i < strlen(Text); i++)
if (Text == 'x') // Если нашли x, то
z[0] = Text[i - 1]; // Копируем значение левее х.
Но вот тут возникает проблема, скопировать то мы можем только 1 символ, т.е если стоит 25x, то копируется только 5.
Нет ли функции типа Copy, как в паскале?
Я хотел бы сделать так:
Находим х, копируем все символы левее его до начала строки, затем смотрим если у нас есть знак степени ^, если есть, то копируем все символы до знакак + или - ну и так далее.
Ну я ж в прошлом посте писал:
char *strncpy(s, ct, n) - копирует не более n символов из строки ct в строку s.
Т.е. Вы можете в цикле двигаться от x влево до тех пор, пока не встретите не-цифру или не попадёте в нулевую позицию строки и затем копировать подстроку, начинающуюся с этой позиции и кол-вом символов, равным кол-ву шагов от x.
А как можно скопировать n символов не с начала строки, а с позиции x?
Ну так s, ct - указатели (char*). Если s указывает на начало строки, то s+k - на подстроку, начинающуюся с k-го символа включительно. Арифметика указателей.
Цитата: Ander Skirnir
Ну так s, ct - указатели (char*). Если s указывает на начало строки, то s+k - на подстроку, начинающуюся с k-го символа включительно. Арифметика указателей.
А можно примерчик, а то я чета ваще запутался(
Код:
int main (void)
{
char *str1 = "glass",
*str2 = malloc(4); // 'a', 's', 's', '\0'
strncpy(str2, str1+2, 3);
printf(str1); // glass
printf(str2); // ass
}
{
char *str1 = "glass",
*str2 = malloc(4); // 'a', 's', 's', '\0'
strncpy(str2, str1+2, 3);
printf(str1); // glass
printf(str2); // ass
}
Если бы строка str1 была длинее, во вторую всё-равно скопировало бы только "ass", т.к. n = 3.
Код:
int main()
{
char S[255];
char S2[255];
char *st;
char *st2;
int i;
scanf("%s", S);
for (i = 0; i < strlen(S); i++)
{
if ((S == 'x') && (i > 0))
{
strncpy(S2, S, i);
printf("%s %d", S2, i);
}
if (S == '^')
{
st = S;
strncpy(st, st2+2, 1);
printf("\n%s", st);
}
}
}
{
char S[255];
char S2[255];
char *st;
char *st2;
int i;
scanf("%s", S);
for (i = 0; i < strlen(S); i++)
{
if ((S == 'x') && (i > 0))
{
strncpy(S2, S, i);
printf("%s %d", S2, i);
}
if (S == '^')
{
st = S;
strncpy(st, st2+2, 1);
printf("\n%s", st);
}
}
}
Накидал код, вот элемент левее х находится, а правее ^ нет. Да вообще для сравнения я использую просто строку, а вот для копирования указатель. Только вообще ни черта не выходит. Ваще строки в С дерьмо еще то.
в Си нет строк
>>строки в С дерьмо еще то
см. выше
Строки эмулируются массивами символов и указателями.
Просто Си для других целей - это такой ассемблер со слегка повышенным уровнем абстракции. Его целесообразно использовать для высокой производительности и переносимости. В C++, например, есть класс string - и всё там красиво и удобно, но работает он, конечно же, гораздо медленее, чем сишные низкоуровневые операции с указателями.
И еще: в последнем Вашем посте коеффициент при x находит неправильно: у Вас копирование начинается с начала строки, а нужно начинать с места, где начинается сам коеффициент.
Вот пример:
Код:
#include <stdio.h>
// byte в коде будет заменяться на unsigned char - число в диапазоне [0; 255]
typedef unsigned char byte;
int parse_koef (char *str, byte spos)
{
char sk [8];
byte i, k = 0,
j = spos ? spos - 1 : 0; // если spos > 0, то j = spos - 1, иначе j = 0
for (i = spos ? spos : 1; i < strlen(str); ++j, ++i)
if (str == 'x')
{
while (isdigit(str[j])) // пока str[j] - десятичная цифра
{
if (j == 0) break;
++k, --j;
}
strncpy(sk, str + i - k, k);
sk[k] = '\0';
break;
}
return atoi(sk);
}
int main()
{
char *s = "122 + 52 + 43 + 6522x + 235x";
int k1 = parse_koef(s, 0);
printf("k1 = %d\n", k1);
int k2 = parse_koef(s, 22);
printf("k2 = %d\n", k2);
}
// byte в коде будет заменяться на unsigned char - число в диапазоне [0; 255]
typedef unsigned char byte;
int parse_koef (char *str, byte spos)
{
char sk [8];
byte i, k = 0,
j = spos ? spos - 1 : 0; // если spos > 0, то j = spos - 1, иначе j = 0
for (i = spos ? spos : 1; i < strlen(str); ++j, ++i)
if (str == 'x')
{
while (isdigit(str[j])) // пока str[j] - десятичная цифра
{
if (j == 0) break;
++k, --j;
}
strncpy(sk, str + i - k, k);
sk[k] = '\0';
break;
}
return atoi(sk);
}
int main()
{
char *s = "122 + 52 + 43 + 6522x + 235x";
int k1 = parse_koef(s, 0);
printf("k1 = %d\n", k1);
int k2 = parse_koef(s, 22);
printf("k2 = %d\n", k2);
}
Здесь parse_koef находит для заданной строки коеффициент при первом х, встречающемся после заданной позиции.
k1 = 6522
k2 = 235