Я неправильно использую atoi?

У меня были некоторые проблемы с моей функцией синтаксического анализа, поэтому я добавил несколько операторов cout, чтобы сообщить мне значение определенных переменных во время выполнения, и я считаю, что atoi неправильно преобразует символы.

Вот короткий фрагмент моего кода, который ведет себя странно:

c = data_file.get();
if (data_index == 50)
    cout << "50 digit 0 = '" << c << "' number = " << atoi(&c) << endl;

вывод для этого оператора: 50 digit 0 = '5' number = 52

Я вызываю этот код в цикле, и что странно, он правильно преобразует первые 47 символов, затем к 48-му символу добавляет 0 после целого числа, к 49-му символу добавляет 1, к 50-му (см. здесь) он добавляет двойку вплоть до 57-го символа, где он добавляет 9, затем продолжает корректное преобразование вплоть до 239-го символа.

Это странно или что?

Просто чтобы уточнить немного больше, я опубликую всю функцию. Этой функции передается указатель на пустой двойной массив (ping_data):

int parse_ping_data(double* ping_data)
{
    ifstream data_file(DATA_FILE);

    int pulled_digits [4];
    int add_data;
    int loop_count;
    int data_index = 0;

    for (char c = data_file.get(); !data_file.eof(); c = data_file.get())
    {
        if (c == 't' && data_file.get() == 'i' && data_file.get() == 'm' && data_file.get() == 'e' && data_file.get() == '=')
        {
            loop_count = 0;
            c = data_file.get();
            if (data_index == 50)
                    cout << "50 digit 0 = '" << c << "' number = " << atoi(&c) << endl;
            pulled_digits[loop_count] = atoi(&c);

            while ((c = data_file.get()) != 'm')
            {
                loop_count++;
                if (data_index == 50)
                    cout << "50 digit " << loop_count << " = '" << c << "' number = " << atoi(&c) << endl;
                pulled_digits[loop_count] = atoi(&c);
            }
            add_data = 0;
            for (int i = 0; i <= loop_count; i++)
                add_data += pulled_digits[loop_count - i] * (int)pow(10.0,i);

            if (data_index == 50)
                cout << "50 index = " << add_data << endl;
            ping_data[data_index] = add_data;
            data_index++;

            if (data_index >= MAX_PING_DATA)
            {
                cout << "Error parsing data. Exceeded maximum allocated memory for ping data." << endl;
                return MAX_PING_DATA;
            }   
        }
    }

    data_file.close();

    return data_index;
}

person Ring    schedule 27.11.2009    source источник


Ответы (3)


atoi принимает строку, то есть массив char с нулевым завершением, а не указатель на один char, поэтому это неверно и приведет к непредсказуемым результатам.

char c;
//...
/* ... */ atoi(&c) /* ... */

Кроме того, atoi не позволяет обнаруживать ошибки, поэтому отдавайте предпочтение strtol и подобным функциям.

E.g.

char *endptr;
char c[2] = {0}; // initalize c to all zero

c[0] = data.file.get(); // c[1] is the null terminator

long l = strtol(c, &endptr, 10);

if (endptr == c)
    // an error occured
person CB Bailey    schedule 27.11.2009

atoi ожидает на входе строку с завершающим нулем. То, что вы предоставляете, не является строкой с нулевым завершением.

Сказав это, всегда стоит добавить, что очень сложно (если вообще возможно) правильно использовать atoi. atoi — это функция, которая не предлагает ни контроля ошибок, ни контроля переполнения. Единственный правильный способ выполнить преобразование строкового представления в число в стандартной библиотеке C — это функции из группы strto....

На самом деле, если вам нужно преобразовать только одну цифру, использование atoi или любой другой функции преобразования строк является странным излишеством. Как уже было предложено, все, что вам нужно, это вычесть значение 0 из значения цифры вашего символа, чтобы получить соответствующее числовое значение. Спецификация языка гарантирует, что это переносимое решение.

person AnT    schedule 27.11.2009

Неважно, мне просто нужно было преобразовать символ в строку, оканчивающуюся на \0. Я изменил его на этот код:

символьный буфер [2];

буфер[1] = '\0';

буфер[0] = data_file.get();

если (данные_индекс == 50)

cout << "50 digit 0 = '" << buffer[0] << "' number = " << atoi(buffer) << endl;

и это сработало.

person Ring    schedule 27.11.2009
comment
Отлично, но вы все еще стреляете по воробьям из пушки, когда используете atoi для этой цели. - person AnT; 28.11.2009