将我的数组转换为函数并制作第二个函数来打印它

我试图创建一个有2个选项,查看和计算的程序。 现在我试图想办法如何转动我的数组,我将我的值输入到一个函数中,所以我可以进出几次来存储值。 我也想查看一个函数,我可以多次查看值。

我已经设法让计算部分在我的主要工作,现在我需要把它变成一个function。 其次,我如何创建第二个函数来查看它?

我的代码有点乱,请耐心等待。

#include  #define LENGTH 10 int enterMeasurements(); int main(void) { char input; int nrMeasurements=0; int arrayTable[LENGTH] = {0}; //main menu do { char input; printf("\nMeasurement tool 1.0\n"); printf("V for (View)\n"); printf("E for (Enter Values)\n"); printf("C for (Compute Values)\n"); printf("R for (Reset Values)\n"); printf("Q for (Quit)\n"); printf("\nEnter input: "); scanf(" %c", &input); if(input == 'v' || input == 'V') { // function to print array values printf("[ ]\n"); } else if(input == 'e' || input == 'E') { // enter values here nrMeasurements = enterMeasurements(arrayTable,nrMeasurements); // my function for entering values } else if (input == 'c' || input == 'C') { // enter function to calc min, max and avg and prints it. printf("[ min max avg ]\n"); } else if (input == 'r' || input == 'R') { // enter function that erase the entire array. printf("[ erase array ]\n"); } } while (input !='q' && input != 'Q'); return 0; } int enterMeasurements() { int enterMeasurements(int arrayTable[], int nrMeasurements) { int i; for (i = 0; i < LENGTH; i++) { printf("Enter Measurement #%i (or 0): ", i+1); scanf("%d", &arrayTable[i]); if (arrayTable[i] == 0 ) break; } return i; } 

为了帮助您入门(您应该阅读有关该主题的初学者书 ),我将向您展示printArray函数。

首先, printArray函数需要知道要打印的实际数组。 它还需要知道数组中元素的数量。 这可以通过两种方式实现:全局变量(没有人真正推荐)或使用函数参数

首先需要告诉编译器函数接受参数:

 void printArray(int *array, size_t numElements) 

上面的行告诉编译器printArray函数有两个参数:一个叫做array ,是一个指向int的指针(数组“衰减”到传递给函数时指向它们的第一个元素的指针),还有一个名为numElements参数和是size_t类型(对于大小和元素和类似事物的数量,这是一个很好的类型)。 声明该函数不返回void关键字。

然后声明的参数可以像函数范围内的任何其他变量一样在函数内使用,实际上就像函数内定义的任何其他局部变量一样。 所以你可以像使用它们一样使用它们

 void printArray(int *array, size_t numElements) { for (size_t i = 0; i < numElements; ++i) { printf("array[%d] = %d\n", i, array[i]); } } 

要调用此函数,您需要传递数组和元素数,就像将参数传递给scanfprintf类的任何其他函数一样:

 printArray(arrayTable, i); 

请注意,该函数不返回任何内容,这意味着您无法在printf或任何其他需要值的表达式中使用它。

您当然也应该使您的前向函数原型声明与实际函数定义相匹配。

Alex继续你的上一条评论,显示一个菜单,允许你向数组中添加值,从数组中删除值并查看数组(以及值的最大值最小值平均值 ),可以做类似的事情以下。 注意:命令行不是窗口用户界面,因此您的菜单操作更像是打印的事务收据。 (你可以做很好的文本窗口和固定菜单,但这通常需要一个文本库,比如ncurses ,这超出了你的问题的范围。

正如评论中所解释的那样,您的基本方法就是创建一个不断重复的循环。 它将显示您的菜单,并允许您从列表中输入您的选择,例如:

  ======== Program Menu ========= V) View the Array. I) Insert New Value. D) Delete Existing Value. N) Display Minimum Value. X) Display Maximum Value. A) Display Average of Values. S) Display Sum of Values. Q) Quit. Selection: 

