Programming error
First of all, this is a programming error. It is important to say this because it is usually an exception in many languages and people are tempted to capture the exception and do something. This is to use exception for flow control, is to stop validating something that may be wrong to only treat if the error occurs. Do not do this, correct the error, even if it is to do the validation and give the treatment before giving the error.
The mistake
This error (I won’t mention an exception here, because even if one is thrown, it is still an error) occurs only in data collections or composite objects which behave like collections (some dynamic typing languages have compositions implemented as a collection, for example a class or something similar is implemented as a dictionary which is a collection).
To access an element of the collection you need to say which element is desired in some way. This form is usually called index, but in some cases can be a key, and in English may use the term subscript. This value that indexes the element of the collection tends to be a number, but nothing prevents it from being other types of data, in fact in dictionaries it is common to be strings.
Types of collections
In some collections the values are sequential and form a clear range of data, for example starting at 0 and ending at 9, having uniformly 10 elements in sequence. They have a form of array, even if it’s not exactly one. In freer collections they may have sparse indexes/keys (the term most used in these cases), that is, the values are not sequential, so if they are numbers you can start at any number and end at any number and you don’t need to have all the numbers between them. The same goes for strings or other data as key.
for (var i = 1; i <= lista.Count; i++) //erro aqui
for (var i = 1; i < lista.Count; i++) //certo
One string is a collection of data, it is a sequence of characters usually started in the 0-position character and ending in the minus one size. Do not attempt to access a character that is outside this range. It is common for a person to try to access it unintentionally outside this range, perhaps because they tried to do a search that did not find the information (it can return -1).
If you consider that an ASCII table or something similar is a collection, may occur something similar without giving error, only bad result. Another example.
How the error occurs
As it is a collection, this index/key value needs to exist in it, if there is no error described in the question or some variant of it.
In ordinary collections like arrays the term "range" (crease) or the use of limits (Bounds) start and end is most used because it certainly has all the numbers of a track. What you can’t do is access a number that’s outside that range. It is not mandatory to start at 0, but if you start you cannot use a value that is negative. And you can’t access a value that’s greater than the amount of elements. So if you start with 0, it can’t be the number that indicates the size, nor a number that’s bigger than this. Because if you start from 0, for example if you have 10 elements, it goes from 0 to 9, then 10 is no longer valid. If it starts at 1, then 10 would be valid, but 11 would not, and in this case 0 would also be invalid.
let r = [2, 5, 6, 18, 20, 10, 23, 12, 19, 10];
let s = [1, 5, 7, 13, 18, 21, 10, 25, 32, 17, 3];
let x = [0];
let i;
console.log("i = " + i);
for (i = 0; i <= 9; i++) {
x[i] = r[i];
console.log("i = " + i);
}
console.log("i = " + i);
for (i = 0; i <= 10; i++) {
x[i + 10] = s[i];
console.log("i = " + i);
}
console.log("i = " + i);
I put in the Github for future reference.
The error can indicate a value outside the range down or up, no matter.
The error occurs very commonly when the index that is used is obtained in a formula or is obtained by an external data that that algorithm has no control over. Either it occurs when going to access a specific element or when making a loop and this loop either starts at the wrong number or tries to end after it has already evaluated all elements it had to analyze.
It is common to occur in functions and methods that have a bond internally, a very common case is the Substring()
.
Has a class that superficially shows how the error is generated.
How to avoid
In the case of the loop the ideal is to use a construction of the language, if you have to sweep the entire collection by own control so there is not much to miss (provided that the collection is not modified in its structure and does not change the amount of existing elements). May be a foreach
or a for
abstract to do this. When you use a for
gross or while
where the programmer controls where to stop, it is that the error happens. The most common error is the person placing the comparison checking the end if the counter is less than or equal to the size, but if it starts from scratch it has to be less than the total size of the collection.
foreach (var item in lista) WriteLine(item); //assim não tem como dar esse erro
I put in the Github for future reference.
There are cases that are using a loop but are not accessing the element directly, but rather calculating the number using the loop counter as part of the formula. This is a hybrid case, the problem may be in the limit of the counter or it may be in the formula. For example, if you use a formula that always takes the "counter plus one", you obviously can’t go to the last possible value in the collection because the last possible plus one gives a number outside the range, for example if the collection goes from 0 to 9, the counter should stop at 8, if it is in 9 the formula will result in 10 and will give the error.
So the solution to the problem is always validate right when it should stop, never let go of the element number that does not exist in the collection at that time. Never assume you know how many elements there are, always take this number or use a construction that guarantees it.
if (n >= 0 && n < opcoes.size()) return opcoes[n]->reproduz();
I put in the Github for future reference.
In case the access is done individually by a data calculated or obtained externally it is almost always necessary to validate the variable data and that came without direct control of its algorithm. If you don’t pass the validation of being between the initial range (usually 0) and the final range (usually the collection size minus one), or if you still have that key, then you should do some alternative operation, usually by returning an error or doing something different (in some cases may even cast an exception, but it is not usually the best option, but if it forms a more specific exception in some cases may be interesting, it is only more rare to be the right).
Only access an index/key conditionally, unless it is 100% guaranteed that it has no invalid data, but are rare cases like this, as can be seen in the codes and links posted here. This tip serves for any data, not only those that are indexes/keys. Almost all bugs occur because some data is not in the state that is waiting and can not trust anything.
Note that we see a lot of error case where the key (from a dictionary or object) does not exist without even coming from outside, that is, it is simple typing error, it is as if you had typed the name of a wrong variable in the code.
And in fact many times in cases of literals using as a key they function as if they were names and even variables. The collection element is still a variable.
The use of assert()
, requires()
or something similar is usually a good idea. Learn them.
Not everything makes a mistake
Some data structures do not throw errors or exceptions when the key does not exist, only return one error code which may be a null. Some have methods that allow you to choose what happens when you try to access a non-existent key. Caution may seem right because it works, but it will result bad.
There are languages that do not give error, only fucks everything. C and C++ to some extent, are like this.
Where there’s no mistake
If you are not passing a position on a data collection then the error will not happen, then you need two things: data collection and position being accessed. The position can be passed by an indexer operator, very common be brackets objeto[x]
(of a array, list, or dictionary), but other languages may have other notations, JS can do so objeto.x
and it’s still a position in that collection. It can also occur in methods that receive the position in one way or another, it can be up to a data that will be used to calculate the position.
Finding out the error
A table test manual or aided by IDE (Debugger) will always indicate what is happening. You run step by step and analyze the value of the element being used and you will see that one of it just at the moment it will give the error is accessing an index/key that does not exist, so you need to know all possible keys or the range of the possible index.
Always remember to look at the die at that moment, it may not be what you want, it may not contain all the elements you are waiting for, it may be the cause of the error. If the data is ok then your algorithm is taking a value that it should not.
There is no miracle, there is no easy and quick response, you have to analyze what is happening. Do the analysis and learn to program better in the process. Learn to fend for yourself, you’ll need it. Who does not know how to do this does not know the basics of programming and access collections is beyond your current ability, rethink the pace of learning.
This is a boring mistake because always occurs at runtime (there are few situations that could be avoided at runtime and it is not usually worth the effort to do this).
Extra
I didn’t, but I’ve seen errors where the value being used was a literal and therefore total control of the algorithm being written there. Almost always the problem is not well in this algorithm, it is in the received data, probably you expected to receive a collection of data with a certain number of elements and for some reason you are not receiving it. Probably the problem lies in the creation of the data and should focus efforts on analyzing it. You can improve your algorithm to handle such an error case, but almost always the best result to make the data come out correctly since it is part of the contract to come like this. Sure, that might not be a good one design, is not robust, or to give robustness complicates the code and worsens performance, but many people develop without thinking about these things ("all" who choose a dynamic typing language). Example.
Completion
In a certain way it can be seen as a variant of the division by zero. It only occurs because it is receiving a value that is not accepted in that context. No matter what you do, the solution is always to validate implicitly or explicitly the data that will be used as index/key before using, it has to be guaranteed that it exists (if it is not a typo).
Example in C# of robust code to not allow access to an element that does not exist inadvertently.
Examples of questions that speak of this error, it is almost certain that yours is covered in some.
I’ll put more examples, try to use more languages, other answers can help more people