打印转换错误,Year始终等于零

时间:2014-05-11 18:55:54

标签: c

我有这段代码:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <assert.h>

#define MAX_TITLE_LENGTH  100
#define MAX_AUTHOR_LENGTH 100

/* Book structure */

struct Book
{
   /* Book details */
   char title[MAX_TITLE_LENGTH+1];   /* name string */
   char author[MAX_AUTHOR_LENGTH+1]; /* job string */
   int year;                         /* year of publication */

   /* pointers to left and right branches pointing down to next level in
      the binary tree */
   struct Book *left, *right;
};

/* tree of books, initialized to NULL. */
static struct Book *book_tree = NULL;

/* read_line():
 *
 * Read line of characters from file pointer "fp", copying the characters
 * into the "line" string, up to a maximum of "max_length" characters, plus
 * one for the string termination character '\0'. Reading stops upon
 * encountering the end-of-line character '\n', for which '\0' is substituted
 * in the string. If the end of file character EOF is reached before the end
 * of the line, the failure condition (-1) is returned. If the line is longer
 * than the maximum length "max_length" of the string, the extra characters
 * are read but ignored. Success is returned (0) on successfully reading
 * a line.
 */
static int read_line ( FILE *fp, char *line, int max_length )
{
   int i;
   char ch;

   /* initialize index to string character */
   i = 0;

   /* read to end of line, filling in characters in string up to its
      maximum length, and ignoring the rest, if any */
   for(;;)
   {
      /* read next character */
      ch = fgetc(fp);

      /* check for end of file error */
      if ( ch == EOF )
     return -1;

      /* check for end of line */
      if ( ch == '\n' )
      {
     /* terminate string and return */
     line[i] = '\0';
     return 0;
      }

      /* fill character in string if it is not already full*/
      if ( i < max_length )
     line[i++] = ch;
   }

   /* the program should never reach here */
   return -1;
}

/* read_string():
 *
 * Reads a line from the input file pointer "fp", starting with the "prefix"
 * string, and filling the string "string" with the remainder of the contents
 * of the line. If the start of the line does not match the "prefix" string,
 * the error condition (-1) is returned. Having read the prefix string,
 * read_string() calls read_line() to read the remainder of the line into
 * "string", up to a maximum length "max_length", and returns the result.
 */
static int read_string ( FILE *fp,
             char *prefix, char *string, int max_length )
{
   int i;

   /* read prefix string */
   for ( i = 0; i < strlen(prefix); i++ )
      if ( fgetc(fp) != prefix[i] )
     /* file input doesn't match prefix */
     return -1;

   /* read remaining part of line of input into string */
   return ( read_line ( fp, string, max_length ) );
}

/* book_details(): */
static void book_details (char title[MAX_TITLE_LENGTH+1] , char author[MAX_AUTHOR_LENGTH+1] , int year  , int bn)
{
   char line[301];

   fprintf(stderr,"Enter Title:\n");
   read_line (stdin, line, 101);
   strcpy(title , line);
   fprintf(stderr,"Entered Title: %s\n",title);

   fprintf(stderr,"Enter Author:\n");
   read_line (stdin, line, 101);
   strcpy(author , line);
   fprintf(stderr,"Entered Author %s\n",author);

   fprintf(stderr,"Enter Year:\n");
   read_line (stdin, line, 4);
   sscanf(line,"%i" , &year);
   fprintf(stderr,"Entered Year: %i\n",year);   

   fprintf (stderr,"Book Number = %i\n",bn);
}

/* compare */
static void compare(struct Book *new , struct Book *book_tree)
{
   if (strcmp (new->title , book_tree->title) > 0 ) 
      { 
         if (book_tree->right == NULL) 
            {
            book_tree->right = new; 
            fprintf(stderr, "\nBook successfully added to tree\n\n"); 
            }
         else 
            {
            book_tree = book_tree->right;
            compare(new , book_tree);
            }
      }
   else
      { 
         if (book_tree->left == NULL) 
            { 
            book_tree->left = new; 
            fprintf(stderr, "\nBook successfully added to tree\n\n"); 

            } 
         else 
            {
            book_tree = book_tree->left;
            compare(new , book_tree);
            }
      }
}

/* place_book(): */
static void place_book (char title[MAX_TITLE_LENGTH+1] , char author[MAX_AUTHOR_LENGTH+1] , int year , int bn)
{
   struct Book *new;
   new = (struct Book *) malloc ( sizeof(struct Book) );

   strcpy ( new->title, title );
   strcpy ( new->author, author );
   new->year = year;
   new->left = new->right = NULL;

   if (bn == 1)   
      {
         if (book_tree == NULL)   
            {   
            book_tree = new; 
            fprintf(stderr, "\nBook successfully added to tree\n\n");   
            }   
         else   
            fprintf(stderr, "\nBook unsuccessfully added to tree\n\n");   
      }

   if (bn >= 2) compare(new , book_tree);    
}

