Как сравнить номера версий в С++
Наш профессор хочет, чтобы мы записали программу для сравнения двух номеров версий, таких как 0,1 < 0,2 или 1 < 1.1. Также есть некоторые трюки, такие как .0.4 < 0,1.
Итак, моя идея - первый судья, если число начинается как точка, если это так, я добавляю 0 к нему. После этого я удаляю другие точки, кроме первого. Затем я конвертирую строку в число и сравниваю ее. Вот что я делаю на первом шаге.
string numb1,numb2;
if(numb1[0]=='.')
{
numb1 ="0"+ numb1;
}
Я делаю то же самое со вторым номером. И теперь мне нужна помощь, чтобы показать мне, как удалить точки, кроме первой.
Наш профессор хочет, чтобы мы использовали эту специфическую функцию:
int compareVersions (строка ver1, строка ver2).
Если ver1 > ver2: return 1
если ver1 < ver2: return -1
иначе возвращаем 0.
Кстати, часть видения может очень долгое время напоминать 2.3.2.2.3.1.1.5.3.5.6.2 или 1.1.1.1.1.1.1.
Ответы
Ответ 1
Здесь один подход, который должен работать для числовых номеров версий:
- Разделите входные строки на куски, используя
getline(strstream, token, ".")
- Преобразуйте соответствующие фигуры в числа с помощью
atoi
или stol
и сравните численно
В принципе, обрабатывайте номера версий как последовательности чисел, разделенные символом .
, и сравнивайте эти последовательности лексикографически.
Обратите внимание, что практический, общий алгоритм сравнения номеров версий, вероятно, должен обрабатывать дополнительную хитрость, такую как суффиксы букв (например, 1.1e
, 2.4b24
, 3.5rc1
) и т.д. Я предполагаю, что это выходит за рамки упражнений класса, но подход аналогичен: разделите эти части на последовательности числовых и нечисловых частей и сравните каждую часть (например, 2.4b7 < 2.4b24
, потому что 4, "b", 7 < 4, "b", 24
).
Ответ 2
Так как вы знаете, что numb[1]
будет равно '.' вы можете просто использовать
numb1.erase(std::remove(numb1.begin() + 2, numb1.end(), '.'), numb1.end());
Что бы удалить все точки в numb1
после второго символа.
Ответ 3
Что вам нужно сделать, это перебрать строку, игнорируя ".". и преобразование представлений чисел char в ints. Затем сравните два конечных результата.
string numb1 = "4.3.2";
string numb2 = "3.4.5";
int n1 = 0;
int n2 = 0;
for (int i = 0; i < numb1.length(); i++)
{
if (numb1[i] != '.')
{
n1 = n1 * 10;
n2 = n2 * 10;
n1 += (int(numb1[i]) - '0');
n2 += (int(numb2[i]) - '0');
}
}
Это даст вам 432 и 345, сравнивая их с тем, что является более высокой версией.
Ответ 4
Что-то вроде этого будет работать, чтобы сделать проверку и довольно минимально. Он использует boost для разделения строки, а затем поэтапно сравнивает версию. Он автоматически обрабатывает отсутствующие начальные нули.
#include <boost/algorithm/string.hpp>
#include <string>
#include <vector>
#include <iostream>
int version_a_newer_than_b(const std::string& a, const std::string& b)
{
// First, split the string.
std::vector<std::string> va, vb;
boost::split(va, a, boost::is_any_of("."));
boost::split(vb, b, boost::is_any_of("."));
// Compare the numbers step by step, but only as deep as the version
// with the least elements allows.
const int depth = std::min(va.size(), vb.size());
int ia,ib;
for (int i=0; i<depth; ++i)
{
ia = atoi(va[i].c_str());
ib = atoi(vb[i].c_str());
if (ia != ib)
break;
}
// Return the required number.
if (ia > ib)
return 1;
else if (ia < ib)
return -1;
else
{
// In case of equal versions, assumes that the version
// with the most elements is the highest version.
if (va.size() > vb.size())
return 1;
else if (va.size() < vb.size())
return -1;
}
// Everything is equal, return 0.
return 0;
}
int main()
{
std::string a = "0.1.32.8";
std::string b = "0.1";
std::cout << "Is a newer than b: " << version_a_newer_than_b(a, b) << std::endl;
return 0;
}
Ответ 5
В следующем примере будет показано сравнение формата следующей версии:
major.minor.revision.build
или любую более короткую версию, например, только major
, в то время как она позволяет вам продлить ее в соответствии с вашими потребностями, начиная с
"some of the version numbers may be very long like 2.3.2.2.3.1.1.5.3.5.6.2"
Используя пример ниже, точки в начале и конце строки версии позаботятся, поскольку .0.4
считается равным 0.0.4
, а .1.
считается равным 0.1.0
.
CompareVersion.h
#ifndef COMPAREVERSION_H_
#define COMPAREVERSION_H_
#include <cstdio>
#include <string>
#include <iostream>
using namespace std;
struct CompareVersion {
public:
int maj;
int min;
int rev;
int build;
CompareVersion(std::string);
bool operator < (const CompareVersion&);
bool operator <= (const CompareVersion&);
bool operator == (const CompareVersion&);
friend std::ostream& operator << (std::ostream& stream, const CompareVersion& ver) {
stream << ver.maj;
stream << '.';
stream << ver.min;
stream << '.';
stream << ver.rev;
stream << '.';
stream << ver.build;
return stream;
};
void reset();
};
#endif /* COMPAREVERSION_H_ */
CompareVersion.cpp
#include "CompareVersion.h"
CompareVersion::CompareVersion(std::string version)
{
reset();
if (version.compare(0,1,".") == 0)
version = "0"+version;
if (version.compare(version.size()-1,1,".") == 0)
version.append("0");
sscanf(version.c_str(), "%d.%d.%d.%d", &maj, &min, &rev, &build);
if (maj <= 0) maj = 0;
if (min <= 0) min = 0;
if (rev <= 0) rev = 0;
if (build <= 0) build = 0;
}
bool CompareVersion::operator < (const CompareVersion& other)
{
if (maj < other.maj) return true;
if (min < other.min) return true;
if (rev < other.rev) return true;
if (build < other.build) return true;
return false;
}
bool CompareVersion::operator <= (const CompareVersion& other)
{
if (maj >= other.maj) return true;
if (min >= other.min) return true;
if (rev >= other.rev) return true;
if (build >= other.build) return true;
return false;
}
bool CompareVersion::operator == (const CompareVersion& other)
{
return maj == other.maj
&& min == other.min
&& rev == other.rev
&& build == other.build;
}
void CompareVersion::reset()
{
maj = 0;
min = 0;
rev = 0;
build = 0;
}
main.cpp
#include <iostream>
#include "CompareVersion.h"
using namespace std;
int main()
{
if((CompareVersion("1.2.3.4") == CompareVersion("1.2.3.4")) == true)
cout << "Version 1.2.3.4 and version 1.2.3.4 are equal" << endl;
if((CompareVersion("1.2.3.3") < CompareVersion("1.2.3.4")) == true)
cout << "Version 1.2.3.3 is smaller than 1.2.3.4. " << endl;
if((CompareVersion("1.2.3.4") < CompareVersion("1.2.3.4")) == true)
cout << "You won't see that. " << endl;
if((CompareVersion("1.2.3.4") <= CompareVersion("1.2.3.4")) == true)
cout << "Version 1.2.3.4 is smaller or equal to 1.2.3.4" << endl;
if((CompareVersion("1") <= CompareVersion("1.0.0.1")) == true)
cout << "Version 1 is smaller or equal to 1.0.0.1" << endl;
/* THE DOTS */
if((CompareVersion(".0.4") == CompareVersion("0.0.4")) == true)
cout << "Version .0.4 and version 0.0.4 are equal" << endl;
if((CompareVersion(".1.") == CompareVersion("0.1.0")) == true)
cout << "Version .1. and version 0.1.0 are equal" << endl;
if((CompareVersion("1") == CompareVersion("1.0.0.0")) == true)
cout << "Version 1 and version 1.0.0.0 are equal" << endl;
return 0;
}
Выход
Version 1.2.3.4 and version 1.2.3.4 are equal
Version 1.2.3.3 is smaller than 1.2.3.4.
Version 1.2.3.4 is smaller or equal to 1.2.3.4
Version 1 is smaller or equal to 1.0.0.1
Version .0.4 and version 0.0.4 are equal
Version .1. and version 0.1.0 are equal
Version 1 and version 1.0.0.0 are equal