C stoi обработка ошибки

  • Forum
  • Beginners
  • How to handle stoi conversion error?

How to handle stoi conversion error?

I am trying to convert a string to an integer using stoi, I have never touched on try catch and don’t know how to handle the exception or error given by stoi. The code below is what I’ve managed to produce but I can’t seem to be able to let the user re-enter once the stoi conversion has failed. Shouldn’t cin>>input be enough to start the try catch again? Really new to try catch and error handling. I am trying to loop the input for user when stoi conversion fails. Appreciate it if anyone can give me some examples.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17

String input;
int amount_input;

cout<<"Enter the amount of cake"<<endl;
cin>>input;

try{
amount_input = stoi(input);	
		
}
catch(exception &err)
{
cout<<"Conversion failure"<<endl;
cin>>input;
}

Last edited on

It is a strong temptation to bug the user to fix errors, but as the years have passed I have come stronger and stronger of the opinion that it is the Wrong ThingTM to do.

If the user’s input is incorrect, complain (be specific) and quit.

Good job!

Here is a more complete example for you to boggle over.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
#include <iostream>
#include <string>

int main()
{
  int number_of_slices_of_cake;
  try
  {
    std::cout << "How many slices of cake? ";
    std::string s;
    getline( std::cin, s );
    number_of_slices_of_cake = std::stoi( s );
    if (number_of_slices_of_cake < 0) throw 1;
  }
  catch (...)
  {
    std::cerr << "You must answer with a whole number >= 0.n";
    return 1;
  }

  int number_of_cakes = (number_of_slices_of_cake + 7) / 8;
  std::cout << "Great! That's " << number_of_cakes << " cakes!n";
}

Notice that on line 13 we also throw if the number of slices is invalid. It does not matter what we throw, since we are just trying to use the same response as a non-integer input. In other words, the catch (...) block catches both the 1 we throw and either of the things that stoi() throws.

If we wanted to have a different complaint then we would do something other than throwing that 1. (Such as complain and quit.)

Hope this helps.

I can’t seem to be able to let the user re-enter once the stoi conversion has failed.

In addition to @Duthomhas you need a loop like so:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
String input;
int amount_input;

bool is_ok = false;

while(not is_ok)
{
cout<<"Enter the amount of cake"<<endl;
cin>>input;

try{
amount_input = stoi(input);	
is_ok = true; // Note: is_ok is only set to true when stoi(...) was successfull
}
catch(exception &err)
{
cout<<"Conversion failure: "<< err.what() <<endl; // Note: what() tells the exact error
cin>>input; // Edit: don't
}

Last edited on

The problem with

1
2
3
4
while (user has not input what I want)
{
  …
}

is that you now have an infinite loop.

Don’t do that.

@Dunthomhas , if so is there a better way to let the user re-enter the input if the conversion has failed?

Ways of dealing with the infinite loop

1
2
3
4
   while ( not is_ok )
   {
      ....
   }

— Give it what it wants; enter something that makes

is_ok

true

— CTRL-C

— taskkill /f /IM myprog.exe

— close command window

— power off

— take a hammer to the PC

mrtammy2008 wrote:
if so is there a better way to let the user re-enter the input if the conversion has failed?

No. Make the user try again properly.

For many program, that means starting the program over.

For a (much) larger program, where this input is a smaller piece of the program, exit back to the menu/whatever the user used to get to the part where input was desired.

Don’t forget to tell the user what went wrong.

is that you now have an infinite loop.

No, due to line 13.

Ways of dealing with the infinite loop

Actually it depends on the requirements. One way could be:

1
2
3
4
5
6
7
8
9
10
11
12
13
catch(exception &err)
{
cout<<"Conversion failure: "<< err.what() <<endl; // Note: what() tells the exact error
cin>>input;
}
if(not is_ok)
{
  cout << "Exit? y/n" << endl;
  char exit_ch;
  cin >> exit_ch;
  is_ok = (exit_ch == 'y');
}
}

Yes, due to line 9.

Why are you wasting your time on this?

’Cause… whatever.

Topic archived. No new replies allowed.

This wrapper effectively removes some of the available functionality from std::stoi() because its signature is

int stoi(const std::string& str, std::size_t* pos = 0, int base = 10);