/* menu_add_book(): */
static void menu_add_book (char title[MAX_TITLE_LENGTH+1] , char author[MAX_AUTHOR_LENGTH+1] , int year , int bn)
{
   book_details(title , author , year , bn);
   place_book(title , author , year , bn); 
}

/* descend () */
static void descend (struct Book *print_pointer)
{
   if (print_pointer->left != NULL) 
      descend(print_pointer->left);

   printf ("Title: %s\n" , print_pointer->title);
   printf ("Author: %s\n" , print_pointer->author);
   printf ("Year: %i\n\n" , print_pointer->year); 

   if (print_pointer->right != NULL) 
      descend(print_pointer->right);
}

/* menu_print_database(): */
static void menu_print_database (char title[MAX_TITLE_LENGTH+1] , char author[MAX_AUTHOR_LENGTH+1] , int year , int bn)
{
struct Book *print_pointer = book_tree;
descend(print_pointer);
}

/* codes for menu */
#define ADD_CODE     0
#define DETAILS_CODE 1
#define DELETE_CODE  2
#define PRINT_CODE   3
#define TREE_CODE    4
#define EXIT_CODE    5

int main ( int argc, char *argv[] )
{
   char title[MAX_TITLE_LENGTH+1];   /* name string */
   char author[MAX_AUTHOR_LENGTH+1]; /* job string */
   int year = 0;                     /* year of publication */
   int bn = 0;                       /* book number */

   /* check arguments */
   if ( argc != 1 && argc != 2 )
   {
      fprintf ( stderr, "Usage: %s [<database-file>]\n", argv[0] );
      exit(-1);
   }

   /* read database file if provided, or start with empty database */
   if ( argc == 2 )
      read_book_database ( argv[1] );

   for(;;)
   {
      int choice, result;
      char line[301];

      /* print menu to standard error */
      fprintf ( stderr, "\nOptions:\n" );
      fprintf ( stderr, "%d: Add new book to database\n",      ADD_CODE );
      fprintf ( stderr, "%d: Get details of book\n",       DETAILS_CODE );
      fprintf ( stderr, "%d: Delete book from database\n",  DELETE_CODE );
      fprintf ( stderr, "%d: Print database to screen\n",    PRINT_CODE );
      fprintf ( stderr, "%d: Print tree\n",                   TREE_CODE );
      fprintf ( stderr, "%d: Exit database program\n",        EXIT_CODE );
      fprintf ( stderr, "\nEnter option: " );

      if ( read_line ( stdin, line, 300 ) != 0 ) continue;

      result = sscanf ( line, "%d", &choice );
      if ( result != 1 )
      {
     fprintf ( stderr, "corrupted menu choice\n" );
     continue;
      }

      switch ( choice )
      {
         case ADD_CODE: /* add book to database */
         bn++;
     menu_add_book(title , author , year , bn);
     break;

         case DETAILS_CODE: /* get book details from database */
     menu_get_book_details();
     break;

         case DELETE_CODE: /* delete book from database */
     menu_delete_book();
     break;

         case PRINT_CODE: /* print database contents to screen (standard output) */
         menu_print_database(title , author , year , bn);
     break;

         case TREE_CODE: /* print tree to screen (standard output) */
     menu_print_tree();
     break;

     /* exit */
         case EXIT_CODE:
     break;

         default:
     fprintf ( stderr, "illegal choice %d\n", choice );
     break;
      }

      /* check for exit menu choice */
      if ( choice == EXIT_CODE )
     break;
   }

   return 0;   
}

目前我只对选项0和3的功能感兴趣。

当我运行选项3 menu_print_database时,我的年份总是为零,尽管输入书籍详细信息时它是适当的一年。我相当肯定我在这一年的印刷品上遗漏了一些东西?可能是转换角色还是什么?

干杯!

1 个答案:

答案 0 :(得分:1)

增加是错误的。因此,打印(如果它没有错误)无法做任何事情。

问题在于:

static void book_details(char title[MAX_TITLE_LENGTH + 1],
                         char author[MAX_AUTHOR_LENGTH + 1], int year, int bn) {
  char line[301];

  fprintf(stderr, "Enter Year:\n");
  read_line(stdin, line, 4);
  // I changed %i to %d, which is the one you should use for integers
  sscanf(line, "%d", &year);
  fprintf(stderr, "Entered Year: %d\n", year);

  // and here yes, year has the value that you expect, but because it is passed by value, when the function is terminated, all the changes made to year will be lost
}

static void menu_add_book(char title[MAX_TITLE_LENGTH + 1],
                      char author[MAX_AUTHOR_LENGTH + 1], int year, int bn) {
  // you call book_details here, and you pass year by value!!!!!
  book_details(title, author, year, bn);
  place_book(title, author, year, bn);
}

如果你想刷新按值和引用传递变量,我有一个小例子here

在链接中的OP和我的示例的注释之后,如果您想从main调用两个函数并保留更改,则可能会出现类似的情况:

void bla(int* argumentTwo)
{
  *argumentTwo = 32000;
}


/* Definition of function foo. */
void foo(int argumentOne, int* argumentTwo)
{
    argumentOne = 1500;
    bla(argumentTwo);
}