c언어의 예외 처리 문제를 해결하고 싶습니다.
아래는 코드입니다.
addr.c
#define _CRT_SECURE_NO_WARNINGS
#include "backend-hash.h"
#include <stdio.h>
#include <stdlib.h> // Necessary for exit()
#include <string.h>
#define WELCOME_MESSAGE "Welcome to Address Book!\n"
#define COMMAND_PROMPT "ADDR>"
#define ADD_PROMPT "ADD NAME>>"
#define SEARCH_PROMPT "SEARCH NAME>>"
#define NUMBER_PROMPT "ENTER NUMBER>>>"
#define DELETE_PROMPT "DELETE NAME>>"
#define MAX 100
int prompt_command(char*, char*);
int prompt_name(char*, char*);
int prompt_number(char*, char*);
void add_words();
const int SIZE = 5;
const int ONE = 1;
int main()
{
char command[1];
char name[5];
init();
printf(WELCOME_MESSAGE);
while (1) {
restart:
if (prompt_command(COMMAND_PROMPT, command) != 0)
goto restart;
switch (command[0]) {
case 'A':
case 'a':
add_words(); //a를 누르면 words.dat가 실행이 된다.
add();
//이윽고 입력받은 데이터들을 배치하는 함수가 실행이 된다.
break;
case 'S':
case 's':
if (prompt_name(SEARCH_PROMPT, name) != 0)
goto restart;
break;
case 'D':
case 'd':
if (prompt_name(DELETE_PROMPT, name) != 0)
goto restart;
break;
case 'Q':
case 'q':
printf("Quitting ... \n");
return 0;
// Prints the number of keys in each chain.
case 'P':
case 'p':
print_dist();
break;
default:
printf("Please enter a valid command.\n");
goto restart;
}
}
}
void add_words() //words.dat을 입력받는 함수이다.
{
char* p_word_list[5762] = { 0, }; //단어를 읽어올 공간
char* p[5757][5]; //진짜 최종 저장 공간
int i = 0;
FILE* fp = NULL;
int f = 0;
int k = 0;
fp = fopen("words.dat", "r");
if (fp == NULL) //파일이 비어 있으면 긴급 탈출.
{
fprintf(stderr, "File Open Error!\n");
return;
}
//메모리 확보
for (i = 0; i < 5762; ++i) //5줄의 문자를 읽어옴.
{
p_word_list[i] = (char*)malloc(sizeof(char) * 6); //5글자+널문자
}
for (i = 0; i < 5762; ++i)
{
for (f = 0; f < 5; ++f)
{
fscanf(fp, "%s", &p_word_list[i][f]);
}
//malloc 함수는 실패시 null을 반환합니다.
if (p_word_list[i][0] != '*'&& p_word_list[i][0]!='\0')
{
for (f = 0; f < 5; ++f)
{
wcscpy(p[k][f], p_word_list[i][f]);
}
k++;
}
}
printf("The name was successfully added!\n");
return;
}
int prompt_command(char* s, char* p)
{
char* q;
char c;
while (1) {
printf("%s ", s);
fflush(stdout);
q = p;
while (1) {
c = getchar();
if (c == EOF)
exit(-1); // Should let exit() take care of the sudden EOF.
if (c == '\n')
break;
if (q < p + 1)
*q = c;
q++;
}
if (q == p + 1)
return 0; // got a good command //
if (q == p)
return 1; // just a <return> //
printf("Please type a command.\n");
}
}
int prompt_name(char* s, char* p)
{
char* q;
char c;
while (1) {
printf("%s ", s);
fflush(stdout);
q = p;
while (1) {
c = getchar();
if (c == EOF)
exit(-1); // Should let exit() take care of the sudden EOF.
if (c == '\n')
break;
if (q < p + 3)
*q = c;
q++;
}
if (q == p + 3)
return 0; // got a good name //
if (q == p)
return 1; // just a <return> //
printf("Please type a three-letter name.\n");
}
}
int prompt_number(char* s, char* p)
{
char* q;
char c;
while (1) {
printf("%s ", s);
fflush(stdout);
q = p;
while (1) {
c = getchar();
if (c == EOF)
exit(-1); // Should let exit() take care of the sudden EOF.
if (c == '\n')
break;
if (q < p + 4)
*q = c;
q++;
}
if (q == p + 4)
return 0; // got a good number //
if (q == p)
return 1; // just a <return> //
printf("Please type a four-digit number.\n");
}
return 0;
}
backend-hash.c
/*
Data Structure programming assignment. The same address book program with hashing with chaining.
Will take a hash prime p, not too big, probably 17, for an easy test.
Give a function name_to_num().
Define the hash function hash(name)= name_to_num(name) mod p.
The list of first three hundred primes:
{2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, \
67, 71, 73, 79, 83, 89, 97, 101, 103, 107, 109, 113, 127, 131, 137, \
139, 149, 151, 157, 163, 167, 173, 179, 181, 191, 193, 197, 199, 211, \
223, 227, 229, 233, 239, 241, 251, 257, 263, 269, 271, 277, 281, 283, \
293, 307, 311, 313, 317, 331, 337, 347, 349, 353, 359, 367, 373, 379, \
383, 389, 397, 401, 409, 419, 421, 431, 433, 439, 443, 449, 457, 461, \
463, 467, 479, 487, 491, 499, 503, 509, 521, 523, 541, 547, 557, 563, \
569, 571, 577, 587, 593, 599, 601, 607, 613, 617, 619, 631, 641, 643, \
647, 653, 659, 661, 673, 677, 683, 691, 701, 709, 719, 727, 733, 739, \
743, 751, 757, 761, 769, 773, 787, 797, 809, 811, 821, 823, 827, 829, \
839, 853, 857, 859, 863, 877, 881, 883, 887, 907, 911, 919, 929, 937, \
941, 947, 953, 967, 971, 977, 983, 991, 997, 1009, 1013, 1019, 1021, \
1031, 1033, 1039, 1049, 1051, 1061, 1063, 1069, 1087, 1091, 1093, \
1097, 1103, 1109, 1117, 1123, 1129, 1151, 1153, 1163, 1171, 1181, \
1187, 1193, 1201, 1213, 1217, 1223, 1229, 1231, 1237, 1249, 1259, \
1277, 1279, 1283, 1289, 1291, 1297, 1301, 1303, 1307, 1319, 1321, \
1327, 1361, 1367, 1373, 1381, 1399, 1409, 1423, 1427, 1429, 1433, \
1439, 1447, 1451, 1453, 1459, 1471, 1481, 1483, 1487, 1489, 1493, \
1499, 1511, 1523, 1531, 1543, 1549, 1553, 1559, 1567, 1571, 1579, \
1583, 1597, 1601, 1607, 1609, 1613, 1619, 1621, 1627, 1637, 1657, \
1663, 1667, 1669, 1693, 1697, 1699, 1709, 1721, 1723, 1733, 1741, \
1747, 1753, 1759, 1777, 1783, 1787, 1789, 1801, 1811, 1823, 1831, \
1847, 1861, 1867, 1871, 1873, 1877, 1879, 1889, 1901, 1907, 1913, \
1931, 1933, 1949, 1951, 1973, 1979, 1987}
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "backend-hash.h"
#define HASH_PRIME 7000
#define POOL_SIZE 100
int hh = 0;
int name_to_num(char name[3])
{
int x;
x = name[0];
x = x << 8;
x = x + name[1];
x = x << 8;
return x + name[2];
}
int hash(char key[5]) //이번 과제에서는 hash함수도 바뀐다.
{
int i;
long long x;
x = 0;
for (i = 0; i < 4; i++) {
x = x + key[i];
x = x << 8;
}
x = x + key[4];
return x % HASH_PRIME;
}
// record structure
struct record {
char name[5];
char number[4];
struct record* next;
};
// pool of memory
struct record pool[POOL_SIZE];
struct record* top = pool; // a pointer variable for stack top.
// utility function declarations
void print_name(struct record*);
void print_number(struct record*);
void print_data(char*, int);
// Hash table: an array of hash values.
struct record* hash_table[HASH_PRIME];
// Initially, each pointer of the hash table is valued NULL.
void init_hash_table()
{
int i;
for (i = 0; i < HASH_PRIME; i++)
hash_table[i] = NULL;
}
// Printing all the addresses does not make a good sense in hashing...
// Still use the same memory management.
void init_pool() // Initialize the pool.
{
int i;
struct record* r = pool;
struct record* s;
pool[POOL_SIZE - 1].next = NULL;
for (i = 1; i < POOL_SIZE; i++) {
s = r++;
s->next = r;
}
}
void init()
{
init_pool();
init_hash_table();
}
// Get a node from the pool. Returns NULL if pool is empty. (A BETTER DESIGN)
// When calling new(), make sure to check if it is NULL.
struct record* new_node()
{
struct record* r;
if (top == NULL)
return NULL;
r = top;
top = r->next;
return r;
}
// Push a node to the pool.
void free_node(struct record* r)
{
r->next = top;
top = r;
}
/**************************
IMPORTANT NOTE on add()
1. Allow duplicate names.
2. Put in front of the linked list.
**************************/
void add() //이번 숙제에서의 add는 ()안에 아무 것도 없는 void 형식이다.
{
int i = 0;
for (i = 0; i < 5757; i++) {
hh = hash(*p[i]); //는 0부터 16까지의 값을 받게 된다.
struct record* NewNode = new_node();
NewNode->next = NULL;
struct record* r = hash_table[hh];
if (hash_table[hh] == NULL) //만약 텅 비어있다면
{
hash_table[hh] = NewNode;
}
//텅 비어 있지 않다면
else { //whw3숙제는 각 체인의 순서가 중요하지는 않으므로 그냥 맨 앞에 추가한다.
NewNode->next = r;
hash_table[hh] = NewNode;
}
}
}
/**************************
IMPORTANT NOTE on search()
Because we allow duplicate names, search() finds the most recently-added name.
Prints the number of comparisons.
**************************/
void search(char name[5])
{//이 함수에서는 search도 중요한 기능이 아니기 때문에 기능을 사실상 없앴다.
printf("Couldn't find the name.\n");
}
void print_name(struct record* r)
{
print_data(r->name, 3);
}
void print_number(struct record* r)
{
print_data(r->number, 4);
}
void print_data(char* s, int n)
{
int i;
for (i = 0; i < n; i++)
putchar(s[i]);
}
void print_dist()
{
int i;
for (i = 0; i < HASH_PRIME; i++)
{
int Count = 0;
struct record* r = hash_table[i];
printf("%d :", i);
while (r != NULL) {
Count = Count + 1;
r = r->next;
//whw3에서는 숫자만 count하면 된다.
}
printf(":%d ", Count);
printf("\n");
}
printf("\n");
}
backend-hash,h
void search(char[5]);
void init();
void print_dist();
void add_words();
char* p[5757][5]; //진짜 최종 저장 공간
char* p_word_list[5762]; //단어를 읽어올 공간
void add();
int hash(char[5]);
이 함수를 실행시켜 보았더니
nt hash(char key[5]) //이번 과제에서는 hash함수도 바뀐다.
{
int i;
long long x;
x = 0;
for (i = 0; i < 4; i++) {
x = x + key[i]; (예외가 발생한 부분)
x = x << 8;
}
x = x + key[4];
return x % HASH_PRIME;
}
예외가 throw됨: 읽기 액세스 위반입니다.
key이(가) 0x1110112였습니다.
같은 예외가 발생했습니다.