修改C电话簿程序以返回匹配数组,而不仅仅是一个匹配项

时间:2014-10-06 13:41:06

标签: c arrays

我正在修改一个小程序,我已经成功地将这个小程序变成了一个更大的程序,但我仍然需要两个函数。

  1. 有编辑选项
  2. 在搜索时返回多个记录。
  3. 我正在帮助我的一个朋友。

    #include <stdio.h>
    
    
    #define CAPACITY 100
    
    /* User commands */
    
    #define ADD 'a'
    #define FIND   'f'
    #define LIST   'l'
    #define QUIT   'q'
    
    #define NAME_LEN 80
    #define NUMBER_LEN 40
    
    /* In memory representation of an entry in the phonebook. */
    
    typedef struct {
      char name[ NAME_LEN ];
      char number[ NUMBER_LEN ];
    } phone_record;
    
    /* Procedures in phonebook.c */
    
    char get_command( void );
    phone_record *get_record( void );
    void add_record( phone_record *new_record );
    void list_phonebook( void );
    int find_name( char *name );
    
    int num_entries;           // Number of entries currently in the phone book
    phone_record **phonebook;  // Where the names are stored
    
    int main( int argc, char **argv ) {
      char ch;
      char name[ NAME_LEN ];
      char confirm[ 10 ];
      phone_record *rec;
      int loc;
    
      // Create an empty phonebook
      phonebook = (phone_record **)malloc( sizeof( phone_record *) * CAPACITY );
      num_entries = 0;
    
      // Read commands until the user gets tired
      while ( ( ch = get_command() ) != QUIT ) {
        switch( ch ) {
          case ADD:
            // Get new info
            rec = get_record();
    
              add_record( rec );
    
            break;
    
          case FIND:
            // Name to find
            printf( "Name:  " );
            scanf( "%s", name );
    
            // Look for the name
            if ( ( loc = find_name( name ) ) != -1 ) {
              printf( "Number:  %s\n", phonebook[ loc ]->number );
            }
            else {
              printf( "That name is not in the phonebook\n" );
            }
            break;
    
          case LIST:
            // List the phonebook
            list_phonebook();
            break;
        }
      }
    }
    
    /* 
     * Read and return a command from the keyboard. 
     */
    char get_command() {
      char line[ 80 ];
    
      do {
        // Get input
        printf( "pb> " );
    
        // scanf returns -1 when it encoutners EOF - pretend we saw quit
        if ( scanf( "%s", line ) == -1 ) {
          line[ 0 ] = QUIT;
          printf( "\n" );  // Add new line so terminal looks nice
        }
    
        // Verify input (lightly)
        switch( line[ 0 ] ) {
          case ADD:
          case FIND:
          case LIST:
          case QUIT:
            break;
          default:
            printf( "Unrecognized command\n" );
            line[ 0 ] = 0;
        }
      } while ( line[ 0 ] == 0 );
    
      return line[ 0 ];
    }
    
    /*
     * Add a new record to the phonebook.
     */
    void add_record( phone_record *new_record ) {
      int cur;
    
      // Make sure there is room
      if ( num_entries == CAPACITY ) {
        printf( "Sorry phonebook is full\n" );
      }
      else {
        // Insertion sort.  Start at bottom and copy elements down one until
        // you find the first one less than what we are adding or we hit the
        // top of the phonebook
        for ( cur = num_entries; 
              cur > 0 && strcmp( phonebook[ cur - 1 ]->name, new_record->name ) > 0;
              cur = cur - 1 ) {
    
          phonebook[ cur ] = phonebook[ cur - 1 ];
        }
    
        // Add the entry in the open slot
        phonebook[ cur ] = new_record;
        num_entries = num_entries + 1;
      }
    }
    
    /*
     * List the entries in the phonebook.
     */
    void list_phonebook() {
      int i;
    
      if ( num_entries != 0 ) {
        printf( "Name\t\tNumber\n" );
        printf( "----\t\t------\n" );
    
        for ( i = 0; i < num_entries; i = i + 1 ) {
          printf( "%s\t\t%s\n", phonebook[ i ]->name, phonebook[ i ]->number );
        }
      }
      else {
        printf( "There are no entries in the phonebook\n" );
      }
    }
    
    
    /*
     * Find a name in the phonebook.  -1 means it is not there.
     */
    int find_name( char *name ) {
      int pos = -1;
      int i;
    
      for ( i = 0; pos == -1 && i < num_entries; i = i + 1 ) {
        if ( strcmp( name, phonebook[ i ]->name ) == 0 ) pos = i;
      }  
    
      return pos;
    }
    
    /*
     * Read and return a phone record from the keyboard.
     */
    phone_record *get_record() {
      phone_record *rec;
      char *name;
      char *number;
    
      // Allocate storage for the phone record.  Since we want the record
      // to live after the function returns we need to use malloc
      rec = (phone_record *)malloc( sizeof( phone_record ) );
    
      // Get the data
      printf( "Name:  " );
      scanf( "%s", rec->name );
    
      printf( "Phone:  " );
      scanf( "%s", rec->number );
    
      return rec;
    }
    

    在电话簿阵列中找到匹配名称的find_name()函数是:

    int find_name( char *name ) {
      int pos = -1;
      int i;
    
      for ( i = 0; pos == -1 && i < num_entries; i = i + 1 ) {
        if ( strcmp( name, phonebook[ i ]->name ) == 0 ) pos = i;
      }  
    
      return pos;
    }
    

    它只返回一个显示电话簿匹配元素位置的整数:

    if ( ( loc = find_name( name ) ) != -1 ) {
      printf( "Number:  %s\n", phonebook[ loc ]->number );
    }
    

    我认为方法find_name应该返回一个数组,但我不知道如何实现它。

