Từ 1 tới 4 trên tổng số 4 kết quả

Đề tài: chương trình kiểm tra ISBN

  1. #1
    Ngày gia nhập
    09 2008
    Bài viết
    16

    Mặc định chương trình kiểm tra ISBN

    CS 210 - Program #4

    An ISBN (International Standard Book Number) identifies a unique publication. An ISBN is ten digits. The first nine digits must be decimal digits (0...9). The tenth may a decimal digit or the letter X, according to the checksum, discussed below. Three single dashes may be between any of the characters, but an ISBN must not begin or end with a dash.

    Some example ISBNs:

    0-201-88337-6
    0-13-117334-0
    0821211315 (no dashes ok)
    1-57231-866-X

    The last character of an ISBN number is a checksum. The checksum is the determined by the first 9 digits; it is computed by taking modulo 11 (the remainder after dividing by 11) of the sum of each digit multiplied by its position in the ISBN. The letter X corresponds to a value of 10.

    Here are two ISBNs and the calculations that show how the check sum is determined:

    0-201-88337-6 -> (0*1 + 2*2 + 0*3 + 1*4 + 8*5 + 8*6 + 3*7 + 3*8 + 7*9) mod 11 = 6
    1-57231-866-X -> (1*1 + 5*2 + 7*3 + 2*4 + 3*5 + 1*6 + 8*7 + 6*8 + 6*9) mod 11 = 10 (X)

    For more info, check out:
    www.isbn.org
    www.amazon.com Try a book search by ISBN

    Some invalid ISBNs:

    0-201-8A337-6 (bad digit)
    0-201-88337-63 (too many digits)
    0-201-88-337-6 (too many dashes)
    0-201883376 (not enough dashes)
    0-201-88337-3 (wrong check sum)
    -013-117334-0 (beginning or ending dash)
    157231--866-X (sequential dashes)
    013-1134-0 (too few digits)

    Code:
    // filename isbn.cpp
    
    
    
    // Program 4 - Validate ISBN numbers program
    // Description: This program asks the user whether he wants to validate
    //				ISBN numbers from his own input or from a file of isbn numbers
    
    // Start program
    
    // Header files
    
    #include <iostream>				// In/Out, standard
    #include <fstream>				// File input/output
    #include <cctype>				// Character testing
    #include <string>				// String
    using namespace std;
    
    // Constant declarations
    
    const char NWLN = '\n';			// Defines newline in stream
    
    // Function declarations
    
    void instruction();				// Displays instructions
    void userinput(char&);			// Gets user input
    void fileinput(char&);			// Gets file input
    void test(string);				// Tests ISBN numbers
    void convert(char, int&);		// Converts character numbers to int numbers 
    
    // Start of main
    
    int main()
    {
    	int choice;					// User choice value
    	char check;					// Main loop test flag
    
    	// Start of main loop
    	
    	do {						// while check is equal to m
    		instruction();			// Give user instructions
    		
    		// Get user input
    		
    		cout << "Choice: ";
    		cin >> choice;
    		cout << " " << endl;
    
    		// User choice decision switch statment
    		
    		switch(choice)
    		{
    		case 1:                 // Manual input
    			userinput(check);
    			break;
    		case 2:                 // File input
    			fileinput(check);
    			break;
    		case 3:                 //  All done!
    			cout << "Goodbye" << endl;	// Check flag set to end loop
    			check = 'q';
    			break;
    		default: 
    			cerr << "Invalid choice - " << choice << endl
    				<< "enter again please. " << endl << endl;
    		}
    		
    		// End switch
    		
    	} while (check == 'm');
    	
    	// End main loop
    	
    	system("pause");
    	return 0;
    }
    
    // End main
    
    // Instruction subprogram
    
    void instruction()
    {
    	cout << "***** Isbn Number Validator *****" << endl << endl << endl;
    	
    	cout << "| Enter -1- to validate one or more isbn number by typing them in." << endl
    		 << "| Enter -2- to validate a text file of isbn numbers." << endl
    		 << "| Enter -3- to quit." << endl << endl;
    }
    
    // End subprogram
    
    // User input subprogram: Gets user isbn number
    
    void userinput(char& check)
    {
    	string isbn;				// Isbn number
    	
    	cout << "Enter an isbn: "; 
    
    	// !!! error, if i use the getline function instead of just cin
    	// like getline(cin, isbn) or getline(cin, isbn, '\n'),
    	// it wont take isbn numbers and gives 
    	// me an error in the program and according to the book
    	// it should work, because i wanted to use getline here to get an
    	// isbn number with spaces and it won't let me, so i just used cin. !!!!!
    	cin.ignore(80, '\n');
    	getline(cin, isbn);
    	if (isbn.at(isbn.length() - 1) == '\n')
    	    isbn.erase(isbn.length() - 1, 1);
    	
    	cout << " " << endl;
    	
    	// Test isbn number main loop
    	
    	while (isbn.at(0) != 'M' && isbn.at(0) != 'm')
    	{
    		system("cls");
    		test(isbn);
    		system("cls");
    		cout << "Enter an isbn or 'M' to return to main menu:";
    		getline(cin, isbn);
    		if (isbn.at(isbn.length() - 1) == '\n')
    		    isbn.erase(isbn.length() - 1, 1);
    		cout << " " << endl;
    	}
    	
    	// End loop
    	
    	system("cls");
    	check = 'm';
    }
    
    // End subprogram
    
    // File input subprogram: Gets file with isbn numbers
    
    void fileinput(char& check)
    {
    	string file;				// User's Isbn file
    	string isbn;				// Isbn number
    	int num;					// Number of isbn's in file
    	int linecount;				// Line count flag to compare with sum
    	ifstream ins;				// Define input
    	linecount = 0;
    	num = 0;
    	cout << "Enter filename with isbn numbers: ";
    	cin >> file;
    	
    	// Open file
    	
    	ins.open(file.c_str());
    	
    	// File open error test
    	
    	if  (ins.fail())
    	{
    		cerr << "Error - Can't open file [ " << file << " ] for input" << endl;
    		check = 'm';
    	}
    	
    	// End test
    	
    	// Good open of file
    	
    	else
    	{	
    		
    		ins >> num;
    		ins.ignore(100, NWLN);
    		getline(ins, isbn);
    		
    		// Test isbn number main loop
    		
    		while (!ins.eof() && num != linecount)
    		{	
    			system("cls");
    			linecount++;
    			cout << isbn << endl;
    			test(isbn);
    			system("cls");
    			getline(ins, isbn);
    		}
    		
    		// Close input file
    		
    		ins.close();
    		system("cls");
    	}
    	
    	
    	cout << " " << endl;
    	check = 'm';
    	
    	
    }
    
    // End subprogram
    
    // Test subprogram: Tests isbn number
    
    void test(string isbn)
    {
    	int charcount;					// Count of character digits
    	int dashstart;					// Test variable for dash at beginning or end of number
    	int counter;					// Counts characters in string and used in testing
    	int value;						// Value of isbn formula and final value equals remainder of formula
    	int lettercheck;				// Test count variable for letter in isbn
    	int dashcount;					// Test count variable for dashes in isbn
    	int doubledash;					// Test count variable for double dashes in isbn
    	int spacecount;					// Test count variable for spaces in isbn
    	int digit;						// Int value of character digit
    	int length;						// Isbn length
    	char number;					// Character number
    	char prevchar;					// Record last character variable
    	spacecount = 0;
    	lettercheck = 0;
    	value = 0;
    	counter = 1;
    	dashstart = 0;
    	charcount = 0;
    	dashcount = 0;
    	doubledash = 0;
    	
    	length = isbn.length();
    	
    	// Test isbn for loop
    	
    	for(int i=0; i < length - 1; i++)     // for each character
    	{
    		
    		// Check for dash in beginning or end of number
    		
    		if (isbn.at(0) == '-' || isbn.at(length - 1) == '-')
    		{
    			dashstart = 1;
    			counter++;
    		}
    		
    		// Calculate value if isbn has right amount of numbers
    		
    		if ((isdigit(isbn.at(i))) &&
    			(charcount < 9) &&
    			(lettercheck == 0) && isbn.at(i) != '-' && isbn.at(i) != ' ')
    		{
    			number = isbn.at(i);
    			convert(number, digit);
    			value = value + (digit * (counter));
    			counter++;
    			charcount++;
    		}
    		
    		// If isbn has a dash, adds 1 to dashcount
    		
    		if (isbn.at(i) == '-' && dashstart != 1)
    		{
    			dashcount++;
    
    			// Check for double dash
    			
    			if (prevchar == '-')
    				doubledash++;
    			else
    				;
    		}
    		
    		// Check for letter
    		
    		if (isbn.at(i) != '-' && !isdigit(isbn.at(i)) && isbn.at(i) != ' ' && (isbn.at(length - 1) != 'x' || isbn.at(length - 1) != 'X'))
    		{	
    			lettercheck = 1;
    		}
    		
    		// Check for spaces
    		
    		if (isbn.at(i) == ' ')
    		{
    			spacecount++;
    		}
    		
    		
    		// Set previous character variable to last character tested
    		
    		prevchar = isbn.at(i);
    
    	}       // end for each character
    	
    	// End loop
    	
    	
    	// If there isn't a dash at beginning or end of number convert
    	
    	if(dashstart != 1)
    	{
    		
    		// Calculate remainder of forumla
    		
    		value = value % 11;
    		
    		// reminder value statements
    
    		cout << "ISBN: " << isbn << endl << endl;
    		cout << "calculated checksum == " << value << endl << endl;
    	
    
    		if (length == 13 && lettercheck == 0 && charcount == 9 && dashstart == 0)
    		{
    			charcount += 1;
    			number = isbn.at(12);
    		}
    		else if (length == 10 && lettercheck == 0 && charcount == 9 && dashstart == 0)
    		{
    			charcount += 1;
    			number = isbn.at(9);
    		}
    		else if (dashstart == 1 && charcount == 9 && (i > 9 && i < 12))
    		{
    			number = isbn.at(length -1);
    		}
    		else if (dashstart == 1 && charcount == 9 && i > 12)
    		{
    			number = isbn.at(length -1);
    		}
    		else
    		{
    			cout << "Invalid Isbn - will not calculate checksum, return 1" << endl;
    			number = '1';
    		}
    		// Convert last character digit in isbn to int digit to compare to value
    		
    		convert(number, digit);
    	
    	}
    	// Answer output statements based on data
    	
    	if (charcount < 10)
    		cout << " (Not enough digits)" << endl;
    	if (charcount > 10)
    		cout << " (To many digits)" << endl;
    	if (charcount  <  10 && lettercheck == 1)
    		cout << " (Can't have any character except for 'X' at end unless 10 is the remainder)" << endl;
    	if (dashcount > 4)
    		cout << " (Too many dashes)" << endl;
    	if ((dashcount < 3 && dashcount > 0) && length > 10) 
    		cout << " (Not enough dashes)" << endl;
    	if (value != digit)
    		cout << " (Wrong check sum)" << endl;
    	if (dashstart == 1)
    		cout << " (Beginning or ending dash)" << endl;
    	if (doubledash > 0)
    		cout << " (Sequential dashes)" << endl;
    	if (spacecount > 4)
    		cout << " (Too many spaces)" << endl;
    	if ((spacecount < 3 && spacecount > 0) && length > 10)
    		cout << " (Not enough spaces)" << endl;
    	if ((spacecount == 0 || spacecount == 3) && (dashcount == 3 || dashcount == 0) && (charcount == 10) && (counter == 10) && (digit == value))
    		cout << " (Good number and checksum)" << endl;
    	else
    		;
    	
    	cout << " " << endl;
    	system("pause");
    
    }   // end test function
    
    // End subprogram
    
    // Convert subprogram: Converts character digits to int digits
    
    void convert(char number, int& digit)
    {
    	if (number == 'x' || number == 'X')
    		digit = 10;
    	else
    		digit = int(number) - int('0');
    }
    
    // End subprogram
    
    // End program

    tình hình là chương trình vẫn chưa complie ,mong anh em giúp mình cho nó cha.y dùm, email cho pro Huy Nguyen nhung weekend mớii đươc nhưng mình cần nó gấp lấm

  2. #2
    Ngày gia nhập
    12 2006
    Nơi ở
    US
    Bài viết
    1,917

    - Tui giúp cậu lần này thôi đó, code cậu viết fragile quá, không bao giờ handle quá nhiều tasks trong 1 hàm.
    - Cậu đang học Uni nào vậy ? Bài này trong cuốn Starting Out C++ phải không, tui thấy quen lắm nhưng không chắc vì sách đó tui bán lại mùa trước rùi.
    - Tui làm đơn giản nhất rùi đó, nếu dùng full STL và function object code sẽ more elegant. À con trỏ hàm cũng ok . Trường hợp space thì cậu tự mà thêm vào nhé !
    C++ Code:
    1. // filename isbn.cpp
    2. #include <iostream>             // In/Out, standard
    3. #include <fstream>              // File input/output
    4. #include <cctype>               // Character testing
    5. #include <string>               // String
    6.  
    7. using namespace std;
    8.  
    9. const int MAX_ERRORS          = 9;
    10. const int MAX_DASHES          = 3;
    11. const int MAX_DIGITS          = 10;
    12.  
    13. enum ErrorType
    14. {
    15.     BEGIN_OR_END_BY_DASH,     // 1
    16.     WRONG_END_DIGIT,          // 2
    17.     SEQUENTIAL_DASHES,        // 3
    18.     DASHES_BAD_POSITION,      // 4
    19.     NOT_ENOUGH_DIGITS,        // 5
    20.     TOO_MANY_DIGITS,          // 6
    21.     NOT_ENOUGH_DASHES,        // 7
    22.     TOO_MANY_DASHES,          // 8
    23.     WRONG_CHECK_SUM,          // 9
    24.     OK_BUT_NOT_WELL_FORM,     // 10
    25.     VALID_AND_WELL_FORM       // 11
    26. };
    27.  
    28. enum UserOption
    29. {
    30.     MANUAL_INPUT,
    31.     FILE_INPUT,
    32.     QUIT,
    33.     INVALID_CHOICE
    34. };
    35.  
    36.  
    37. bool       open_input_file( const string& file_name );
    38. UserOption get_user_choice();
    39. void       print_instruction();
    40. string     read_isbn_number( istream& in );
    41. bool       open_input_file( ifstream& inf );
    42. bool       is_begin_end_dash( const string& isbn );
    43. bool       is_last_digit_invalid( const string& isbn );
    44. int        count_dashes( const string& isbn );
    45. int        count_digits( const string& isbn );
    46. bool       is_sequential_dashes( const string& isbn );
    47. bool       is_dashes_at_bad_position( const string& isbn );
    48. int        get_check_sum( const string& isbn );
    49. void       test_isbn( const string& isbn );
    50. void       print_error_type_messages( ErrorType er );
    51. int        convert_single_char_to_int( char number );
    52. bool       continue_or_quit( const char* mess );
    53.  
    54. int main()
    55. {
    56.     int        choice;                  // User choice value
    57.     UserOption usop;
    58.     string     isbn_number;
    59.     ifstream   inf;
    60.     char       retest;
    61.  
    62.     do {
    63.         print_instruction();
    64.         usop = get_user_choice();
    65.  
    66.         cin.ignore( 80, '\n' );
    67.  
    68.         switch( usop )
    69.         {
    70.             case MANUAL_INPUT :
    71.             {
    72.                 cout << "Enter an isbn : ";
    73.                 isbn_number = read_isbn_number( cin );
    74.                 break;
    75.             }
    76.             case FILE_INPUT :
    77.             {
    78.                 if( open_input_file( inf ) )
    79.                     isbn_number = read_isbn_number( inf );
    80.                 else
    81.                     cout << endl;
    82.                 break;
    83.             }
    84.             case QUIT :
    85.             {
    86.                 cout << "\n... About to Exit " << endl;
    87.                 break;
    88.             }
    89.             default :
    90.             {
    91.                 cerr << "\n... Invalid choice " << choice << endl;
    92.                 break;
    93.             }
    94.         }
    95.  
    96.         if( !isbn_number.empty() )
    97.         {
    98.             test_isbn( isbn_number );
    99.         }
    100.  
    101.         cout << "\n Hit the enter key to continue....";
    102.         cin.ignore( 80, '\n' );
    103.  
    104.         if( usop == FILE_INPUT )
    105.             inf.clear();
    106.  
    107.     } while( continue_or_quit( "\n Continue ( Y/n or N/n ) ?" ) );
    108.  
    109.     return 0;
    110. }
    111.  
    112. void print_instruction()
    113. {
    114.     cout << "***** Isbn Number Validator *****" << endl << endl << endl;
    115.     cout << "| Enter -1- to validate one or more isbn number by typing them in." << endl
    116.          << "| Enter -2- to validate a text file of isbn numbers." << endl
    117.          << "| Enter -3- to quit." << endl << endl;
    118. }
    119.  
    120. UserOption get_user_choice()
    121. {
    122.     int        choice;
    123.     UserOption usop;
    124.  
    125.     cout << "Choice: ";
    126.     cin >> choice;
    127.     cout << " " << endl;
    128.  
    129.     switch( choice )
    130.     {
    131.     case 1 :
    132.             usop = MANUAL_INPUT;
    133.             break;
    134.     case 2 :
    135.             usop = FILE_INPUT;
    136.             break;
    137.     case 3 :
    138.             usop = QUIT;
    139.             break;
    140.     default :
    141.             usop = INVALID_CHOICE;
    142.             break;
    143.     }
    144.     return usop;
    145. }
    146.  
    147.  
    148. string read_isbn_number( istream& in )
    149. {
    150.     string isbn_number;
    151.     getline( in, isbn_number );
    152.     return isbn_number;
    153. }
    154.  
    155. bool open_input_file( ifstream& inf )
    156. {
    157.     string   file_name;
    158.     cout << "Enter input file : \n";
    159.     cin >> file_name;
    160.  
    161.     inf.open( file_name.c_str() );
    162.     if ( inf.fail() )
    163.     {
    164.         cerr << "Error - Can't open file [ " << file_name << " ] for input" << endl;
    165.         return false;
    166.     }
    167.     else
    168.     {
    169.         cout << "Success - Open file [ " << file_name << " ] for input. " << endl;
    170.         return true;
    171.     }
    172. }
    173.  
    174. bool is_begin_end_dash( const string& isbn )
    175. {
    176.     if( isbn.at( 0 ) == '-' || isbn.at( isbn.length() - 1 ) == '-' )
    177.         return true;
    178.     return false;
    179. }
    180.  
    181. bool is_last_digit_invalid( const string& isbn )
    182. {
    183.     char last_char = isbn.at( isbn.length() - 1 );
    184.     if( last_char != 'x' && last_char != 'X' && !isdigit( last_char ) )
    185.         return true;
    186.     return false;
    187. }
    188.  
    189. int count_dashes( const string& isbn )
    190. {
    191.     int len    = isbn.length();
    192.     int dashes = 0;
    193.     for( int i = 0; i < len; ++i )
    194.     {
    195.         if( isbn.at( i ) == '-' )
    196.             dashes++;
    197.     }
    198.     return dashes;
    199. }
    200.  
    201. int count_digits( const string& isbn )
    202. {
    203.     int len    = isbn.length();
    204.     int digits = 0;
    205.     for( int i = 0; i < len; ++i )
    206.     {
    207.         if( isdigit( isbn.at( i ) ) )
    208.             digits++;
    209.     }
    210.     return digits;
    211. }
    212.  
    213. bool is_sequential_dashes( const string& isbn )
    214. {
    215.     int len    = isbn.length();
    216.     for( int i = 0; i < len - 1; ++i )
    217.     {
    218.         if( isbn.at( i ) == '-' && isbn.at( i + 1 ) == '-' )
    219.             return true;
    220.     }
    221.     return false;
    222. }
    223.  
    224. bool is_dashes_at_bad_position( const string& isbn )
    225. {
    226.     if(
    227.         isbn.at( 1 )  != '-' ||
    228.         isbn.at( 5 )  != '-' ||
    229.         isbn.at( 11 ) != '-'
    230.     )
    231.         return true;
    232.     return false;
    233. }
    234.  
    235. int get_check_sum( const string& isbn )
    236. {
    237.     int len = isbn.length();
    238.     int sum = 0;
    239.     int cnt = 1;
    240.     for( int i = 0; i < len - 1; ++i )
    241.     {
    242.         if( isdigit( isbn.at( i ) ) )
    243.         {
    244.             sum += cnt * convert_single_char_to_int( isbn.at( i ) );
    245.             cnt++;
    246.         }
    247.     }
    248.     return sum;
    249. }
    250.  
    251.  
    252.  
    253. void test_isbn( const string& isbn )
    254. {
    255.     ErrorType er;
    256.     int       number_digits = count_digits( isbn );
    257.     int       number_dashes = count_dashes( isbn );
    258.  
    259.     if( is_begin_end_dash( isbn ) )
    260.     {
    261.         er = BEGIN_OR_END_BY_DASH;
    262.     }
    263.     else if( is_last_digit_invalid( isbn ) )
    264.     {
    265.         er = WRONG_END_DIGIT;
    266.     }
    267.     else if( is_sequential_dashes( isbn ) )
    268.     {
    269.         er = SEQUENTIAL_DASHES;
    270.     }
    271.     else if( number_digits != MAX_DIGITS )
    272.     {
    273.         if( number_digits < MAX_DIGITS )
    274.             er = NOT_ENOUGH_DIGITS;
    275.         else
    276.             er = TOO_MANY_DIGITS;
    277.     }
    278.     else if( number_dashes == MAX_DASHES || number_dashes == 0 )
    279.     {
    280.         if( number_dashes == MAX_DASHES && is_dashes_at_bad_position( isbn ) )
    281.         {
    282.             er = DASHES_BAD_POSITION;
    283.         }
    284.         else
    285.         {
    286.             int check_sum  = get_check_sum( isbn );
    287.             int last_digit = convert_single_char_to_int( isbn.at( isbn.length() - 1 ) );
    288.  
    289.             if( ( check_sum % ( MAX_DIGITS + 1 ) ) == last_digit )
    290.             {
    291.                 if( number_dashes == 0 )
    292.                     er = OK_BUT_NOT_WELL_FORM;
    293.                 else
    294.                     er = VALID_AND_WELL_FORM;
    295.             }
    296.             else
    297.             {
    298.                 er = WRONG_CHECK_SUM;
    299.             }
    300.         }
    301.     }
    302.     else
    303.     {
    304.         if( number_dashes > MAX_DASHES )
    305.             er = TOO_MANY_DASHES;
    306.         else
    307.             er = NOT_ENOUGH_DASHES;
    308.     }
    309.  
    310.     print_error_type_messages( er );
    311. }
    312.  
    313.  
    314.  
    315. void print_error_type_messages( ErrorType er )
    316. {
    317.     switch( er )
    318.     {
    319.     case WRONG_END_DIGIT :
    320.         cout << " (Can't have any character except for 'X' at end unless 10 is the remainder)" << endl;
    321.         break;
    322.     case NOT_ENOUGH_DIGITS :
    323.         cout << " (Not enough digits)" << endl;
    324.         break;
    325.     case TOO_MANY_DIGITS :
    326.         cout << " (To many digits)" << endl;
    327.         break;
    328.     case NOT_ENOUGH_DASHES :
    329.         cout << " (Not enough dashes)" << endl;
    330.         break;
    331.     case TOO_MANY_DASHES :
    332.         cout << " (Too many dashes)" << endl;
    333.         break;
    334.     case WRONG_CHECK_SUM :
    335.         cout << " (Wrong check sum)" << endl;
    336.         break;
    337.     case BEGIN_OR_END_BY_DASH :
    338.         cout << " (Beginning or ending dash)" << endl;
    339.         break;
    340.     case SEQUENTIAL_DASHES :
    341.         cout << " (Sequential dashes)" << endl;
    342.         break;
    343.     case DASHES_BAD_POSITION :
    344.         cout << " (Dashes at wrong places)" << endl;
    345.         break;
    346.     case OK_BUT_NOT_WELL_FORM :
    347.         cout << " (Good number but not well-formed) " << endl;
    348.         break;
    349.     default :
    350.         cout << " (Good number and well-formed)" << endl;
    351.     }
    352. }
    353.  
    354. int convert_single_char_to_int( char number )
    355. {
    356.     if( number == 'x' || number == 'X' )
    357.         return 10;
    358.     else
    359.         return static_cast< int >( number ) - static_cast< int >( '0' );
    360. }
    361.  
    362. bool continue_or_quit( const char* mess )
    363. {
    364.     cout << mess << "\n";
    365.     string repl;
    366.     while( 1 )
    367.     {
    368.         cin >> repl;
    369.         if( repl.at( 0 ) == 'Y' || repl.at( 0 ) == 'y' )
    370.             return true;
    371.         else if( repl.at( 0 ) == 'N' || repl.at( 0 ) == 'n' )
    372.             return false;
    373.         else
    374.             cout << "\n Invalid answer. Try again !\n";
    375.     }
    376. }

  3. #3
    Ngày gia nhập
    09 2008
    Bài viết
    16

    Code:
    // filename = isbn.cpp
    
    // Prof. Gelotte
    
    // Program 4 - Validate ISBN numbers program
    // Description: This program asks the user whether he wants to validate
    //				ISBN numbers from his own input or from a file of isbn numbers
    
    // Start program
    
    // Header files
    
    #include <iostream>				// In/Out, standard
    #include <fstream>				// File input/output
    #include <cctype>				// Character testing
    #include <string>				// String
    using namespace std;
    
    // Constant declarations
    
    const char NWLN = '\n';			// Defines newline in stream
    
    // Function declarations
    
    void instruction();				// Displays instructions
    void userinput(char&);			// Gets user input
    void fileinput(char&);			// Gets file input
    void test(string);				// Tests ISBN numbers
    void convert(char, int&);		// Converts character numbers to int numbers 
    
    // Start of main
    
    int main()
    {
    	char choice;					// User choice value
    	char check = 'm';					// Main loop test flag
    
    	// Start of main loop
    	
    	do {						// while check is equal to m
    		instruction();			// Give user instructions
    		
    		// Get user input
    		
    		cout << "Choice: ";
    		cin >> choice;
    		cout << " " << endl;
    
    		// User choice decision switch statment
    		
    		switch(choice)
    		{
    		case '1':                 // Manual input
    			userinput(check);
    			break;
    		case '2':                 // File input
    			fileinput(check);
    			break;
    		case '3':                 //  All done!
    			cout << "Goodbye" << endl;	// Check flag set to end loop
    			check = 'q';
    			break;
    		default:
    			cerr << "Invalid choice - " << choice << endl
    				<< "enter again please. " << endl << endl;
    		}
    
    		// End switch
    
    	} while (check == 'm');
    	
    	// End main loop
    	
    	system("pause");
    	return 0;
    }
    
    // End main
    
    // Instruction subprogram
    
    void instruction()
    {
    	cout << "***** Isbn Number Validator *****" << endl << endl << endl;
    	
    	cout << "| Enter -1- to validate one or more isbn number by typing them in." << endl
    		 << "| Enter -2- to validate a text file of isbn numbers." << endl
    		 << "| Enter -3- to quit." << endl << endl;
    }
    
    // End subprogram
    
    // User input subprogram: Gets user isbn number
    
    void userinput(char& check)
    {
    	string isbn;				// Isbn number
    	
    	cout << "Enter an isbn: "; 
    
    	// !!! error, if i use the getline function instead of just cin
    	// like getline(cin, isbn) or getline(cin, isbn, '\n'),
    	// it wont take isbn numbers and gives 
    	// me an error in the program and according to the book
    	// it should work, because i wanted to use getline here to get an
    	// isbn number with spaces and it won't let me, so i just used cin. !!!!!
    	cin.ignore(80, '\n');
    	getline(cin, isbn);
    	if (isbn.at(isbn.length() - 1) == '\n')
    	    isbn.erase(isbn.length() - 1, 1);
    	
    	cout << " " << endl;
    	
    	// Test isbn number main loop
    	
    	while (isbn.at(0) != 'M' && isbn.at(0) != 'm')
    	{
    		system("cls");
    		test(isbn);
    		system("cls");
    		cout << "Enter an isbn or 'M' to return to main menu:";
    		getline(cin, isbn);
    		if (isbn.at(isbn.length() - 1) == '\n')
    		    isbn.erase(isbn.length() - 1, 1);
    		cout << " " << endl;
    	}
    	
    	// End loop
    	
    	system("cls");
    	check = 'm';
    }
    
    // End subprogram
    
    // File input subprogram: Gets file with isbn numbers
    
    void fileinput(char& check)
    {
    	string file;				// User's Isbn file
    	string isbn;				// Isbn number
    	int num;					// Number of isbn's in file
    	int linecount;				// Line count flag to compare with sum
    	ifstream ins;				// Define input
    	linecount = 0;
    	num = 0;
    	cout << "Enter filename with isbn numbers: ";
    	cin >> file;
    	
    	// Open file
    	
    	ins.open(file.c_str());
    	
    	// File open error test
    	
    	if  (ins.fail())
    	{
    		cerr << "Error - Can't open file [ " << file << " ] for input" << endl;
    		check = 'm';
    	}
    	
    	// End test
    	
    	// Good open of file
    	
    	else    // else WHAT>?@#$(*&@#$()*#$&()*!!!
    	{	
    		
    		ins >> num;
    		ins.ignore(100, NWLN);
    		getline(ins, isbn);
    		
    		// Test isbn number main loop
    		
    		while (!ins.eof() && num != linecount)
    		{	
    			system("cls");
    			linecount++;
    			cout << isbn << endl;
    			test(isbn);
    			system("cls");
    			getline(ins, isbn);
    		}
    		
    		// Close input file
    		
    		ins.close();
    		system("cls");
    	}   // end WHAT?!@#*&^#$@(*&$#^(&*!!
    	
    	
    	cout << " " << endl;
    	check = 'm';
    	
    	
    }    // end what?
    
    // End subprogram
    
    // Test subprogram: Tests isbn number
    
    void test(string isbn)
    {
    	int charcount;					// Count of character digits
    	int dashstart;					// Test variable for dash at beginning or end of number
    	int counter;					// Counts characters in string and used in testing
    	int value;						// Value of isbn formula and final value equals remainder of formula
    	int lettercheck;				// Test count variable for letter in isbn
    	int dashcount;					// Test count variable for dashes in isbn
    	int doubledash;					// Test count variable for double dashes in isbn
    	int spacecount;					// Test count variable for spaces in isbn
    	int digit;						// Int value of character digit
    	int length;						// Isbn length
    	char number;					// Character number
    	char prevchar;					// Record last character variable
    	spacecount = 0;
    	lettercheck = 0;
    	value = 0;
    	counter = 1;
    	dashstart = 0;
    	charcount = 0;
    	dashcount = 0;
    	doubledash = 0;
    	
    	length = isbn.length();
    	
    	// Test isbn for loop
    	
    	for(int i=0; i < length - 1; i++)     // for each character
    	{
    		
    		// Check for dash in beginning or end of number
    		
    		if (isbn.at(0) == '-' || isbn.at(length - 1) == '-')
    		{
    			dashstart = 1;
    			counter++;
    		}
    		
    		// Calculate value if isbn has right amount of numbers
    		
    		if ((isdigit(isbn.at(i))) &&
    			(charcount < 9) &&
    			(lettercheck == 0) && isbn.at(i) != '-' && isbn.at(i) != ' ')
    		{
    			number = isbn.at(i);
    			convert(number, digit);
    			value = value + (digit * (counter));
    			counter++;
    			charcount++;
    		}
    		
    		// If isbn has a dash, adds 1 to dashcount
    		
    		if (isbn.at(i) == '-' && dashstart != 1)
    		{
    			dashcount++;
    
    			// Check for double dash
    			
    			if (prevchar == '-')
    				doubledash++;
    			else
    				;
    		}
    		
    		// Check for letter
    		
    		if (isbn.at(i) != '-' && !isdigit(isbn.at(i)) && isbn.at(i) != ' ' && (isbn.at(length - 1) != 'x' || isbn.at(length - 1) != 'X'))
    		{	
    			lettercheck = 1;
    		}
    		
    		// Check for spaces
    		
    		if (isbn.at(i) == ' ')
    		{
    			spacecount++;
    		}
    		
    		
    		// Set previous character variable to last character tested
    		
    		prevchar = isbn.at(i);
    
    	}       // end for each character
    	
    	// End loop
    	
    	
    	// If there isn't a dash at beginning or end of number convert
    	int i;
    	if(dashstart != 1)
    	{
    		
    		// Calculate remainder of forumla
    		
    		value = value % 11;
    		
    		// reminder value statements
    
    		cout << "ISBN: " << isbn << endl << endl;
    		cout << "calculated checksum == " << value << endl << endl;
    	
    
    		if (length == 13 && lettercheck == 0 && charcount == 9 && dashstart == 0)
    		{
    			charcount += 1;
    			number = isbn.at(12);
    		}
    		else if (length == 10 && lettercheck == 0 && charcount == 9 && dashstart == 0)
    		{
    			charcount += 1;
    			number = isbn.at(9);
    		}
    		else if (dashstart == 1 && charcount == 9 && (i > 9 && i < 12))
    		{
    			number = isbn.at(length -1);
    		}
    		else if (dashstart == 1 && charcount == 9 && i > 12)
    		{
    			number = isbn.at(length -1);
    		}
    		else
    		{
    			cout << "Invalid Isbn - will not calculate checksum, return 1" << endl;
    			number = '1';
    		}
    		// Convert last character digit in isbn to int digit to compare to value
    		
    		convert(number, digit);
    	
    	}
    	// Answer output statements based on data
    	
    	if (charcount < 10)
    		cout << " (Not enough digits)" << endl;
    	if (charcount > 10)
    		cout << " (To many digits)" << endl;
    	if (charcount  <  10 && lettercheck == 1)
    		cout << " (Can't have any character except for 'X' at end unless 10 is the remainder)" << endl;
    	if (dashcount > 4)
    		cout << " (Too many dashes)" << endl;
    	if ((dashcount < 3 && dashcount > 0) && length > 10) 
    		cout << " (Not enough dashes)" << endl;
    	if (value != digit)
    		cout << " (Wrong check sum)" << endl;
    	if (dashstart == 1)
    		cout << " (Beginning or ending dash)" << endl;
    	if (doubledash > 0)
    		cout << " (Sequential dashes)" << endl;
    	if (spacecount > 4)
    		cout << " (Too many spaces)" << endl;
    	if ((spacecount < 3 && spacecount > 0) && length > 10)
    		cout << " (Not enough spaces)" << endl;
    	if ((spacecount == 0 || spacecount == 3) && (dashcount == 3 || dashcount == 0) && (charcount == 10) && (counter == 10) && (digit == value))
    		cout << " (Good number and checksum)" << endl;
    	else
    		;
    	
    	cout << " " << endl;
    	system("pause");
    
    }   // end test function
    
    // End subprogram
    
    // Convert subprogram: Converts character digits to int digits
    
    void convert(char number, int& digit)
    {
    	if (number == 'x' || number == 'X')
    		digit = 10;
    	else
    		digit = int(number) - int('0');
    }
    
    // End subprogram
    
    // End program
    thanks pro morock nhiều lắm, mình tự làm được rồi nè, pro có góp ý gì thêm cho mình hông, mình mới học programming được 5 tuần thôi, mình đang ở Us, người ta bắt đọc nhiều lắm, nhớ không hết luôn, diễn đàn này thiệ bổ ích

  4. #4
    Ngày gia nhập
    12 2006
    Nơi ở
    US
    Bài viết
    1,917

    - Tui nhìn code thì biết chắc cậu không học ở VN ! Mà cậu học ở trường nào thế ? Biết đâu chung trường của nên !
    - Học 5 tuần mà viết thế là tốt lắm rồi đây !
    - Còn bài cậu thì có nhiều chỗ để bàn :
    1. Enum dùng sẽ sáng nghĩ hơn.
    2. Hai cái hàm fileinput & userinput có nhiều điểm giống( có thể dùng istream& cho ifstream và cin ). Nhưng code cậu implement khác nhau, dư nhiều code không cần thiết.
    3. Cậu nên nhớ là không bao giờ cho input và output vào các function khác.
    Ví dụ đoạn :
    C++ Code:
    1. if (charcount < 10)
    2.         cout << " (Not enough digits)" << endl;
    3.     if (charcount > 10)
    4.         cout << " (To many digits)" << endl;
    5.     if (charcount  <  10 && lettercheck == 1)
    6.         cout << " (Can't have any character except for 'X' at end unless 10 is the remainder)" << endl;
    7.     if (dashcount > 4)
    8.         cout << " (Too many dashes)" << endl;
    9.     if ((dashcount < 3 && dashcount > 0) && length > 10)
    10.         cout << " (Not enough dashes)" << endl;
    11.     if (value != digit)
    12.         cout << " (Wrong check sum)" << endl;
    13.     if (dashstart == 1)
    14.         cout << " (Beginning or ending dash)" << endl;
    15.     if (doubledash > 0)
    16.         cout << " (Sequential dashes)" << endl;
    17.     if (spacecount > 4)
    18.         cout << " (Too many spaces)" << endl;
    19.     if ((spacecount < 3 && spacecount > 0) && length > 10)
    20.         cout << " (Not enough spaces)" << endl;
    21.     if ((spacecount == 0 || spacecount == 3) && (dashcount == 3 || dashcount == 0) && (charcount == 10) && (counter == 10) && (digit == value))
    22.         cout << " (Good number and checksum)" << endl;
    23.     else
    24.         ;
    Giả nếu tui cần chuyển sang tiếng Việt thì cậu nghĩ có bao nhiêu hàm cậu cần phải sữa lại ?
    3. Hàm test( string& ) phải là test( const string& ) vì cậu chỉ test chứ không modify string.
    4. Test 1 chức năng 1 hàm thì sẽ dễ hơn RẤT RẤT nhiều vì sao ? Vì khi cậu muốn thêm hay bớt cậu không test toàn bộ. Hàm test là quá dài, 1 cái sai thì cá đảm kia chạy bằng niềm tin. Thà cậu paid-off cho function hơn là cậu gom 1 đống vào.
    ->
    5. Khi tui học lớp này, cô tui chấm rất kĩ : chú ý thêm các chỗ thiếu const, và gom những cái chung để ra ngoài. Không để magic number nhiều quá, dùng const int để khai báo nó với 1 cái tên có ý nghĩa hơn. Hàm cách 2 blank line. Main đặt trên đầu, nhớ ghi tên đầy đủ và giới thiệt sơ chương trình trong phần output.
    6. Lần sau không post vào box project( đây là nơi chia sẽ mã nguồn ), không phải nơi hỏi ! Dù cậu xài Visual C++ ở trường nhưng cái này là C++ not Visual C++, chú ý post đúng box.
    ps : có mod nào move dùm vào box C++ được không ?

Các đề tài tương tự

  1. Trả lời: 0
    Bài viết cuối: 01-11-2013, 04:43 PM
  2. Bài tập C Input and check ISBN number với lập trình C
    Gửi bởi yeumjnhem01 trong diễn đàn Thắc mắc lập trình C/C++/C++0x
    Trả lời: 6
    Bài viết cuối: 24-03-2013, 11:20 AM
  3. Viết chương trình kiểm tra ISBN
    Gửi bởi seit trong diễn đàn Nhập môn lập trình C/C++
    Trả lời: 27
    Bài viết cuối: 25-10-2010, 10:38 AM

Quyền hạn của bạn

  • Bạn không thể gửi đề tài mới
  • Bạn không thể gửi bài trả lời
  • Bạn không thể gửi các đính kèm
  • Bạn không thể chỉnh sửa bài viết của bạn