如何解决随机数的无限打印?

问题描述 投票:0回答:3

[我编写了一个程序,将未知数量的整数扫描到一个数组中,但是当我运行它时,它会打印出无数次的最后一个值。

例如输入:1 2 3 4 5

输出为55555555555555555555555555 ...

为什么会这样,我该如何解决?

我的目标是为实例{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);
c loops printf command-line-interface scanf
3个回答
2
投票

为什么会发生(?)(打印...无限次。)

查看循环终止条件c != EOF

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

EOF是一些负值,通常为-1。 scanf("%d", &c)尝试读取用户输入并转换为intscanf()返回10EOF取决于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;
}

1
投票

存在许多问题。

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

1
投票

当scanf失败时,您应停止循环。根据manual

成功后,[scanf] 返回]成功匹配和分配的输入项目数;如果较早匹配失败,则该值可以小于所提供的值,甚至为零。如果在第一次成功转换或匹配失败发生之前到达输入结束,则返回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;
    pSetNew = (int*) realloc(pSet, sizeof(int)*(i+1));
    if(pSetNew == NULL) {
      free(pSet);
      return FAIL;        
    } else {
      pSet = pSetNew;
    }
    printf("%d ", c);
    i++;
  }

  free(pSet);
}

但是如果您想要一段更健壮的代码,我建议您以字符串形式检索答案(NULL终止的char数组),然后使用诸如strtol的专用函数对其进行解析。检查whole字符串是否是有效条目,而不仅仅是前几个字符。

注意:HengLi修复了以上代码示例中的潜在内存泄漏

© www.soinside.com 2019 - 2024. All rights reserved.