Как исправить бесконечную печать случайного числа?Язык C - PullRequest
0 голосов
/ 30 ноября 2018

Я написал программу, которая сканирует неизвестное количество целых чисел в массив, но когда я запускаю его, он печатает последнее значение, которое он получил бесконечное количество раз.Например, для ввода: 1 2 3 4 5 Выход будет 55555555555555555555555 ... Почему это происходит и как я могу это исправить?Моя цель здесь - создать массив для экземпляра {1, 2, 3, 4, 5}, а затем распечатать то, что он отсканировал, в массив, ТОЛЬКО ОДИН РАЗ ...

int *pSet = (int*) malloc(sizeof(int)); int i; int c;
printf("Please enter a stream of numbers to make a set out of them: ");
printf("\n");

scanf("%d", &c);
pSet[0] = c;
printf("%d ", c);
for(i = 1; c != EOF; i++) {
    pSet = (int*) realloc(pSet, sizeof(int)*(i+1));
    if(pSet == NULL) {
        return FAIL;        
    }
    scanf("%d", &c);
    pSet[i] = c;
    printf("%d ", c);
}

free(pSet);

Спасибо.

Ответы [ 3 ]

0 голосов
/ 30 ноября 2018

Существует ряд проблем.

1) Завершить цикл при сбое scanf вместо использования EOF.Сделайте это, проверив, что возвращаемое значение равно 1 (т. Е. Число входных элементов успешно сопоставлено)

2) Не выделяйте память, пока она не понадобится

3) Никогда делайте realloc непосредственно в целевой указатель - всегда используйте временную переменную.

Исправьте этот код:

#include <stdio.h>

int main(void) {
    int *pSet = NULL;
    printf("Please enter a stream of numbers to make a set out of them: ");
    printf("\n");

    int i = 0;
    int c;
    while (1) {
         if (scanf("%d", &c) != 1)
         {
             printf("Terminating input loop\n");
             break;
         }

         int* tmp = realloc(pSet, sizeof(int)*(i+1));
         if(tmp == NULL) {
            printf("oh dear...\n");
            break;
         }
         pSet = tmp;
         pSet[i++] = c;
         printf("%d ", c);
    }

    for (int j=0; j < i; ++j) printf("%d\n", pSet[j]);
    free(pSet);
    return 0;
}

Ввод:

1 2 3 4 5 6 7 stop

Выход:

Please enter a stream of numbers to make a set out of them: 
1 2 3 4 5 6 7 
Terminating input loop
1
2
3
4
5
6
7
0 голосов
/ 30 ноября 2018

Почему это происходит (?) (Печать ... бесконечное количество раз.)

Посмотрите на условия завершения цикла c != EOF.

int c;
scanf("%d", &c);
for(i = 1; c != EOF; i++) {  // Not good code
  scanf("%d", &c);
}

EOF - это некоторое отрицательное значение, часто -1.scanf("%d", &c) пытается прочитать пользовательский ввод и преобразовать в int.scanf() возвращает 1, 0, EOF в зависимости от того, успешно ли 1), 2) не удалось найти числовой текст или 3) произошла ошибка конца файла или ввода.К сожалению, код не использует это возвращаемое значение.Вместо этого код использовал прочитанное число c и проверил, совпадает ли считанное число с EOF.


как я могу это исправить?

Цикл только тогда, когда возвращаемое значение scanf() соответствует ожидаемому (1).

for(i = 1; scanf("%d", &c) == 1; i++) {
  ...
}

Соединяя это с некоторыми другими идеями

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

int main(void) {
  printf("Please enter a stream of numbers to make a set out of them:\n");
  int *pSet = NULL;  // Start with no allocation
  size_t i = 0;

  int c;
  for (i = 0; scanf("%d", &c) == 1; i++) {
    //        +---------------------------  No cast needed.
    //        v               v----------v  Use sizeof de-referenced pointer
    void *p =   realloc(pSet, sizeof *pSet * (i + 1));
    if (p == NULL) {
      free(pSet);
      return EXIT_FAILURE;
    }
    pSet = p;
    pSet[i] = c;
  }

  for (size_t j = 0; j < i; j++) {
    printf("%d ", pSet[j]);
  }

  free(pSet);
  return 0;
}
0 голосов
/ 30 ноября 2018

Вы должны остановить ваш цикл, когда scanf не работаетВ соответствии с руководством :

В случае успеха [scanf] return [s] количество элементов ввода, успешно сопоставленных и назначенных;это может быть меньше, чем предусмотрено, или даже равно нулю, в случае сбоя раннего сопоставления.Значение EOF возвращается, если достигнут конец ввода перед первым успешным преобразованием или ошибкой сопоставления.EOF также возвращается, если происходит ошибка чтения.[...]

Таким образом, вы можете превратить ваш цикл for в краткий.

#include <stdio.h>
#include <stdlib.h>

#define FAIL 0
int main() {
  int *pSet = (int*) malloc(sizeof(int));
  int c;
  int i=0;
  printf("Please enter a stream of numbers to make a set out of them: ");
  while(scanf("%d", &c) == 1) {
    pSet[i] = c;
    pSet = (int*) realloc(pSet, sizeof(int)*(i+1));
    if(pSet == NULL) {
      return FAIL;        
    }
    printf("%d ", c);
    i++;
  }

  free(pSet);
}

Но если вам нужен более надежный фрагмент кода, я предлагаю вамполучить ответ в виде строки (NULL -определенный массив char), а затем проанализировать его с помощью специальных функций, таких как strtol, которые позволяют проверить, является ли строка whole допустимой записью, ине только первые символы.

...