2014-05-11 58 views
1

我有這樣的代碼:當我運行選項3 menu_print_database我一年印刷轉換錯誤,新年總是等於零

#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

功能感興趣儘管在輸入書的詳細信息時是一個適當的年份,但它始終爲零。我相當肯定我在這一年的印刷品上錯過了一些東西?也許是轉換角色或什麼的?

乾杯!

+1

對於你以前的問題,這個菜單通常用'stdout'而不是'stderr'打印,並且說過如何解決它。你不想聽。現在,沒有'print_database'。也許'menu_print_database'。此外,由於您只對部分代碼感興趣,請編輯帖子,以便僅保留與其相關的代碼!幫助我們來幫助你。縮進你的代碼也是必須的! – gsamaras

+1

'char ch; ch = fgetc(fp);如果(ch == EOF)' - >>將ch改爲int'int ch;' – wildplasser

+0

我將在一秒內編輯我的代碼,我不得不最初通過遠程登錄進行發佈,其中太慢而無法處理多個副本並粘貼 糾正stderr問題,這不是一個問題,我沒有選擇在這件事上,雖然對於這個特定的打印我不打印到stderr。 – stuart194

回答

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的鏈接中的評論和我的例子,你可以像這樣在你要撥打的兩個主要功能,並保持變化的情況下:我記得我曾告訴

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


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

您的解釋是迄今爲止我讀過的最好的,我正確地說如果main調用一個調用函數的函數,並且我想在該函數中使用year並對main進行更改。我應該做些什麼? 'int main() { int year = 0; menu_add_book(&year); }' 然後定義'和'INT * year'and相同menu_add_book'兩個'book_details'和'place_book',但是當我打電話給他們,我只需要'&'當我打電話'menu_add_book' – stuart194

+0

@ user262751在回答中看到我的編輯 – gsamaras

+0

每次你使用'&'調用一個函數時,你必須在它的定義中添加一個強制類型,然後確保它什麼時候發生。是否參照程序中的相關程度是否存在?我有它的工作我只想更好地理解 – stuart194