Рассмотрим десятичное размещение
Недостающая часть в коде вопроса накапливает цифры (в отличие от подсчета цифр с помощью sum++;
) И умножает на десять предыдущее накопленное число перед добавлением следующего ди git.
Ответ: number = number * 10 + i - '0';
Часть - '0'
преобразует ASCII di git в число.
Все остальное в приведенном ниже Код проверяет, чтобы убедиться, что нет явных переполнений и правильно , поддерживающий знак минус также рядом с числами, а также игнорирование цифр после десятичной запятой (и). Я уверен, что это не идеально, но идея здесь в том, чтобы предоставить рабочий пример того, как это можно сделать, а не хорошо протестированный код и использовать библиотечный вызов, чтобы сделать это за вас.
популярный спрос (комментарии были удалены) Я добавил простую, но работающую проверку переполнения:
#include <stdlib.h>
#include <stdio.h>
#include <ctype.h>
#include <error.h>
#include <limits.h>
int main(int argc, char* argv[]) {
int sum = 0, state = 0, i = 0, dir = 1;
unsigned int number = 0, check;
if (argc < 2) {
fprintf(stderr, "Missing filename\n");
return EXIT_FAILURE;
}
char* filename = argv[1];
FILE* file = fopen(filename, "r");
if (!file) {
perror(filename);
return EXIT_FAILURE;
}
while (i != EOF) {
i = fgetc(file);
if (isdigit(i)) {
if (dir) {
state = 1;
check = number;
number = number * 10 + i - '0';
if (check > number || number > INT_MAX) {
fprintf(stderr, "Single number overflow error\n");
fclose(file);
return EXIT_FAILURE;
}
}
} else {
if (state && dir) {
check = number;
if (dir < 0 && sum < 0)
check -= sum;
else if (dir > 0 && sum > 0)
check += sum;
if (check > INT_MAX) {
fprintf(stderr, "Sum overflow error\n");
fclose(file);
return EXIT_FAILURE;
}
sum += number * dir;
number = 0;
}
state = 0;
dir = i == '-' ? -1 : i == '.' ? 0 : 1;
}
}
printf("Sum of numbers is: %i\n", sum);
fclose(file);
return EXIT_SUCCESS;
}
Тестовый запуск:
$ cat opString.txt
This text 15 is very 19 nice.
$ ./test2 opString.txt
Sum of numbers is: 34
$
И на всякий случай, если вы на 64-битной linux и требует гораздо более высокой производительности (вы упомянули большой файл), приведенный ниже код отобразит весь файл (даже файл больше, чем память, ядро прекрасно с этим справится) и не вызовет библиотеку для каждого символа. В моих тестах isdigit()
и strtol()
значительно замедляют его.
#include <stdlib.h>
#include <stdio.h>
#include <error.h>
#include <limits.h>
#include <sys/mman.h>
int addToSum(unsigned int* number, int* sum, int dir, FILE* file) {
unsigned int check;
check = *number;
if (dir < 0 && *sum < 0)
check -= *sum;
else if (dir > 0 && *sum > 0)
check += *sum;
if (check > INT_MAX) {
fprintf(stderr, "Sum overflow error\n");
fclose(file);
exit(EXIT_FAILURE);
}
*sum += *number * dir;
*number = 0;
}
int main(int argc, char* argv[]) {
int sum = 0, state = 0, i = 0, dir = 1;
unsigned int number = 0, check;
if (argc < 2) {
fprintf(stderr, "Missing filename\n");
return EXIT_FAILURE;
}
char* filename = argv[1];
FILE* file = fopen(filename, "r");
if (!file) {
perror(filename);
return EXIT_FAILURE;
}
if (fseek(file, 0L, SEEK_END) < 0) {
perror("fseek failed");
fclose(file);
return EXIT_FAILURE;
}
long fsize = ftell(file);
char* fmap = mmap(NULL, fsize, PROT_READ, MAP_SHARED, fileno(file), 0);
if (fmap == MAP_FAILED) {
perror("map failed");
fclose(file);
return EXIT_FAILURE;
}
long pos = 0;
while (pos < fsize) {
i = fmap[pos++];
if (i >= '0' && i <= '9') {
if (dir) {
state = 1;
check = number;
number = number * 10 + i - '0';
if (check > number || number > INT_MAX) {
fprintf(stderr, "Single number overflow error\n");
fclose(file);
return EXIT_FAILURE;
}
}
} else {
if (state && dir) addToSum(&number, &sum, dir, file);
state = 0;
dir = i == '-' ? -1 : i == '.' ? 0 : 1;
}
}
if (state && dir) addToSum(&number, &sum, dir, file);
printf("Sum of numbers is: %i\n", sum);
fclose(file);
return EXIT_SUCCESS;
}