Because your wrapper does not allow a pos or base argument you cannot use it to give you the number of characters processed (with pos) nor to convert using a different base. std::stoi() provides default values for these arguments so you’d only have to provide them if you need the non-default behavior.

Also, you don’t take the std::string argument by const reference like std::stoi() — the string argument is probably not too expensive to copy in this context but why not accept the argument the same way std::stoi() does?

For completeness, I would also implement the overload of std::stoi() which accepts a std::wstring (and possibly std::stol() and std::stoll()).

I would also avoid the leading underscore, as identifiers with a leading underscore are reserved.

With these suggestions the wrapper would be implemented as

int stoi(const std::string& str, int* p_value, std::size_t* pos = 0, int base = 10) {
    // wrapping std::stoi because it may throw an exception

    try {
        *p_value = std::stoi(str, pos, base);
        return 0;
    }

    catch (const std::invalid_argument& ia) {
        //std::cerr << "Invalid argument: " << ia.what() << std::endl;
        return -1;
    }

    catch (const std::out_of_range& oor) {
        //std::cerr << "Out of Range error: " << oor.what() << std::endl;
        return -2;
    }

    catch (const std::exception& e)
    {
        //std::cerr << "Undefined error: " << e.what() << std::endl;
        return -3;
    }
}

I personally find that a regex is no overkill for this. Checking user input with a regex will have no negative impact on performance whatsoever.

But I think that you are more interested in exception handling. You need to read many many pages of a good C++ book to understand exception handling and its use cases.

And maybe, but I do not know, you want simply to catch the standard exceptions thrown by std::stoi. These are:

  • std::invalid_argument
  • std::out_of_range

That would be easy with writing

        // Standard exceptions for stoi
        catch (const std::invalid_argument & e) {
            std::cout << e.what() << "n";
        }
        catch (const std::out_of_range & e) {
            std::cout << e.what() << "n";
        }

But maybe you want to learn, how to write own exceptions. For your specific requirements. But please note that your specification, e.g. «more than 10 digits» and «no letter» are maybe not quite what you want. With a machine, where int is 32bit bit, the maximum number that can be converted is: 2147483647. Any number bigger and still having only 10 characters, will throw a std::out_of_range. On the other hand numbers like 123X would be converted by std::stoi to 123. So, maybe your requirements are not so clear.

Anyway, to show you, how you could use own exceptions, I create 2 customized exceptions classes. And to make life easy, I derived those from std::exception (recommended).

See the below example:

#include <iostream>
#include <string>
#include <algorithm>
#include <exception>
#include <cctype>
#include <vector>
#include <sstream>

class StoiException : public std::exception
{
public:
    StoiException(const std::string& msg) : message(msg) {}
    virtual const char* what() const noexcept override { return message.c_str(); }
protected:
    void setMessage(const std::string& msg) { message = msg; }
protected:
    std::string message{};
};

class NoNumber : StoiException
{
public:
    NoNumber(const std::string& msg) : StoiException(msg) { setMessage(std::string("My Exception -> NoNumber: ") + msg); }
    virtual const char* what() const noexcept override { return message.c_str(); }
};
class Overflow : StoiException
{
public:
    Overflow(const std::string& msg) : StoiException(msg) { setMessage(std::string("My Exception -> Overflow: ") + msg); }
    virtual const char* what() const noexcept override { return message.c_str(); }
};

int castInput(std::string& input) {
    int result{};
    // Check, if there is any letter in the input string
    if (std::any_of(input.begin(), input.end(), isalpha)) {
        // If so, than throw
        throw NoNumber(input);
    }
    // Check, if string has more than 10 characters
    if (input.length() > 10) {
        // If so, than throw
        throw Overflow(input);
    }
    result = std::stoi(input);
    return result;
}

std::istringstream testCin{ R"(123
   567
2147483647
2147483648
123X
12345678901
xyzxyzxyzxyzxyz
)" };


int main() {

    std::string input{};
    // Read all input
    while (testCin >> input) {
        try {
            // Convert
            int convert = castInput(input);
            // This will only be shown , if there is no exception
            std::cout << "nConverted Number is: " << convert << "n";
        }
        // Catch all exceptions
        catch (const NoNumber & e) {
            std::cout << e.what() << "n";
        }
        catch (const Overflow & e) {
            std::cout << e.what() << "n";
        }
        // Standard exceptions for stoi
        catch (const std::invalid_argument & e) {
            std::cout << e.what() << "n";
        }
        catch (const std::out_of_range & e) {
            std::cout << e.what() << "n";
        }
    }
    return 0;
}

