В1) Ваша версия atoi()
слишком проста, стандартная версия игнорирует начальные пробельные символы и обрабатывает необязательный знак перед числом. atoi(" -123junk")
следует оценить до -123
.
Q2) atoi
- это стандартная функция, определенная прототипом int atoi(const char *s);
, она возвращает целое число.
В3) В Code 2
есть несколько ошибок:
char
s
как i
, который неинициализирован. вместо этого вы должны определить массив с достаточно большим значением, таким как 64
, EOF
, чтобы остановить цикл в случае, если конец файла встречается без перевода строки. Вот модифицированная версия:
#include <stdio.h>
#include <stdlib.h>
int main() {
char s[64];
size_t i;
int c;
for (i = 0; i < sizeof(s) - 1 && (c = getchar()) != EOF;) {
s[i++] = c;
if (c == '\n')
break;
}
s[i] = '\0';
printf("%i", atoi(s));
return 0;
}
Q4) выражение n = 10 * n + (s[i] - '0')
вычисляется для каждой новой цифры, найденной в строке. Действительно, немного неэффективно умножать текущее значение на 10 до тех пор, пока не будет найдено ненулевой цифры, но написать функцию таким образом просто.
Чтобы избежать этих бесполезных умножений, вот альтернатива:
int atoi(const char *s) {
int n = 0;
size_t i = 0;
while (s[i] == '0')
i++;
if (s[i] >= '1' && s[i] <= '9') {
n = s[i++] - '0';
while (s[i] >= '0' && s[i] <= '9')
n = 10 * n + (s[i++] - '0');
}
return n;
}
Но эта функция более громоздка и может фактически быть менее эффективной, чем простая версия. Попробуйте и сравните тесты в вашей системе.
Для полноты, вот полная переносимая версия, использующая ctype.h>
, которая обрабатывает необязательный начальный пробел и необязательный знак. Он также обрабатывает переполнение с определенным поведением, хотя для этого не требуется стандартная версия atoi()
.
#include <limits.h>
#include <stdio.h>
int atoi(const char *s) {
int n = 0, d;
/* skip optional initial white space */
while (isspace((unsigned char)*s))
s++;
if (*s == '-') {
/* convert negative number */
s++;
while (isdigit((unsigned char)*s)) {
d = (*s++ - '0');
/* check for potential arithmetic overflow */
if (n < INT_MIN / 10 || (n == INT_MIN / 10 && -d < INT_MIN % 10)) {
n = INT_MIN;
break;
}
n = n * 10 - d;
}
} else {
/* ignore optional positive sign */
if (*s == '+')
s++;
while (isdigit((unsigned char)*s)) {
d = (*s++ - '0');
/* check for potential arithmetic overflow */
if (n > INT_MAX / 10 || (n == INT_MAX / 10 && d > INT_MAX % 10)) {
n = INT_MAX;
break;
}
n = n * 10 + d;
}
}
return n;
}
int main(int argc, char *argv[]) {
int i, n;
for (i = 1; i < argc; i++) {
n = atoi(argv[i]);
printf("\"%s\" -> %d\n", argv[i], n);
}
return 0;
}
arc4random возвращает 32-разрядное целое число без знака (от 0 до 2 <глоток> 32 глоток>-1).
, вероятно, не будет никакой noticable предвзятости по модулю для достаточно маленького x. Однако, если Вы хотите быть действительно уверенными, сделайте это:
год = 2 <глоток> p глоток>, где 2 <глоток> p-1 глоток> < x в‰ 2¤ <глоток> p глоток>
val = arc4random() % y;
while(val >= x)
val = arc4random() % y;
u_int32_t maxValue = ~((u_int32_t) 0); // equal to 0xffff...
maxValue -= maxValue % x; // make maxValue a multiple of x
while((value = arc4random()) >= maxValue) { // loop until we get 0 ≤ value < maxValue
}
value %= x;
, хотя, если Вы не используете x менее чем миллион (или больше) я не волновался бы об этом
Если максимальное значение arc4random
модификация x
больше, чем x
, проигнорируйте любые значения, больше, чем самое большое arc4random-max mod x
, звоня arc4random
снова вместо этого.