[c언어]리눅스에서 dat파일의 단어들을 입력받는 함수를 만드는데 strdup함수에서 오류가 납니다.

조회수 453회

words.dat파일의 문자열들을 입력받아 이를 통해 과제를 수행하고 있습니다.

참고로 words.dat의 내용은 다음과 같습니다.(첫글자가 '*' 인 것을 제외하고 나머지 문자열들은 앞의 5글자씩 문자를 받는 형태입니다. )

  • File "words.dat" from the Stanford GraphBase (C) 1993 Stanford University
  • A database of English five-letter words
  • This file may be freely copied but please do not change it in any way!
  • (Checksum parameters 5757,526296596) aargh abaca 2

zonks zooey zooks zooms*3,1 zowie 4

  • End of file "words.dat"

다음은 코드입니다. 코드는 addr.c의 add_words와 backend-hash.c의 add만 중심으로 보시면 됩니다.

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

include

include

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 < 5762; 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");

}

addr.c

define _CRT_SECURE_NO_WARNINGS

include "backend-hash.h"

include

include // Necessary for exit()

include

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] = malloc(sizeof(char) * 6); //5글자+널문자
}
for (i = 0; i < 5762; ++i)
{
    fscanf(fp, "%s", p_word_list[i]);
    if (p_word_list[i][0] != '*')
    {
        for (f = 0; f < 5; ++f)
        {
            p[k][f]= strdup(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.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]);

이렇게 코드를 짜고 리눅스를 통해 addr>에서 a를 누르면

addr.c: In function ‘add_words’: addr.c:102:17: warning: passing argument 1 of ‘strdup’ makes pointer from integer without a cast [enabled by default] p[k][f]= strdup(p_word_list[i][f]); ^ In file included from addr.c:5:0: /usr/include/string.h:172:14: note: expected ‘const char *’ but argument is of type ‘char’ extern char *strdup (const char *__s)

와 같은 오류가 뜨는데 이런 오류가 뜨는 이유를 잘 모르겠어서 질문드립니다.

감사합니다.

  • (•́ ✖ •̀)
    알 수 없는 사용자

답변을 하려면 로그인이 필요합니다.

프로그래머스 커뮤니티는 개발자들을 위한 Q&A 서비스입니다. 로그인해야 답변을 작성하실 수 있습니다.

(ಠ_ಠ)
(ಠ‿ಠ)