用户输入选择后,为了使比较更容易,用户的输入转换为小写 。 另请注意,使用fgets (面向行的输入函数)将输入读取为字符串,这使得用户输入更容易,而不必担心'\n'是否仍然在输入缓冲区( stdin )中等待导致下一次输入出现问题。 (您可以使用scanf系列函数,但您负责计算用户输入的每个字符(并清空输入缓冲区)。

使用fgets读取输入将读取并包括'\n' ,因此它们不可能在stdin中保留'\n'未读。 另请注意, fgets将读取一个或多个字符串,您只对第一个字符串感兴趣。 只需引用缓冲区中的第一个字符即可轻松处理。 (例如,如果您正在将用户输入读入名为buf ,您可以简单地使用buf[0]来访问第一个字符,或者只是简单地使用*buf

读取用户输入后,第一个字符将传递给switch语句,其中语句的每个case与第一个字符进行比较。 如果角色与案例匹配,那么将采取与该案例相关联的操作,以break结束(如果您自己省略了break则可以阅读有关后续处理的内容)

正如评论中所提到的,如果你只需要打破一个循环,那么就是你所需要的。 但是在这里,你的switch语句在循环中。 一次break只会让你离开switch而不是外面for循环。 要打破嵌套循环,请使用goto语句。 (你也可以添加更多的变量并设置某种类型的退出标志,但为什么呢?这就是goto意图。(在某些情况下,旗帜也同样好)

在每种case ,您都可以自由调用处理该菜单选项所需的任何代码。 您将注意到我们只需从switch内调用短辅助函数来打印数组,插入值,删除值等。如果您愿意,可以将所有代码放在switch ,它很快就会变得不可读。

总而言之,您可以执行以下操作:

 #include  #include  #include  #include  enum { MAXN = 64 }; /* constant - max numbers of vals & chars */ void showmenu (); void prnarray (int *a, int n); int addvalue (int *a, int n, int newval); int delvalue (int *a, int n, int index); int minvalue (int *a, int n); int maxvalue (int *a, int n); int sumvalues (int *a, int n); int main (void) { int vals[MAXN] = { 21, 18, 32, 3, 9, 6, 16 }, /* the array */ n = 7; for (;;) { /* loop until user quits or cancels, eg ctrl+d */ showmenu(); /* show the menu */ char buf[MAXN] = ""; fgets (buf, MAXN, stdin); /* read user input */ /* convert to lower-case for comparison of all entries */ switch (tolower (buf[0])) { /* 1st char is entry */ case 'v' : prnarray(vals, n); break; case 'i' : printf ("\n enter the new value: "); if (fgets (buf, MAXN, stdin) && isdigit (buf[0])) { n = addvalue (vals, n, atoi (buf)); } break; case 'd' : printf ("\n enter the index to delete: "); if (fgets (buf, MAXN, stdin) && isdigit (buf[0])) { n = delvalue (vals, n, atoi (buf)); } break; case 'n' : printf ("\n Mininum of '%d' values is : %d\n", n, minvalue (vals, n)); break; case 'x' : printf ("\n Maxinum of '%d' values is : %d\n", n, maxvalue (vals, n)); break; case 'a' : printf ("\n Average of '%d' values is : %.2lf\n", n, (double)sumvalues (vals, n)/n); break; case 's' : printf ("\n Sum of '%d' values is : %d\n", n, sumvalues (vals, n)); break; case 'q' : printf (" that's all folks...\n"); goto done; default : if (!buf[0]) { /* check for manual EOF */ putchar ('\n'); /* tidy up */ goto done; } fprintf (stderr, "error: invalid selection.\n"); } } done:; /* goto label - breaking 'for' and 'switch' */ return 0; } void showmenu () { fprintf(stderr, "\n ======== Program Menu =========\n\n" " V) View the Array.\n" " I) Insert New Value.\n" " D) Delete Existing Value.\n" " N) Display Minimum Value.\n" " X) Display Maximum Value.\n" " A) Display Average of Values.\n" " S) Display Sum of Values.\n" "\n" " Q) Quit.\n" "\n" " Selection: "); } void prnarray (int *a, int n) { int i; printf ("\n there are '%d' values in the array:\n\n", n); for (i = 0; i < n; i++) printf (" array[%2d] : %d\n", i, a[i]); } int addvalue (int *a, int n, int newval) { if (n == MAXN) { fprintf (stderr, "error: all '%d' values filled.\n", n); return n; } a[n++] = newval; return n; } int delvalue (int *a, int n, int index) { if (index < 0 || index > n - 1) { fprintf (stderr, "error: index out of range.\n"); return n; } int i; for (i = index + 1; i < n; i++) a[i-1] = a[i]; a[i] = 0; return --n; } int minvalue (int *a, int n) { int i, min = INT_MAX; for (i = 0; i < n; i++) if (a[i] < min) min = a[i]; return min; } int maxvalue (int *a, int n) { int i, max = INT_MIN; for (i = 0; i < n; i++) if (a[i] > max) max = a[i]; return max; } int sumvalues (int *a, int n) { int i, sum = 0; for (i = 0; i < n; i++) sum += a[i]; return sum; } 

(注意:您可以添加额外的validation检查,以测试您是否已阅读用户提供的所有输入等。但鉴于您的问题的关键,我将留给您学习)

示例使用/输出

 $ ./bin/menusimple ======== Program Menu ========= V) View the Array. I) Insert New Value. D) Delete Existing Value. N) Display Minimum Value. X) Display Maximum Value. A) Display Average of Values. S) Display Sum of Values. Q) Quit. Selection: v there are '7' values in the array: array[ 0] : 21 array[ 1] : 18 array[ 2] : 32 array[ 3] : 3 array[ 4] : 9 array[ 5] : 6 array[ 6] : 16 ======== Program Menu ========= V) View the Array. I) Insert New Value. D) Delete Existing Value. N) Display Minimum Value. X) Display Maximum Value. A) Display Average of Values. S) Display Sum of Values. Q) Quit. Selection: i enter the new value: 77 ======== Program Menu ========= V) View the Array. I) Insert New Value. D) Delete Existing Value. N) Display Minimum Value. X) Display Maximum Value. A) Display Average of Values. S) Display Sum of Values. Q) Quit. Selection: v there are '8' values in the array: array[ 0] : 21 array[ 1] : 18 array[ 2] : 32 array[ 3] : 3 array[ 4] : 9 array[ 5] : 6 array[ 6] : 16 array[ 7] : 77 

