Сложный алгоритм для извлечения чисел / числового диапазона из строки

Я работаю над алгоритмом, в котором я пытаюсь следующий вывод:

Заданные значения / входы:

char *Var = "1-5,10,12,15-16,25-35,67,69,99-105";
int size = 29;

Вот «1-5» отображает значение диапазона, то есть оно будет пониматься как «1,2,3,4,5» в то время как значения просто «» являются индивидуальными ценностями.

Я писал алгоритм, в котором конечный вывод должен быть таким, чтобы он давал полный диапазон вывода как:

int list[]=1,2,3,4,5,10,12,15,16,25,26,27,28,29,30,31,32,33,34,35,67,69,99,100,101,102,103,104,105;

Если кто-то знаком с этой проблемой, то помощь будет очень признателен.
Заранее спасибо!

Мой исходный код был такой:

if(NULL != strchr((char *)grp_range, '-'))
{
int_u8 delims[] = "-";
result = (int_u8 *)strtok((char *)grp_range, (char *)delims);

if(NULL != result)
{
start_index = strtol((char*)result, (char **)&end_ptr, 10);
result = (int_u8 *)strtok(NULL, (char *)delims);
}

while(NULL != result)
{
end_index = strtol((char*)result, (char**)&end_ptr, 10);
result = (int_u8 *)strtok(NULL, (char *)delims);
}

while(start_index <= end_index)
{
grp_list[i++] = start_index;
start_index++;
}
}

else if(NULL != strchr((char *)grp_range, ','))
{
int_u8 delims[] = ",";
result = (unison_u8 *)strtok((char *)grp_range, (char *)delims);

while(result != NULL)
{
grp_list[i++] = strtol((char*)result, (char**)&end_ptr, 10);
result = (int_u8 *)strtok(NULL, (char *)delims);
}
}

Но это работает, только если у меня есть «0-5» или «0,10,15». Я с нетерпением жду, чтобы сделать его более универсальным.

-5

Решение

Ваша проблема, кажется, неправильно понимает, как работает strtok. Посмотри на это!

#include <string.h>
#include <stdio.h>

int main()
{
int i, j;
char delims[] = " ,";
char str[] = "1-5,6,7";
char *tok;
char tmp[256];
int rstart, rend;

tok = strtok(str, delims);

while(tok != NULL) {
for(i = 0; i < strlen(tok); ++i) {
//// range
if(i != 0 && tok[i] == '-') {
strncpy(tmp, tok, i);
rstart = atoi(tmp);
strcpy(tmp, tok + i + 1);
rend = atoi(tmp);
for(j = rstart; j <= rend; ++j)
printf("%d\n", j);
i = strlen(tok) + 1;
}
else if(strchr(tok, '-') == NULL)
printf("%s\n", tok);
}

tok = strtok(NULL, delims);
}

return 0;
}
2

Другие решения

Вот решение C ++ для изучения.

#include <vector>
#include <string>
#include <sstream>
#include <iostream>
using namespace std;

int ConvertString2Int(const string& str)
{
stringstream ss(str);
int x;
if (! (ss >> x))
{
cerr << "Error converting " << str << " to integer" << endl;
abort();
}
return x;
}

vector<string> SplitStringToArray(const string& str, char splitter)
{
vector<string> tokens;
stringstream ss(str);
string temp;
while (getline(ss, temp, splitter)) // split into new "lines" based on character
{
tokens.push_back(temp);
}
return tokens;
}

vector<int> ParseData(const string& data)
{
vector<string> tokens = SplitStringToArray(data, ',');

vector<int> result;
for (vector<string>::const_iterator it = tokens.begin(), end_it = tokens.end(); it != end_it; ++it)
{
const string& token = *it;
vector<string> range = SplitStringToArray(token, '-');
if (range.size() == 1)
{
result.push_back(ConvertString2Int(range[0]));
}
else if (range.size() == 2)
{
int start = ConvertString2Int(range[0]);
int stop = ConvertString2Int(range[1]);
for (int i = start; i <= stop; i++)
{
result.push_back(i);
}
}
else
{
cerr << "Error parsing token " << token << endl;
abort();
}
}

return result;
}

int main()
{
vector<int> result = ParseData("1-5,10,12,15-16,25-35,67,69,99-105");
for (vector<int>::const_iterator it = result.begin(), end_it = result.end(); it != end_it; ++it)
{
cout << *it << " ";
}
cout << endl;
}

Живой пример

http://ideone.com/2W99Tt

3

