using namespace std;
float str_to_float(char x[]) {
int j;
float val1 = x[0] - '0';
float val2=0,factor=1;
for (int i = 1; x[i] != '.'; i++) {
val1 = (val1 * 10) + (x[i] - '0');
j = i;
}
for (int k = j + 2; k != '\0'; k++) {
**val2 = val2 + (x[k] - '0')*factor;**
factor /= 10;
}
return val1+val2;
}
int main() {
char x[1000];
cin.getline(x, 1000);
cout<<str_to_float(x);
return 0;
}
Эта функция должна возвращать значение с плавающей запятой строки, содержащей число с плавающей запятой. Ошибка возникает в строке, выделенной жирным шрифтом (во втором цикле for), при отладке «нарушения доступа для чтения»
Какое значение будет иметь j
, если x[1]
является десятичной точкой (например, если пользователь введет 1.23
)?
Как вы думаете, что будет делать первый цикл, если строка вообще не содержит десятичной точки? Например "2"
.
С точки зрения стиля вам не нужны i
и k
. Просто используйте j
в качестве переменной управления циклом в обоих циклах. Таким образом, вам не нужно копировать значения вокруг: for (j = 1; x[j] != ‘.’; ++j)
, затем между двумя циклами увеличивать j
после десятичной точки с помощью ++j;
, затем запускать второй цикл for ( ; x[j] != ‘\0’; ++j)
.
Кроме того, эти повторяющиеся деления на 10 вносят ошибки округления, которые накапливаются. Вы получите более точный результат, если просто суммируете цифры справа от запятой как целое число, как в первом цикле, а затем разделите на std::pow(10, n)
, где n
— количество цифр, которые вы видели.
Есть 2 ошибки:
x[k] != '\0'
.factor
должна быть инициализирована как 0.1
.Кроме того, чтобы избежать некоторых ошибок времени выполнения (например, в случае 0,908), начните первый цикл с индекса 0
, чтобы переменная j
имела допустимое значение перед запуском второго цикла.
Взгляните на следующую реализацию:
#include <iostream>
#include <iomanip>
double str_to_double(char x[]) {
int j;
double val1 = 0, val2 = 0.0, factor = 0.1;
for (int i = 0; x[i] != '.'; i++) {
val1 = (val1 * 10) + (x[i] - '0');
j = i;
}
for (int k = j + 2; x[k] != '\0'; k++) {
val2 = val2 + (x[k] - '0')*factor;
factor /= 10;
}
return val1+val2;
}
int main() {
char x[1000];
std::cin.getline(x, 1000);
std::cout<<std::setprecision(15)<<str_to_double(x);
return 0;
}
Тестовые случаи:
Тестовый пример 1: ввод: 34.908
, вывод: 34.908
Тестовый пример 2: ввод: 0.908
, вывод: 0.908
Тестовый пример 3: ввод: 000006795.989090877700000
, вывод: 6795.9890908777
PS: при больших значениях float
и double
может быть потеря точности. Прочтите эту статью.
k != '\0'
Вы действительно не хотите сравнивать индекс в массиве со значением char из массива.