Of course you can handle the std::stoi‘s exception also in your custom converter function. Then only your owwn exceptions are visible.

Please see:

#include <iostream>
#include <string>
#include <algorithm>
#include <exception>
#include <cctype>
#include <vector>
#include <sstream>

class StoiException : public std::exception
{
public:
    StoiException(const std::string& msg) : message(msg) {}
    virtual const char* what() const noexcept override { return message.c_str(); }
protected:
    void setMessage(const std::string& msg) { message = msg; }
protected:
    std::string message{};
};

class NoNumber : StoiException
{
public:
    NoNumber(const std::string& msg) : StoiException(msg) { setMessage(std::string("My Exception -> NoNumber: ") + msg); }
    virtual const char* what() const noexcept override { return message.c_str(); }
};
class Overflow : StoiException
{
public:
    Overflow(const std::string& msg) : StoiException(msg) { setMessage(std::string("My Exception -> Overflow: ") + msg); }
    virtual const char* what() const noexcept override { return message.c_str(); }
};

int castInput(std::string& input) {
    int result{};
    // Check, if there is any letter in the input string
    if (std::any_of(input.begin(), input.end(), isalpha)) {
        // If so, than throw
        throw NoNumber(input);
    }
    // Check, if string has more than 10 characters
    if (input.length() > 10) {
        // If so, than throw
        throw Overflow(input);
    }
    try {
        result = std::stoi(input);
    }
    // Standard exceptions for stoi
    catch (const std::invalid_argument & e) {
        throw NoNumber(input);
    }
    catch (const std::out_of_range & e) {
        throw Overflow(input);
    }
    return result;
}

std::istringstream testCin{ R"(123
   567
2147483647
2147483648
123X
12345678901
xyzxyzxyzxyzxyz
)" };


int main() {

    std::string input{};
    // Read all input
    while (testCin >> input) {
        try {
            // Convert
            int convert = castInput(input);
            // This will only be shown , if there is no exception
            std::cout << "nConverted Number is: " << convert << "n";
        }
        // Catch all exceptions
        catch (const NoNumber & e) {
            std::cout << e.what() << "n";
        }
        catch (const Overflow & e) {
            std::cout << e.what() << "n";
        }
    }
    return 0;
}

But maybe, what you really want to have, is a function, that encapsulates std::stoi and has an additional return value to show, if it worked or not.

Please note: The last solution will also convert «123X» to 123. That is the difference to the previous versions.

#include <iostream>
#include <string>
#include <algorithm>
#include <exception>
#include <cctype>
#include <vector>
#include <sstream>


std::pair<bool, int> castInput(std::string& input) {
    bool ok{ false };
    int result{};
    try {
        result = std::stoi(input);
        ok = true;
    }
    // Catch stoi errors
    catch (const std::invalid_argument & e) {}
    catch (const std::out_of_range & e) {}
    return {ok, result};
}

std::istringstream testCin{ R"(123
   567
2147483647
2147483648
123X
12345678901
xyzxyzxyzxyzxyz
)" };


int main() {
    std::string input{};
    // Read all input
    while (testCin >> input) {
            const auto [ok, convert] = castInput(input);
            if (ok)
                std::cout << "Converted value: " << convert << "n";
            else
                std::cout << "String '" << input << "' could not be convertedn";
    }
    return 0;
}

Defined in header <string>

int       stoi( const std::string& str, std::size_t* pos = nullptr, int base = 10 );
int       stoi( const std::wstring& str, std::size_t* pos = nullptr, int base = 10 );

(1) (since C++11)

long      stol( const std::string& str, std::size_t* pos = nullptr, int base = 10 );
long      stol( const std::wstring& str, std::size_t* pos = nullptr, int base = 10 );

(2) (since C++11)

long long stoll( const std::string& str, std::size_t* pos = nullptr, int base = 10 );
long long stoll( const std::wstring& str, std::size_t* pos = nullptr, int base = 10 );

(3) (since C++11)

Interprets a signed integer value in the string str.

