#c #string #type-conversion #substring
#c #строка #преобразование типов #подстрока
Вопрос:
Я попытался сделать это с некоторыми подстроками, которые все были натуральными числами
fi = stoi(f[i]) - stoi(s[i]);
se = stoi(s[i]) - stoi(f[i]);
где f и s — это 2 строки. Это было решено, когда я присвоил часть строки новой переменной. Я сталкивался с похожими вещами с atoi(str.c_str()). Почему stoi и atoi ведут себя подобным образом?
Комментарии:
1. Что это
stoi(f[i])
предполагает сделать?2. Превратить подстроку в целое число
3.
f[i] - ‘0’
значение представлено символом цифрыf[i]
.4. Только если значение
f[i]
находится между символами'0'
..'9'
включительно, в противном случае результат будет неопределенным , в зависимости от используемого набора символов.5. Обратите внимание, что C 17 ввел преобразования более низкого уровня в
<charconv>
, которые позволили бы вам делать то, что вы хотите.
Ответ №1:
Почему часть строки не может быть передана в atoi или stoi?
Это возможно, но для получения подстроки из std::string
вам нужно вызвать std::string::substr()
метод. Что-то вроде:
std::stoi( f.substr( i, 1 ) );
предполагая, что вы хотите, чтобы длина подстроки составляла 1 символ, начиная с позиции i
. std::string::operator[]
выдает вам не подстроку, а один символ из этой позиции, т. Е. std::string
может выступать в качестве контейнера символов.
Ответ №2:
Если f
и s
являются string
s, то f[i]
и s[i]
являются одиночными char
s. atoi()
и std::stoi()
не принимают одиночные char
s в качестве входных данных. Они просто не предназначены для такой работы.
atoi()
принимает const char*
в качестве входных данных и ожидает, что это будет указатель на строку в стиле C с нулевым завершением. Итак, чтобы передать ей один char
, вам сначала нужно будет создать char[2]
массив, например:
char arr[] = { f[i], '' };
int i = atoi(arr);
std::stoi()
принимает std::string
в качестве входных данных. Чтобы передать ей один символ char
, вам сначала нужно создать 1 символ std::string
. Однако, std::string
не имеет конструктора, который принимает только один char
в качестве входных данных, но есть много разных способов, которыми вы можете создать 1-символ std::string
, например:
std::string s(1, f[i]);
int i = std::stoi(s);
std::string s(f, i, 1);
int i = std::stoi(s);
std::string s(amp;f[i], 1);
int i = std::stoi(s);
std::string s(f i, f (i 1)); // if f is a char[]/char*
int i = std::stoi(s);
std::string s(f.begin() i, f.begin() (i 1)); // if f is a std::string
int i = std::stoi(s);
std::string s = f.substr(i, 1); // if f is a std::string
int i = std::stoi(s);
std::string s = { f[i] };
int i = std::stoi(s);
std::string s;
s = f[i]; // std::string has an operator=(char) overload
int i = std::stoi(s);
std::string s;
s.resize(1);;
s[0] = f[i];
int i = std::stoi(s);
std::string s = std::string_view(amp;f[i], 1);
int i = std::stoi(s);
При этом, если все char
s находятся между '0'
.. '9'
включительно, то вам не нужно использовать atoi()
/ std::stoi()
для преобразования их в целые числа. Вместо этого просто вычтите '0'
из них, например:
fi = (f[i] - '0') - (s[i] - '0');
se = (s[i] - '0') - (f[i] - '0');
Это работает, потому что в ASCII символы '0'
.. '9'
определяются как последовательные значения 48 .. 57, таким образом, вышесказанное действительно просто делает это:
'0' - '0' = 0
-> 48 - 48 = 0
'1' - '0' = 1
-> 49 - 48 = 1
'2' - '0' = 2
-> 50 - 48 = 2
и так далее…
Комментарии:
1.
std::stoi()
не ожидает строку в стиле C с нулевым завершением.2. @Slava внутренне,
std::stoi()
просто вызываетstd::strtol()
, который ожидает строку C с нулевым завершением.std:string
гарантированно завершается нулем в C 11 и более поздних версиях.