首先,谢谢你的帮助!
我是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)时它会中断。但这对用户来说并不适用,因为他们可能必须将这些数字作为数据点输入。
很抱歉这篇长篇文章,但感谢您的帮助!
答案 0 :(得分:5)
您的问题已收到许多好的答案,还有几种方法可以输入doubles
并停在"done"
上。由于您正在学习C,因此 始终 (如果不清楚),检查 scanf
的返回验证您实际发生的转化的数量。 [1] (这也提供了在"done"
上结束输入的方法(或任何非双重输入导致scanf
返回少于1
)
如评论中所述,数组在C中 基于零 。当您接受输入时,您将需要使用count
作为您的数组 - 索引,而不是i
(在这种情况下,如果您在每次失败时退出读取 - 这没关系,但您可以轻松地再次提示输入其他输入并仅在a {1}上增加count
从scanf
成功返回)返回到您的问题。如果将读取循环设置为持续循环直到出现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或其他)。如果这不起作用,你可以使用类似的东西:
哦,严格来说,你有条目的上限。你应该检查我,以确保你不会超过这个。永远不要假设您的输入不会超出界限。静态分配变量上的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是浮点类型。