Это мой подход к повышению:

Это не даст вам массив целых, вместо вектора целых

Используемый алгоритм: (ничего нового)

  • Разделить строку с помощью ,

  • Разделить отдельные строки, используя -

  • Сделать диапазон low а также high

  • Вставьте его в вектор с помощью этого диапазона

Код:-

#include<iostream>
#include<vector>
#include <boost/algorithm/string.hpp>
#include <boost/lexical_cast.hpp>int main(){

std::string line("1-5,10,12,15-16,25-35,67,69,99-105");
std::vector<std::string> strs,r;
std::vector<int> v;
int low,high,i;
boost::split(strs,line,boost::is_any_of(","));

for (auto it:strs)
{
boost::split(r,it,boost::is_any_of("-"));

auto x = r.begin();
low = high =boost::lexical_cast<int>(r[0]);
x++;
if(x!=r.end())
high = boost::lexical_cast<int>(r[1]);
for(i=low;i<=high;++i)
v.push_back(i);
}

for(auto x:v)
std::cout<<x<<" ";

return 0;

}
3

Не ищите. Просто просмотрите текст по одному символу за раз. Пока вы видите цифры, накапливайте их в значение. Если за цифрами следует - затем вы смотрите на диапазон, и вам нужно проанализировать следующий набор цифр, чтобы получить верхнюю границу диапазона и поместить все значения в ваш список. Если значение не сопровождается - тогда у вас есть одно значение; положить его в свой список.

2

Остановись и подумай: на самом деле у тебя запятая
разделенный список диапазонов, где диапазон может быть одним
номер или пара чисел, разделенных '-', Так что вы
вероятно, хотите перебрать диапазоны, используя рекурсивный спуск
для разбора. (Подобные вещи лучше всего обрабатываются
istreamвот что я буду использовать.)

std::vector<int> results;
std::istringstream parser( std::string( var ) );
processRange( results, parser );
while ( isSeparator( parser, ',' ) ) {
processRange( results, parser );
}

с:

bool
isSeparator( std::istream& source, char separ )
{
char next;
source >> next;
if ( source && next != separ ) {
source.putback( next );
}
return source && next == separ;
}

а также

void
processRange( std::vector<int>& results, std::istream& source )
{
int first = 0;
source >> first;
int last = first;
if ( isSeparator( source, '-' ) ) {
source >> last;
}
if ( last < first ) {
source.setstate( std::ios_base::failbit );
}
if ( source ) {
while ( first != last ) {
results.push_back( first );
++ first;
}
results.push_back( first );
}
}

isSeparator функция, вероятно, будет полезна в
другие проекты в будущем, и должны быть сохранены в вашем
ящик для инструментов.

2

Сначала разделите всю строку на числа и диапазоны (используя strtok () с разделителем «,»), сохраните строки в массиве, затем выполните поиск в массиве, ища «-«, если он присутствует, чем используйте sscanf () с «% d-% Формат d, иначе используйте sscanf с одним форматом «% d».

Использование функции легко гуглится.

0

Один подход:

Вам нужен анализатор, который идентифицирует 3 вида токенов: ‘,’, ‘-‘ и числа. Это повышает уровень абстракции, так что вы работаете на уровне выше символов.

Затем вы можете проанализировать поток токенов, чтобы создать список диапазонов и констант.

Затем вы можете проанализировать этот список, чтобы преобразовать диапазоны в константы.

Некоторый код, который выполняет часть работы:

#include <stdio.h>

// Prints a comma after the last digit. You will need to fix that up.
void print(int a, int b) {
for (int i = a; i <= b; ++i) {
printf("%d, ", i);
}
}

int main() {
enum { DASH, COMMA, NUMBER };
struct token {
int type;
int value;
};

// Sample input stream. Notice the sentinel comma at the end.
// 1-5,10,
struct token tokStream[] = {
{ NUMBER, 1 },
{ DASH, 0 },
{ NUMBER, 5 },
{ COMMA, 0 },
{ NUMBER, 10 },
{ COMMA, 0 } };

// This parser assumes well formed input. You have to add all the error
// checking yourself.
size_t i = 0;
while (i < sizeof(tokStream)/sizeof(struct token)) {
if (tokStream[i+1].type == COMMA) {
print(tokStream[i].value, tokStream[i].value);
i += 2;  // skip to next number
}
else { // DASH
print(tokStream[i].value, tokStream[i+2].value);
i += 4;  // skip to next number
}
}

return 0;
}
0
По вопросам рекламы [email protected]