仔细看看,如果您有任何疑问,请告诉我。 此外,正如您刚刚学习的那样,请确保您在编译代码时编译警告已启用,并且在没有警告的情况下进行编译之前,您不会认为代码可靠。 这意味着你应该至少使用-Wall -Wextra标志进行编译。 如果您使用的是gcc和命令行,那么它将是:

 gcc -Wall -Wextra -O2 -o simplemenu simplemenu.c 

simplemenu.c的代码编译为名为simplemenu的可执行文件,并应用-O2优化。 如果您真的想要消除所有警告,请添加-pedantic 。 对于代码块或其他IDE,查看编译器菜单选项,它们都提供了一个输入所需选项的位置。 祝你的代码好运。


没有function和输入的程序方法使用scanf

好了,既然我们知道需要备份多远,那么让我们看看在没有使用函数的情况下以最小化,自上而下的方式重写代码,并将用户输入与scanf (这会让你更加悲伤,尤其是混合角色和数字输入,但如果你考虑stdin'\n' ,它就可以完成

首先是关于使用scanf获取输入的注释。 当您要求用户输入时,例如菜单选择,并且用户输入V并按Enter键 ,输入缓冲区stdin包含"V\n" (按Enter键'\n' )。 然后当你使用scanf读取一个字符(例如char sel; scanf ("%c", &sel); )时, 'V'取自stdin并存储在sel ,在stdin保留'\n' 。 如果您然后尝试读取另一个字符(例如char nextch; scanf ("%c", &nextch); )则会出现scanf跳过读取nextch因为它永远不允许您输入值。 实际发生的是scanf ("%c", &nextch); 已经读取了作为下一个字符的stdin中保留的'\n' ,并且非常满足于nextch0xa (十进制10)的nextch

使用scanf时,您必须始终考虑'\n' 。 您有两个选项,1)在转换说明符前留一个空格(例如scanf (" %c", &nextch);或2)使用赋值抑制运算符 '*' (例如scanf ("%c%*c", &nextch); ),第二个%*c告诉scanf 读取并丢弃以下字符而不将转换添加到匹配计数 (这是scanf返回的整数值)。 这提出了最重要的一点总是检查 scanf 的返回 。 (否则,你不知道你是否有一个实际值可以使用或只是垃圾)我将把man scanf的读数留给你,以获得有关转换说明符前的空格效果和赋值抑制运算符的更多详细信息。