2 个答案:

答案 0 :(得分:1)

使用负数(-1)返回整数数组可能最简单,以指示整数列表的结尾。

因此,您的功能将被修改为类似以下内容。我实际上没有编译这个,所以你可能需要解决一些问题。

int find_name( char *name, int *iList, int nListSize ) {
  int pos = -1;
  int i;
  int j;

  for ( j = i = 0; i < num_entries; i = i + 1 ) {
    if ( strcmp( name, phonebook[ i ]->name ) == 0 ) {
        if (j + 1 < nListSize)
            iList[j++] = i;
    }
  }  

  iList[j] = -1;      // indicate the end of the list
  if (j < nListSize) pos = j;  // return the number of items in the list
  return pos;
}

您需要修改使用此函数创建整数数组的方式,并将数组与最大数组条目一起传递。然后检查返回值以确定找到了多少(如果有)匹配。

如果找到的匹配项数多于可用的数组元素,则该函数返回-1。

修改

case FIND:中你会做一个类似于下面的输出循环。我再次没有进行编译或测试,但这是概念。如果此示例中有超过100个匹配的名称,那么您确实遇到了问题,因此您需要考虑如何处理这种可能性:

// Look for the name
{
    int   aList[100];   // just a large array and hope no more than this matching entries
    if ( ( loc = find_name( name, aList, 100 ) ) > 0 ) {
        int iLoop = 0;
        // loop through the list to print out the matching entries.
        for (iLoop= 0; aList[iLoop] >= 0; iLoop++) {
            printf( "Number:  %s\n", phonebook[ aList[iLoop] ]->number );
        }
    }
    else {
        printf( "That name is not in the phonebook or too many matches\n" );
    }
}

修改

您也可以考虑使用稍微不同的方法来创建使用迭代器类型方法的find_name()。我们的想法是拥有一个充当电话簿迭代器的变量。如果有匹配的名称,则迭代器变量返回指向匹配数据的指针。

我再次编译或测试过,所以可能需要你做一些工作。

由于需要更新迭代器结构,我们需要传递一个指向迭代器结构的指针,以便在处理电话簿数组时更新它。

int find_name( char *name, phonebookitera *pItera ) {
  int pos = -1;

  for (; pItera->pos < num_entries; pItera->pos++ ) {
    if ( strcmp( name, phonebook[ pItera->pos ]->name ) == 0 ) {
        // copy the matching pointers to our iterator 
        pItera->name = phonebook[ pItera->pos ]->name;
        pItera->number = phonebook[ pItera->pos ]->number;
        // we will return the matching position in phonebook though not necessary
        pos = pItera->pos;
        pItera->pos++;     // increment to the following element
        return pos;
    }
  }  

  return pos;
}

此函数将用于以下代码中。

{
    phonebookitera myItera = {0};
    // iterate through the list to print out the matching entries.
    if (find_name (name, &myItera) >= 0) {
        do {
            printf( "Number:  %s\n", myItera.number );
        } while (find_name (name, &myItera) >= 0);
    } else {
        printf( "That name is not in the phonebook\n" );
    }

}

您可以将phonebookitera定义为:

typedef struct {
    int  pos;
    char *name;
    char *number;
} phonebookitera;

答案 1 :(得分:0)

使用NAMES作为过滤器获取数字列表的最简单方法是:

find_by_surname(surname);&lt; ---在CASE FIND

和查找名称功能:

void find_name( char *name ) {

int i;
  if ( num_entries != 0 ) {
    printf( "Name\t\tNumber\n" );
    printf( "----\t\t------\n" );


    for ( i = 0; i < num_entries; i = i + 1 ) {
        if ( strcmp( name, phonebook[ i ]->name ) == 0 )
      printf( "%s\t\t%s\n", phonebook[ i ]->name, phonebook[ i ]->number );
    }
  }
  else {
    printf( "There are no entries in the phonebook\n" );
  }
}