Discards any whitespace characters (as identified by calling std::isspace) until the first non-whitespace character is found, then takes as many characters as possible to form a valid base-n (where n=base) integer number representation and converts them to an integer value. The valid integer value consists of the following parts:

  • (optional) plus or minus sign
  • (optional) prefix (0) indicating octal base (applies only when the base is 8 or 0)
  • (optional) prefix (0x or 0X) indicating hexadecimal base (applies only when the base is 16 or 0)
  • a sequence of digits

The set of valid values for base is {0,2,3,...,36}. The set of valid digits for base-2 integers is {0,1}, for base-3 integers is {0,1,2}, and so on. For bases larger than 10, valid digits include alphabetic characters, starting from Aa for base-11 integer, to Zz for base-36 integer. The case of the characters is ignored.

Additional numeric formats may be accepted by the currently installed C locale.

If the value of base is 0, the numeric base is auto-detected: if the prefix is 0, the base is octal, if the prefix is 0x or 0X, the base is hexadecimal, otherwise the base is decimal.

If the minus sign was part of the input sequence, the numeric value calculated from the sequence of digits is negated as if by unary minus in the result type.

If pos is not a null pointer, then a pointer ptr — internal to the conversion functions — will receive the address of the first unconverted character in str.c_str(), and the index of that character will be calculated and stored in *pos, giving the number of characters that were processed by the conversion.

[edit] Parameters

str the string to convert
pos address of an integer to store the number of characters processed
base the number base

[edit] Return value

Integer value corresponding to the content of str.

[edit] Exceptions

  • std::invalid_argument if no conversion could be performed.
  • std::out_of_range if the converted value would fall out of the range of the result type or if the underlying function (std::strtol or std::strtoll) sets errno to ERANGE.

[edit] Example

#include <iomanip>
#include <iostream>
#include <stdexcept>
#include <string>
#include <utility>
 
int main()
{
    const auto data =
    {
        "45",
        "+45",
        " -45",
        "3.14159",
        "31337 with words",
        "words and 2",
        "12345678901",
    };
 
    for (const std::string s : data)
    {
        std::size_t pos{};
        try
        {
            std::cout << "std::stoi('" << s << "'): ";
            const int i{std::stoi(s, &pos)};
            std::cout << i << "; pos: " << pos << 'n';
        }
        catch (std::invalid_argument const& ex)
        {
            std::cout << "std::invalid_argument::what(): " << ex.what() << 'n';
        }
        catch (std::out_of_range const& ex)
        {
            std::cout << "std::out_of_range::what(): " << ex.what() << 'n';
            const long long ll{std::stoll(s, &pos)};
            std::cout << "std::stoll('" << s << "'): " << ll << "; pos: " << pos << 'n';
        }
    }
 
    std::cout << "nCalling with different radixes:n";
    for (const auto& [s, base] : { std::pair<const char*, int>
        {"11",  2}, {"22",  3}, {"33",  4}, {"77",  8},
        {"99", 10}, {"FF", 16}, {"jJ", 20}, {"Zz", 36}, })
    {
        const int i{std::stoi(s, nullptr, base)};
        std::cout << "std::stoi('" << s << "', " << base << "): " << i << 'n';
    }
}

Possible output:

std::stoi('45'): 45; pos: 2
std::stoi('+45'): 45; pos: 3
std::stoi(' -45'): -45; pos: 4
std::stoi('3.14159'): 3; pos: 1
std::stoi('31337 with words'): 31337; pos: 5
std::stoi('words and 2'): std::invalid_argument::what(): stoi
std::stoi('12345678901'): std::out_of_range::what(): stoi
std::stoll('12345678901'): 12345678901; pos: 11
 
Calling with different radixes:
std::stoi('11', 2): 3
std::stoi('22', 3): 8
std::stoi('33', 4): 15
std::stoi('77', 8): 63
std::stoi('99', 10): 99
std::stoi('FF', 16): 255
std::stoi('jJ', 20): 399
std::stoi('Zz', 36): 1295

[edit] See also

stoulstoull

(C++11)(C++11)

converts a string to an unsigned integer
(function) [edit]

stofstodstold

(C++11)(C++11)(C++11)

converts a string to a floating point value
(function) [edit]

strtolstrtoll

(C++11)

converts a byte string to an integer value
(function) [edit]

strtoulstrtoull

(C++11)

converts a byte string to an unsigned integer value
(function) [edit]

