Как преобразовать строку в int в C из файла без использования библиотечной функции?

#c

#c

Вопрос:

Я пытаюсь открыть файл, в котором много строк чисел, а затем преобразовать его из строки в целое число.

Я хотел бы сделать это без использования каких-либо библиотечных функций, поэтому нет atoi, strtol или strtoul.

Вот как выглядит мой код:

 #include <stdio.h>
#include <stdlib.h> /* required for atoi. */
int main(void) {
  int  i, len;
  int result=0;
  double numbers;
  char num[20];  /* declares a char array. */

FILE *file;  /* declare a file pointer. */
file = fopen("test22.txt", "r");  /* opens the text file for reading only, not writing. */

while(fgets(num, 100, file)!=NULL) {       /* this while loop makes it so that it will continue looping until the value is null, which is the very end. */
    len=strlen(num);
    for(i=0; i<len; i  ) {
        result = result*10   ( num[i] - '0' );
    }
    printf("%dn", result);
    }
fclose(file); /* closes the file */
return 0;
}
  

Прямо сейчас он возвращает числа, которых нет в текстовом файле.

Любая помощь будет оценена! Спасибо!

Комментарии:

1. #include <stdlib.h> /* required for atoi. */ <— И зачем вам пытаться изобретать велосипед? Также: об ctype.h этом тоже не может быть и речи, или вы рады использовать isdigit ?

Ответ №1:

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

 while(fgets(num, 100, file)!=NULL) { 
    len=strlen(num);
    for(i=0; i<len; i  ) {
        result = result*10   ( num[i] - '0' );
    }
    printf("%dn", result);
    }
  

Для

 while(fgets(num, 100, file)!=NULL) {
    result = 0;
    len=strlen(num);
    // account for newline - should really be smarter than this.
    // I'll leave that as an exercise for the reader... ;)
    for(i=0; i< (len - 1); i  ) {
        result = result*10   ( num[i] - '0' );
    }
    printf("%dn", result);
    }
  

Комментарии:

1. Привет, Эндрю, спасибо за ответ. Он по-прежнему печатает числа, которых нет в текстовом файле.

2. @N.Vaz Каково содержимое текстового файла? Опубликованный код вообще не проверяет, каковы входные данные, поэтому, если в файле есть символы, которые не являются числами или символами новой строки, он выведет неправильные значения. Кроме того, если числа слишком велики, чтобы поместиться в an int , у вас возникнут проблемы.

3. Это просто числа, которые были сгенерированы случайным образом и сохранены в нем. Смотрите: puu.sh/rEhMO/4fa9e11f35.png

4. @N.Vaz Опубликованный код не учитывает - символы.

5. Что мне нужно добавить, чтобы учесть отрицательные числа? Я ценю помощь!

Ответ №2:

Функция fgets сохраняет newline в конце строки (если присутствует), которую вы пытаетесь преобразовать в цифру. Я предлагаю такой цикл:

 for(i=0; i<len amp;amp; isdigit(num[i]); i  )
  

и вы также должны иметь

 result = 0;
for(i=0; i<len amp;amp; isdigit(num[i]); i  )
  

перед каждым циклом.

Обратите внимание, что вы не можете просто уменьшить результат strlen , потому что в последней строке файла может не быть a newline в конце.

Редактировать: поскольку вы опубликовали файл с отрицательными числами, вот пример, который их преобразует.

 #include <stdio.h>
#include <ctype.h>

int getnum(char *str) 
{
    int result  = 0;
    int neg = 0;
    if(*str == '-') {
        neg = 1;
        str  ;
    }
    while(isdigit(*str)) {
        result = result * 10   *str - '0';
        str  ;
    }
    if(neg) {
        return -resu<
    }
    return resu<

}

int main(void)
{
    printf("%dn", getnum("123456789n"));
    printf("%dn", getnum("-987654321n"));
    return 0;
}
  

Вывод программы:

 123456789
-987654321
  

Комментарии:

1. Привет, флюгер, спасибо за ответ. Я отредактировал код, и он фактически выдает мне числа, которые находятся в текстовом файле. Однако они не в порядке, и он возвращает 0, что, как я полагаю, связано с отрицательными числами. Смотрите: puu.sh/rEiqM/24311788c2.jpg

2. Примечание: угловой регистр: getnum() может работать или не работать со строковой версией INT_MIN . Вероятно, это не проблема OP.

3. @chux да, проблемы с диапазоном в целом, но я сделал это простым.