当用户在c中输入输入时停止for循环

时间:2016-08-22 04:15:53

标签: c arrays loops for-loop

首先,谢谢你的帮助!

我是C语言的新手(以及一般的编程),我正在尝试编写一个用户输入数据点的程序。然后将数据点保存在一个数组中,然后可以对它们进行操作。

我陷入困境:我希望用户能够输入(几乎)任意数量的点,然后使用各种“关键字”来表示数据输入的结束。在这种情况下,用户将键入“完成”。

这是我到目前为止所拥有的:

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

int main(void) {

printf("\n Welcome! \n\n Please enter each data point. Enter 'done' when finished.\n\n");

double data[1048];
int i, count;

for (i = 1; ;i++) {

    printf("Data[%i]: ", i);
    scanf("%lf", &data[i]);

    if (data[i] == 'done') {

        break;

    } else {

        count++;

    }

  } 

}

我试过'返回1;' '打破;'。每次,程序都能正常运行,直到输入“关键字”,此时我得到:

Data[8]: Data[9]: ... Data[1120]: Data[1Segmentation fault 11 

它唯一有效的时间是当用户输入特定数字(如-1或0)时它会中断。但这对用户来说并不适用,因为他们可能必须将这些数字作为数据点输入。

很抱歉这篇长篇文章,但感谢您的帮助!

6 个答案:

答案 0 :(得分:5)

您的问题已收到许多好的答案,还有几种方法可以输入doubles并停在"done"上。由于您正在学习C,因此 始终 (如果不清楚),检查 scanf的返回验证您实际发生的转化的数量。 [1] (这也提供了在"done"上结束输入的方法(或任何非双重输入导致scanf返回少于1

如评论中所述,数组在C中 基于零 。当您接受输入时,您将需要使用count作为您的数组 - 索引,而不是i(在这种情况下,如果您在每次失败时退出读取 - 这没关系,但您可以轻松地再次提示输入其他输入并仅在a {1}上增加countscanf成功返回)返回到您的问题。如果将读取循环设置为持续循环直到出现scanf失败,则可以使用临时变量来初始捕获输入值,并仅将值分配给数组并在成功时递增索引。例如(常数MAXD = 1048

for (;;) {  /* loop until scanf input fails (with 'done') */

    double tmp;  /* block scope declarations are fine */

    printf (" data[%4d]: ", count);

    if (count < MAXD && scanf(" %lf", &tmp) == 1)
        data[count++] = tmp;
    else
        break;
} 

(您甚至可以在循环上方移动提示的副本,并在if (....) {...}之后移动上面的提示,以在达到数组限制(MAXD)时消除提示 - 这是左边的作为练习)

在上面的示例中,您有2个条件在存储值之前强制执行。 (1)您将用户可以存储的值的数量限制为MAXD,以及(2)如果在double中进行scanf的有效转换,则只存储值。如果其中一个条件失败,您将离开循环(如果您输入"done"作为双值,则会离开循环。)

将这些内容放在一起并在评论中添加一些其他提示,您可以使用以下内容进行测试:

#include <stdio.h>

enum { MAXD = 1048 };   /* declare constants instead of using magic numbers */

int main (void) {

    double data[MAXD] = {0};    /* in ISO C declarations come before code */
    int i, count = 0;           /* initializing variable saves debug time */

    printf ("\n Welcome! \n\n Please enter each data point. "
            "Enter 'done' when finished.\n\n");

    for (;;) {  /* loop until scanf input fails (with 'done') */

        double tmp;  /* block scope declarations are fine */

        printf (" data[%4d]: ", count);

        if (count < MAXD && scanf(" %lf", &tmp) == 1)
            data[count++] = tmp;
        else
            break;
    } 

    printf ("\n %d values entered:\n\n", count);

    for (i = 0; i < count; i++)
        printf ("  data[%4d] : %.2lf\n", i, data[i]);

    return 0;   /* main() is type 'int' and returns a value */
}

示例使用/输出

$ ./bin/scanfdoubles

 Welcome!

 Please enter each data point. Enter 'done' when finished.

 data[   0]: 1.1
 data[   1]: 1.2
 data[   2]: 1.3
 data[   3]: 1.4
 data[   4]: 1.5
 data[   5]: 1.6
 data[   6]: done

 6 values entered:

  data[   0] : 1.10
  data[   1] : 1.20
  data[   2] : 1.30
  data[   3] : 1.40
  data[   4] : 1.50
  data[   5] : 1.60

仔细看看,如果您有任何问题,请告诉我。

<强> 脚注:

1。 ,当您可以使用scanf在C中获取用户输入时,您最好使用< em>面向行的函数(如fgets)然后解析整行(例如sscanf)。允许您同时(1)验证读取(例如,fgets的返回),然后(2)分别验证用户输入的值。您读取的 解耦 ,您的解析有很多优点。

答案 1 :(得分:1)

数据[]的任何元素都不会被完成&#39; (他们会漂浮)。如果你想直接scanf(),你需要选择一个结束序列的double值(通常为零或-1或其他)。如果这不起作用,你可以使用类似的东西:

  1. 使用fgets()来拉取字符串,然后使用strncmp()来检查终止值,使用sscanf()来拉出双精度,或者:
  2. 让用户使用Ctrl-D终止并检查EOF的扫描值。
  3. 哦,严格来说,你有条目的上限。你应该检查我,以确保你不会超过这个。永远不要假设您的输入不会超出界限。静态分配变量上的sizeof()或一些#defined宏来跟踪它。

答案 2 :(得分:0)

  • 您的data类型为double。它无法扫描文字“完成”。

而是使用EOF来检查输入结束。

while(scanf("%lf",&data[i]) != EOF) {
    ...
}

另一种方式:

while(scanf("%lf",&data[i]) == 1) {
    ...
}
  • 另一件事,将计数初始化为零,即count = 0;

答案 3 :(得分:0)

底线:不要使用scanf

使用类似

的内容
char inputline[100];

i = 0;

while(fgets(inputline, sizeof(inputline), stdin) != NULL) {
    if(strncmp(inputline, "done", 4) == 0) break;
    data[i++] = atof(inputline);
}
即使所有输入都是您期望的数字,

scanf也很难使用。如果输入可能是数字或单词&#34;已完成&#34;,scanf将永远不会有效。但是,阅读一行文本(如此处)通常更容易,也更灵活。

P.S。您还必须担心用户输入超过1048个号码的可能性。

答案 4 :(得分:0)

对于您的任务,收集输入的循环不仅应控制关键字,还应控制输入时的数字。我建议如下:

#include <stdio.h>
#include <string.h>
#define NUM_OF_DATA 1048

int main(void) 
{
    printf("\n Welcome! \n\n Please enter each data point. Enter 'done' when finished.\n\n");
    double data[NUM_OF_DATA];
    int i; // counter of entered numbers
    char str[5] = { 0 }; // string to read 'done' or other word from input
    for (i = 0; i < NUM_OF_DATA; i++) // the first index of data in array is 0 (the last NUM_OF_DATA-1)
    {
        printf("Data[%i]: ", i);
        if (1 == scanf("%lf", &data[i])) // if number was successfully read
            continue; // go to next iteration
        // if some problem was with reading a loat number
        // read the string
        scanf("%4s", str); // read not more than 4 characters from input
        if ( strcmp(str, "done") == 0) 
        {
            break; // stop input if 'done' was entered
        }
        // clean input buffer before next input
        while (getchar() != '\n');
        // correct counter in case of wrong input
        i--;
    }
    // output the number of correct inputs
    printf("%d numbers were entered.\n", i);
    // do something with data
    // taking in account, that i is not index of the last element, 
    // but the number of elements (indexes are 0 ... i-1)
    // ...
    return 0;
}

for循环在两种情况下停止:

1)当data数组已满时,

2)当'done'没有输入引号时。

其他功能是跳过不正确的输入(尝试它的工作原理)。

答案 5 :(得分:-1)

数据的数据类型为双

double data[1048]; 

你将它与字符值等同起来。那是一个类型错误。如果要等同,请使用字符数据类型,而不是double。 Double是浮点类型。