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

조회수 527회

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 <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 < 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 <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] = 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 서비스입니다. 로그인해야 답변을 작성하실 수 있습니다.

(ಠ_ಠ)
(ಠ‿ಠ)