strtoimaxstrtoumax

(C++11)(C++11)

converts a byte string to std::intmax_t or std::uintmax_t
(function) [edit]

from_chars

(C++17)

converts a character sequence to an integer or floating-point value
(function) [edit]

atoiatolatoll

(C++11)

converts a byte string to an integer value
(function) [edit]

to_string

(C++11)

converts an integral or floating point value to string
(function) [edit]

to_wstring

(C++11)

converts an integral or floating point value to wstring
(function) [edit]

karaulov6

23 / 23 / 6

Регистрация: 23.03.2013

Сообщений: 245

1

07.06.2017, 20:23. Показов 12499. Ответов 26

Метки нет (Все метки)


Студворк — интернет-сервис помощи студентам

std::stoi вызывает ошибку если подать неверную строку (не число)
atoi просто 0 вернет если строка не правильная

Можно ли как-то исправить std::stoi что бы не вылетала ошибка а возвращало 0 ?

Добавлено через 4 минуты
нашел std::stoi в <string>

C++
1
2
3
4
if ( _Ptr == _Eptr )
        _Xinvalid_argument( "invalid stoi argument" );
if ( errno == ERANGE || _Ans < INT_MIN || INT_MAX < _Ans )
        _Xout_of_range( "stoi argument out of range" );

вот эти гады вызывают ошибки

Добавлено через 26 минут
не понимаю для чего вызывать ошибки , это же все портит, особенно в агрессивной среде где неизвестно какую строку могут скормить))

что бы избежать ошибок нужно везде где используется std::stoi добавлять try {} catch {} ?



0



7529 / 6394 / 2914

Регистрация: 14.04.2014

Сообщений: 27,855

07.06.2017, 21:07

2

Цитата
Сообщение от karaulov6
Посмотреть сообщение

что бы избежать ошибок нужно везде где используется std::stoi добавлять try {} catch {} ?

Не ошибки, а исключения. Да, нужно.



0



23 / 23 / 6

Регистрация: 23.03.2013

Сообщений: 245

07.06.2017, 22:37

 [ТС]

3

жесть )) огромную кучу кода переписать придется, легче заменить stoi на свой))



0



What a waste!

1607 / 1299 / 180

Регистрация: 21.04.2012

Сообщений: 2,727

07.06.2017, 22:57

4

Цитата
Сообщение от karaulov6
Посмотреть сообщение

жесть )) огромную кучу кода переписать придется, легче заменить stoi на свой))

Почему бы тогда не использовать atoi или strtol, если исключения не нужны?



0



284 / 232 / 114

Регистрация: 07.09.2016

Сообщений: 584

08.06.2017, 00:41

5

а как вы в своей «агрессивной среде» собираетесь отличать вполне корректную строку «0», которая в 0 превратится от «xyz», если это тоже в 0 будет превращаться?



0



7529 / 6394 / 2914

Регистрация: 14.04.2014

Сообщений: 27,855

08.06.2017, 09:15

6

DU3, мне тоже не понятна эта неоднозначность atoi().
Кроме того, всё равно придётся делать какие-то проверки, если возможна ситуация с некорректными данными.



1



23 / 23 / 6

Регистрация: 23.03.2013

Сообщений: 245

08.06.2017, 11:21

 [ТС]

7

Я автоматической заменой изменил все atoi( str.c_str() ) на stoi( str ) , а их в коде было много

код стал понятнее и без лишнего мусора

но вдруг, оказалось если пользователь введет не число, а какую-нибудь левую строку, все падает к чертям ))))

да я просто заменил stoi своей функцией и переименовал ща норм стало



0



7529 / 6394 / 2914

Регистрация: 14.04.2014

Сообщений: 27,855

08.06.2017, 12:09

8

karaulov6, как это решает проблему с некорректным вводом? Типа, ничего не видно и ладно?



0



23 / 23 / 6

Регистрация: 23.03.2013

Сообщений: 245

08.06.2017, 23:27

 [ТС]

9

Стало как положено, т.е как в atoi , неверная строка = 0



0



Любитель чаепитий

3737 / 1796 / 563

Регистрация: 24.08.2014

Сообщений: 6,015

Записей в блоге: 1

11.06.2017, 09:30

10

