比较两个整数数组并返回下标(C)

时间:2016-04-24 02:34:03

标签: c

(我的程序的新版本最终正确)

我需要创建一个程序,其中包含一个比较两个整数数组的函数,并返回它们不同的第一个地方的下标。

我必须使用sentinel值来指示有效输入的结束,而不是EOF,因为文件不能有两个文件结束。

我的程序的所需输入和输出示例:

输入1:

    3 4 5

    3 4 6

输出1:

       2

说明:两个数组的第三个值不同,因此它打印第三个下标(计为0,1,2)。

我查看了stackoverflow上的类似问题。修复了许多错误,现在它允许我编译程序,而不会给我任何错误或警告。但它让我蒙羞,因为我不明白究竟什么不起作用。

我遇到的问题:

  • 当我在第一个值后按 Enter 按钮时,程序停止工作。

我认为我的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");
}

1 个答案:

答案 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'

查看示例,如果您有任何其他问题,请告诉我。