scanf的返回值( 匹配计数 )是根据格式字符串中包含的转换说明符数量执行的成功转换次数(例如scanf (" %c %d", &somechar, &someint);包含2 转换说明符 %c%d ,所以两次成功转换后scanf的返回值为2如果发生匹配或转换失败,返回值将小于2 ,如果遇到错误条件,则从流中读取(本例中为stdin )返回EOF (通常值为-1所有这些,以及更多,这就是为什么scanf不是在C中获取用户输入的首选方法 (也就是说,这是大多数教程和大多数教师所做的在不了解陷阱的情况下暴露新C程序员的糟糕选择)

有了这个,如果你通过下面的例子,你会发现我只是将代码从函数移动到if ... else if ... else框架中。 (看看我从第一个例子和下面的代码中调用函数调用函数的一对一关系)这也应该说明为什么要将代码分解为逻辑函数,提高可读性并改善代码重用。 比较switch语句与if ... else if ... else菊花链的使用。 两者都很好,但对我来说, switch更容易阅读一目了然。

你应该确保你理解这两个版本,因为它们都是使用C的基本入门级方法。花时间浏览每个版本如果你有问题,你无法通过参考tag-wiki链接中提供的参考之一回答,只需问。

 #include  #include  /* for atoi */ #include  /* for INT_MIN/INT_MAX */ enum { MAXN = 64 }; /* constant - max numbers of vals & chars */ int main (void) { int vals[MAXN] = { 21, 18, 32, 3, 9, 6, 16 }, /* the array */ n = 7; for (;;) { char c; /* show the menu */ fprintf(stderr, "\n ======== Program Menu =========\n\n" " V) View the Array.\n" " I) Insert New Value.\n" " D) Delete Existing Value.\n" " N) Display Minimum Value.\n" " X) Display Maximum Value.\n" " S) Display Sum of Values.\n" " A) Display Average of Values.\n" "\n" " Q) Quit.\n" "\n" " Selection: "); /* read selection (inside of if is OK), check EOF or quit */ if (scanf (" %c", &c) == EOF || c == 'q' || c == 'Q') { printf ("\n that's all folks...\n"); break; } if (c == 'v' || c == 'V') { /* view array code */ printf ("\n there are '%d' values in the array:\n\n", n); int i; for (i = 0; i < n; i++) printf (" array[%2d] : %d\n", i, vals[i]); } else if (c == 'i' || c == 'I') { /* insert value code */ if (n == MAXN) { fprintf (stderr, "error: all '%d' values filled.\n", n); continue; } int newval = 0; printf ("\n enter the new value: "); if (scanf (" %d", &newval) == 1) { vals[n] = newval; n++; } else fprintf (stderr, "error: invalid input.\n"); } else if (c == 'd' || c == 'D') { /* delete value code */ int i, index = 0; printf ("\n enter the index to delete: "); if (scanf (" %d", &index) != 1) { fprintf (stderr, "error: invalid input.\n"); continue; } if (index < 0 || index > n - 1) { fprintf (stderr, "error: index out of range.\n"); continue; } for (i = index + 1; i < n; i++) vals[i-1] = vals[i]; vals[i] = 0; n--; } else if (c == 'n' || c == 'N') { /* display minimum code */ int i, min = INT_MAX; for (i = 0; i < n; i++) if (vals[i] < min) min = vals[i]; printf ("\n Mininum of '%d' values is : %d\n", n, min); } else if (c == 'x' || c == 'X') { /* display maximum code */ int i, max = INT_MIN; for (i = 0; i < n; i++) if (vals[i] > max) max = vals[i]; printf ("\n Maxinum of '%d' values is : %d\n", n, max); } else if (c == 's' || c == 'S') { /* compute sum code */ int i, sum = 0; for (i = 0; i < n; i++) sum += vals[i]; printf ("\n Sum of '%d' values is : %d\n", n, sum); } else if (c == 'a' || c == 'A') { /* compute avg code */ int i, sum = 0; double avg = 0.0; for (i = 0; i < n; i++) sum += vals[i]; avg = (double)sum/n; printf ("\n Average of '%d' values is : %.2lf\n", n, avg); } else /* if not matched, then invalid selection */ fprintf (stderr, "error: invalid selection.\n"); } return 0; } 

(两个程序版本的操作和输出都是相同的)