если у тебя пользователь в 80 местах данные вводит, то есть смысл вообще всю систему ввода в какой-то подмодуль переделать, где при ошибке ввода пользователя заставят вводить снова и снова.



1



23 / 23 / 6

Регистрация: 23.03.2013

Сообщений: 245

11.06.2017, 14:10

 [ТС]

11

Я же уже написал что вырезал эти ошибки из stoi и теперь все работает.

Хватит поднимать тему зря)



0



Любитель чаепитий

3737 / 1796 / 563

Регистрация: 24.08.2014

Сообщений: 6,015

Записей в блоге: 1

11.06.2017, 14:12

12

Не по теме:

поставил костыль и рад, надеюсь, на работу программистом с таким подходом тебя никогда не возьмут.

а тему не зря поднимаю, а чтобы если кто-то найдет эту тему потом, сразу видел, что это костыль и так делать не надо.



2



23 / 23 / 6

Регистрация: 23.03.2013

Сообщений: 245

11.06.2017, 14:27

 [ТС]

13

Ну скажите как надо делать если в коде 100 мест с использованием atoi(std::string.c_str()) а их требуется заменить на stoi(std::string)
Нигде не известно какие данные будут введены, рассчитано на то что если неверная строка то atoi вернет 0.

Но stoi вместо того что бы спокойно вернуть 0, убивает программу.

Решений проблемы только 2, добавить в 100 мест кода проверку на исключение или же просто заменить stoi своей функцией
которая не будет ложить программу.)))

Я решил проблему вторым вариантом, или есть третий еще более правильный?



0



зомбяк

1581 / 1215 / 345

Регистрация: 14.05.2017

Сообщений: 3,939

11.06.2017, 14:34

14

Цитата
Сообщение от karaulov6
Посмотреть сообщение

Решений проблемы только 2, добавить в 100 мест кода проверку на исключение

напиши функцию (возможно шаблонную), в которой бы происходил stoi(std::string) в требуемый тип, и прямо в этой функции определи try/catch . И чтоб по catch возвращала 0. И ещё inline ей пропиши.

Компилятор сделает тебе 100 мест проверок совершено бесплатно, ещё и спасибо скажет



0



23 / 23 / 6

Регистрация: 23.03.2013

Сообщений: 245

11.06.2017, 14:46

 [ТС]

15

А я написал что-то другое?



0



Любитель чаепитий

3737 / 1796 / 563

Регистрация: 24.08.2014

Сообщений: 6,015

Записей в блоге: 1

11.06.2017, 14:52

16

Цитата
Сообщение от karaulov6
Посмотреть сообщение

или есть третий еще более правильный?

см. #12.



0



23 / 23 / 6

Регистрация: 23.03.2013

Сообщений: 245

11.06.2017, 16:24

 [ТС]

17

Да что с вами не так, я же написал что исправил ошибку уже, зачем пытаться включать» режим телепата «и что-то еще доказывать?

см. #7



0



Любитель чаепитий

3737 / 1796 / 563

Регистрация: 24.08.2014

Сообщений: 6,015

Записей в блоге: 1

11.06.2017, 17:39

18

Цитата
Сообщение от karaulov6
Посмотреть сообщение

исправил ошибку уже

вставить костыль != исправить ошибку.



1



23 / 23 / 6

Регистрация: 23.03.2013

Сообщений: 245

11.06.2017, 17:55

 [ТС]

19

А где я написал что костыль вставил?

Или «режим телепата» помог до этого додуматься?



0



1174 / 835 / 359

Регистрация: 26.02.2015

Сообщений: 3,743

11.06.2017, 18:02

20

Цитата
Сообщение от karaulov6
Посмотреть сообщение

Я решил проблему вторым вариантом, или есть третий еще более правильный?

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

ЧЕМ РАНЬШЕ ВЫ ОБНАРУЖИТЕ, ЧТО ПОЛЬЗОВАТЕЛЬСКИЕ ДАННЫЕ НЕВЕРНЫ, ТЕМ ЛУЧШЕ ЖЕ ДЛЯ ВАС. А самый раннее место это определить — в момент их ввода или же сразу после него. :-D



1



Понравилась статья? Поделить с друзьями:
  • C 3102 ошибка konica minolta
  • C 2556 ошибка konica
  • C 1611 ошибка киа сид
  • C 101101 ошибка вольво
  • C 0213 ошибка коника