(我的程序的新版本最终正确)
我需要创建一个程序,其中包含一个比较两个整数数组的函数,并返回它们不同的第一个地方的下标。
我必须使用sentinel值来指示有效输入的结束,而不是EOF,因为文件不能有两个文件结束。
我的程序的所需输入和输出示例:
输入1:
3 4 5
3 4 6
输出1:
2
说明:两个数组的第三个值不同,因此它打印第三个下标(计为0,1,2)。
我查看了stackoverflow上的类似问题。修复了许多错误,现在它允许我编译程序,而不会给我任何错误或警告。但它让我蒙羞,因为我不明白究竟什么不起作用。
我遇到的问题:
我认为我的tableDiff函数是错误的,但是我从教师的笔记中复制了它。除非我写错字,否则应该没有任何区别。
这是我提交的版本:
/*
* A simple program to sort numbers in the correct order
*/
#include <stdio.h>
#include <stdlib.h>
#define MAX 10 //max elements in array
#define SENTINEL -999 //indicate the end of valid input
int main () {
int tableFill(int a[], int max);
int tableDiff (const int a[], const int b[], int n, int m);
void tablePrint (const int a[], const int b[], int n, int m);
int a[MAX];
int b[MAX];
int m,n,index;
m = tableFill(a, MAX);
n = tableFill(b, MAX);
tablePrint(a,b,n,m);
index = tableDiff(a,b,m,n);
if(index==-1)
printf("Index is the same");
else
printf("Index is the different");
return 0;
}
// read values from stdin into array up to 'max' values
int tableFill(int a[], int max) {
int r; // input from scanf
int next; // next input value
int cnt = 0; // count of values read
int *ptr; //pointer
printf("Enter the numbers! \n");
while ((r=scanf("%i", &next)) == 1 && next != SENTINEL)
{
if (r == 0) //invalid input data
{
printf("Nonnumeric data entered. Please enter a number. \n");
while (getchar()!= '\n'); // flush invalid data
}
else
*ptr++=cnt;
}
if(r==1) //another value was read but the array is full
printf("Error - too many values. Array size %i.\n", max);
return ptr-a; //(ptrb - b) should return the same value
}
int tableDiff (const int a[], const int b[], int n, int m)
{
const int *ptra = a; //start for 1st array
const int *ptrb = b; //start for 2nd array
const int *endptra = a+m; //end for 1st array
const int *endptrb = b+n; //end for 2nd array
while(ptra<endptra && ptrb<endptrb && *ptra==*ptrb)
{
ptra++;
ptrb++;
}
if( ptra==endptra && ptrb==endptrb)
{
return -1;
}
else
return ptra -a; //(ptrb - b) should return the same value
}
//print all elements in array.
void tablePrint (const int a[], const int b[], int n, int m)
{
int i; //varriable to print
for (i = 0; i < n; i++)
printf ("%d ", a[i]);
printf ("\n");
}
这是我的新版本:
该程序现在继续工作,直到达到第二个哨兵(正常工作)。
/*
* A simple program to sort numbers in the correct order
*/
#include <stdio.h>
#define MAX 10 //max elements in array
#define SENTINEL -999 //indicate the end of valid input
int main () {
// read values from stdin into array up to 'max' values
int tableFill(int a[], int max);
//compare two arrays and returns the first subscript they differ
int tableDiff (const int a[], const int b[], int n, int m);
//print all elements in array
void tablePrint (const int a[], int n);
int a[MAX];
int b[MAX];
int m,n,index;
m = tableFill(a, MAX);
n = tableFill(b, MAX);
tablePrint(a,m);
tablePrint(b,n);
index = tableDiff(a,b,m,n);
if(index==-1)
printf("-1. Arrays are the same.");
else
printf ("\n The arrays differ at index '%d'.\n", index);
return 0;
}
// read values from stdin into array up to 'max' values
int tableFill(int a[], int max) {
int r; // input from scanf
int next; // next input value
int cnt = 0; // count of values read
int *ptr = a; //pointer
printf("Enter the numbers! \n");
while ((r=scanf("%i", &next))==0 || (next != SENTINEL))
{
if (r == 0) //invalid input data
{
printf("Nonnumeric data entered. Please enter a number. \n");
while (getchar()!= '\n'); // flush invalid data
}
else if (cnt == max) //another value was read but the array is full
printf("Error - too many values. Array size %i.\n", max);
else {
*ptr++ = next;
++cnt;
}
}
return ptr-a; //(ptrb - b) should return the same value
}
//compare two arrays and returns the first subscript they differ
int tableDiff (const int a[], const int b[], int n, int m)
{
const int *ptra = a; //start for 1st array
const int *ptrb = b; //start for 2nd array
const int *endptra = a+m; //end for 1st array
const int *endptrb = b+n; //end for 2nd array
while(ptra<endptra && ptrb<endptrb && *ptra==*ptrb)
{
ptra++;
ptrb++;
}
if( ptra==endptra && ptrb==endptrb)
{
return -1;
}
else
return ptra -a; //(ptrb - b) should return the same value
}
//print all elements in array
void tablePrint (const int a[], int n)
{
int i; //loop counter
for (i = 0; i < n; i++)
printf ("%d ", a[i]);
printf ("\n");
}
答案 0 :(得分:1)
您的逻辑中存在许多问题。
中的第一个while ((r=scanf("%i", &next)) == 1 && next != SENTINEL)
在输入非数字值的情况下,
阻止循环中的其余代码执行。如果r != 1
,则退出循环,而不是在其中进一步处理。
虽然不是错误,main
中的函数原型仅在 他们在执行期间对彼此一无所知。最好将原型移到main
之上。
你的逻辑的其余部分有些难以理解并且过于复杂。当您在两个数组中寻找差异时,您只需要迭代常见元素。如果它们具有不同数量的元素,您知道它们从第一个唯一元素开始按定义而不同。所以你可以减少你的比较代码。如下所示:
/* check if array 'a' and 'b' are the same, else return index
* of first difference, otherwise return -1 for equal arrays.
*/
int tablediff (const int *a, const int *b, int sza, int szb)
{
int i, lim = sza < szb ? sza : szb; /* limit search to common elements */
for (i = 0; i < lim; i++) /* for each common element check */
if (a[i] != b[i])
return i;
if (sza != szb) /* if size differs, arrays differ */
return lim;
return -1; /* otherwise equal */
}
您可以通过适当的边界检查来避免使用SENTINEL
。此外,虽然您可以自由创建一个打印2个数组的arrayprint
函数,但创建一个打印单个数组并调用它两次的函数要好得多。
将这些碎片放在一起,并注意到你没有使用stdlib.h
中的任何内容,你可以做类似以下的事情:
#include <stdio.h>
#define MAX 10 //max elements in array
int tablefill(int *a, int max);
int tablediff (const int *a, const int *b, int sza, int szb);
void tableprn (const int *a, int sza);
int main (void) {
int a[MAX];
int b[MAX];
int idx, sza, szb;
sza = tablefill (a, MAX);
szb = tablefill (b, MAX);
tableprn (a, sza);
tableprn (b, szb);
if ((idx = tablediff (a, b, sza, szb)) == -1)
printf ("\n the arrays are the same.\n\n");
else
printf ("\n the arrays differ at index '%d'\n\n", idx);
return 0;
}
/* read values from stdin into array up to 'max' values */
int tablefill (int *a, int max)
{
int idx = 0, tmp;
while (idx < max && scanf (" %d", &tmp) == 1)
a[idx++] = tmp;
return idx;
}
/* check if array 'a' and 'b' are the same, else return index
* of first difference, otherwise return -1 for equal arrays.
*/
int tablediff (const int *a, const int *b, int sza, int szb)
{
int i, lim = sza < szb ? sza : szb;
for (i = 0; i < lim; i++)
if (a[i] != b[i])
return i;
if (sza != szb)
return lim;
return -1;
}
/* print all elements in array. */
void tableprn (const int *a, int sz)
{
int i; //varriable to print
for (i = 0; i < sz; i++)
printf (" %d", a[i]);
printf ("\n");
}
示例等于
$ /bin/arraycmp <../dat/20intsame.txt
8572 -2213 6434 16330 3034 12346 4855 16985 11250 1495
8572 -2213 6434 16330 3034 12346 4855 16985 11250 1495
the arrays are the same.
示例差异
$ ./bin/arraycmp <../dat/20intdif.txt
8572 -2213 6434 16330 3034 12346 4855 16985 11250 1495
8572 -2213 6434 16330 3034 12346 4855 16985 11250 1494
the arrays differ at index '9'
提供输入提示
在接受用户输入时,最好还要提供有意义的提示,这样用户就不会看到一个闪烁的光标,想知道程序是否挂起,或者发生了什么。因此,除了上面的逻辑之外,您还需要添加简单的提示来解释程序需要什么以及如何提供输入。简单的事情会做:
printf ("\nenter a max of 10 integers below 'ctrl+d` to end.\n");
sza = tablefill (a, MAX);
printf ("enter a max of 10 integers below 'ctrl+d` to end.\n");
szb = tablefill (b, MAX);
printf ("\nthe arrays entered are:\n\n");
tableprn (a, sza);
tableprn (b, szb);
(注意:在windoze上生成手册EOF
,组合键是 ctrl + z )
因此,为每个数组输入少于10个整数,您可以执行以下操作:
$ ./bin/arraycmp
enter a max of 10 integers below 'ctrl+d` to end.
10 12 14 16 17
enter a max of 10 integers below 'ctrl+d` to end.
10 12 14 15 17
the arrays entered are:
10 12 14 16 17
10 12 14 15 17
the arrays differ at index '3'
查看示例,如果您有任何其他问题,请告诉我。