LINUX.ORG.RU

Решение задачи 5.4 из книги М. Керриска (dup)

 


1

2

При компиляции работающего кода :) Выводятся на экран следующие ошибки (см. по ссылке Ошибки).

Ошибки

hashTable.h

#ifndef HASH_TABLE_H
#define HASH_TABLE_H

struct node;
struct hashMap;
void initializeHashMap(struct hashMap* mp);
void insert(struct hashMap* mp, char* key, char* value);
void delete (struct hashMap* mp, char* key);
char* search(struct hashMap* mp, char* key);
#endif

error_functions.h

#ifndef ERROR_FUNCTIONS_H
#define ERROR_FUNCTIONS_H

void errMsg(const char* format, ...);

#ifdef __GNUC__
/* This macro blocks compiler warnings when using command 'gcc -Wall'
   complaining that 'control reaches end of non-void function',that is
   control reached end of function, which must return a value, if we use 
   the following functions to stop execution of main(), or some other 
   function, which must return a value of some defined type (not void) */
#define NORETURN __attribute__ ((__noreturn__))
#else 
#define NORETURN
#endif

void errExit(const char* format, ...) NORETURN;
void err_exit(const char* format, ...) NORETURN;
void errExitEN(int errnum, const char* format, ...) NORETURN;
void fatal(const char* format, ...) NORETURN;
void usageErr(const char* format, ...) NORETURN;
void cmdLineErr(const char* format, ...) NORETURN;

#endif

dup.c

#include <string.h>
#include <fcntl.h> //O_CREAT
#include <stdlib.h>
#include <stdio.h> // snprintf
#include "error_functions.h"
#include "hashTable.h"

typedef struct FileDescriptor {
	int stateFlg;
	int desc;
} FileDescriptor;

static struct FileDescriptor *descriptors;

void initDescriptorsTable() {
	if (NULL == descriptors)
#define SIZE_OF_DESCRIPTORS_ARRAY 1024
		descriptors = malloc(SIZE_OF_DESCRIPTORS_ARRAY*sizeof(FileDescriptor));
}

void insertFileDescriptor(struct FileDescriptor * pFileDsc) {
  if (pFileDsc == NULL)
	fatal("pFileDsc is NULL");
  int i = 0;
  while (descriptors[i++].desc != -1) {}
  descriptors[--i].desc = pFileDsc->desc;
}

typedef struct OpFileDesc {
        int key;
	int offset;
	int stateFlags;
	int accessMode;
	int ioSigFlags;	
	int indexRef;
} OpFileDesc;

static struct OpFileDesc *openedFiles;

void initOpenedFilesTable() {
	if (NULL == openedFiles)
#define OPENED_FILES_DESC 4096
		openedFiles = malloc(OPENED_FILES_DESC*sizeof(OpFileDesc));
}

void insertOpenFileDescription(struct OpFileDesc * pOpFileDesc) {
	if (pOpFileDesc == NULL)
		fatal("pOpFileDesc is NULL");
	int i = 0;
  	while (openedFiles[i++].key != -1) {}
  	openedFiles[--i].key = pOpFileDesc->key;
}


int
main(int argc, char *argv[])
{
        if (argc != 2 || strcmp(argv[1], "--help") == 0)
		usageErr("%s FD");
        
        initDescriptorsTable();
	initOpenedFilesTable();
	
	int oldfd = atoll(argv[1]);
	int i = 0;
	while (descriptors[i++].desc != -1) {}
	int newfd = i; /* It is expected to point to the same opened file description as oldfd */
	
	FileDescriptor newFileDesc = {0, newfd};
	insertFileDescriptor(&newFileDesc);
	OpFileDesc opFileDesc = {
	  0,
	  O_CREAT|O_APPEND,
	  S_IWUSR|S_IRUSR,
	  0,
	  0
	};
	insertOpenFileDescription(&opFileDesc);
	
	struct hashMap* mp
                = (struct hashMap*)malloc(sizeof(struct hashMap));
        initializeHashMap(mp);
	
#define BUF_SIZE 4096
	char newFileDscBuf[BUF_SIZE];
	snprintf(newFileDscBuf, BUF_SIZE, "%ld", newFileDesc.desc);
	char newOpFileDscBuf[BUF_SIZE];
	snprintf(newOpFileDscBuf, BUF_SIZE, "%ld", opFileDesc.key);
	insert(mp, newFileDscBuf, newOpFileDscBuf);
	
	free(descriptors);
	free(opFiles);
	exit(newfd);
}

hashTable.c

// Linked List node
struct node {

    // key is string
    char* key;

    // value is also string
    char* value;
    struct node* next;
};

// like constructor
void setNode(struct node* node, char* key, char* value)
{
    node->key = key;
    node->value = value;
    node->next = NULL;
    return;
};

struct hashMap {

    // Current number of elements in hashMap
    // and capacity of hashMap
    int numOfElements, capacity;

    // hold base address array of linked list
    struct node** arr;
};

// like constructor
void initializeHashMap(struct hashMap* mp)
{

    // Default capacity in this case
    mp->capacity = 100;
    mp->numOfElements = 0;

    // array of size = 1
    mp->arr = (struct node**)malloc(sizeof(struct node*)
                                    * mp->capacity);
    return;
}

int hashFunction(struct hashMap* mp, char* key)
{
    int bucketIndex;
    int sum = 0, factor = 31;
    for (int i = 0; i < strlen(key); i++) {

        // sum = sum + (ascii value of
        // char * (primeNumber ^ x))...
        // where x = 1, 2, 3....n
        sum = ((sum % mp->capacity)
               + (((int)key[i]) * factor) % mp->capacity)
              % mp->capacity;

        // factor = factor * prime
        // number....(prime
        // number) ^ x
        factor = ((factor % __INT16_MAX__)
                  * (31 % __INT16_MAX__))
                 % __INT16_MAX__;
    }

    bucketIndex = sum;
    return bucketIndex;
}

void insert(struct hashMap* mp, char* key, char* value)
{

    // Getting bucket index for the given
    // key - value pair
    int bucketIndex = hashFunction(mp, key);
    struct node* newNode = (struct node*)malloc(

        // Creating a new node
        sizeof(struct node));

    // Setting value of node
    setNode(newNode, key, value);

    // Bucket index is empty....no collision
    if (mp->arr[bucketIndex] == NULL) {
        mp->arr[bucketIndex] = newNode;
    }

    // Collision
    else {

        // Adding newNode at the head of
        // linked list which is present
        // at bucket index....insertion at
        // head in linked list
        newNode->next = mp->arr[bucketIndex];
        mp->arr[bucketIndex] = newNode;
    }
    return;
}

void delete (struct hashMap* mp, char* key)
{

    // Getting bucket index for the
    // given key
    int bucketIndex = hashFunction(mp, key);

    struct node* prevNode = NULL;

    // Points to the head of
    // linked list present at
    // bucket index
    struct node* currNode = mp->arr[bucketIndex];

    while (currNode != NULL) {

        // Key is matched at delete this
        // node from linked list
        if (strcmp(key, currNode->key) == 0) {

            // Head node
            // deletion
            if (currNode == mp->arr[bucketIndex]) {
                mp->arr[bucketIndex] = currNode->next;
            }

            // Last node or middle node
            else {
                prevNode->next = currNode->next;
            }
            free(currNode);
            break;
        }
        prevNode = currNode;
        currNode = currNode->next;
    }
    return;
}

char* search(struct hashMap* mp, char* key)
{

    // Getting the bucket index
    // for the given key
    int bucketIndex = hashFunction(mp, key);

    // Head of the linked list
    // present at bucket index
    struct node* bucketHead = mp->arr[bucketIndex];
    while (bucketHead != NULL) {

        // Key is found in the hashMap
        if (bucketHead->key == key) {
            return bucketHead->value;
        }
        bucketHead = bucketHead->next;
    }

    // If no key found in the hashMap
    // equal to the given key
    char* errorMssg = (char*)malloc(sizeof(char) * 25);
    errorMssg = "Oops! No data found.\n";
    return errorMssg;
}

error_functions.c

#include <stdarg.h>
#include <stdlib.h>
#include "error_functions.h"
#include "tlpi_hdr.h"
#include "ename.c"    /* Defines ename and MAX_ENAME */

#ifdef __GNUC__
__attribute__ ((__noreturn__))
#endif

static void
terminate(Boolean useExit3)
{
	char *s;

	/* Saves core dump, if environment variable EF_DUMPCORE is defined 
           and contains an unempty string; otherwise it calls exit(3)
	   or _exit(2), depending on value of 'useExit3'. */
        s = getenv("EF_DUMPCORE");
	if (s != NULL && *s != '\0')
		abort();
	else if (useExit3)
		exit(EXIT_FAILURE);
	else
		_exit(EXIT_FAILURE);
}

static void
outputError(Boolean useErr, int err, Boolean flushStdout,
	const char *format, va_list ap)
{
#define BUF_SIZE 500
	char buf[BUF_SIZE], userMsg[BUF_SIZE], errText[BUF_SIZE];
	vsnprintf(userMsg, BUF_SIZE, format, ap);

	if (useErr)
		snprintf(errText, BUF_SIZE, " [%s %s]",
			(err > 0 && err <= MAX_ENAME) ?
			ename[err] : "?UNKNOWN?", strerror(err));
	else
		snprintf(errText, BUF_SIZE, ":");
	snprintf(buf, BUF_SIZE, "ERROR%s %s\n", errText, userMsg);
	if (flushStdout)
		fflush(stdout); /* Reset all pending output */
	fputs(buf, stderr);
	fflush(stderr);
}

void
errMsg(const char *format, ...)
{
	va_list argList;
	int savedErrno;
	savedErrno = errno;
	va_start(argList, format);
	outputError(TRUE, errno, TRUE, format, argList);
	va_end(argList);
	errno = savedErrno;
}

void
errExit(const char *format, ...)
{
	va_list argList;
	va_start(argList, format);
	outputError(TRUE, errno, TRUE, format, argList);
	va_end(argList);
	terminate(TRUE);
}

void
err_exit(const char *format, ...)
{
	va_list argList;
	va_start(argList, format);
	outputError(TRUE, errno, FALSE, format, argList);
	va_end(argList);
	terminate(FALSE);
}

void
errExitEN(int errnum, const char *format, ...)
{
	va_list argList;
	va_start(argList, format);
	outputError(TRUE, errnum, TRUE, format, argList);
	va_end(argList);
	terminate(TRUE);
}

void
fatal(const char *format, ...)
{
	va_list argList;
	va_start(argList, format);
	outputError(TRUE, 0, TRUE, format, argList);
	va_end(argList);
	terminate(TRUE);
}

void
usageErr(const char *format, ...)
{
	va_list argList;
	fflush(stdout);
	fprintf(stderr, "Usage: ");
	va_start(argList, format);
	vfprintf(stderr, format, argList);
	va_end(argList);
	fflush(stderr);
	exit(EXIT_FAILURE);
}

void
cmdLineErr(const char *format, ...)
{
	va_list argList;
	fflush(stdout);
	fprintf(stderr, "Command-line usage error: ");
	va_start(argList, format);
	vfprintf(stderr, format, argList);
	va_end(argList);
	fflush(stderr);
	exit(EXIT_FAILURE);
}

ename.c

/* ename.c.inc

   Built on GNU/Linux x86_64 with glibc 2.42
*/
static char *ename[] = {
    /*   0 */ "",
    /*   1 */ "EPERM", "ENOENT", "ESRCH", "EINTR", "EIO", "ENXIO",
    /*   7 */ "E2BIG", "ENOEXEC", "EBADF", "ECHILD",
    /*  11 */ "EAGAIN/EWOULDBLOCK", "ENOMEM", "EACCES", "EFAULT",
    /*  15 */ "ENOTBLK", "EBUSY", "EEXIST", "EXDEV", "ENODEV",
    /*  20 */ "ENOTDIR", "EISDIR", "EINVAL", "ENFILE", "EMFILE",
    /*  25 */ "ENOTTY", "ETXTBSY", "EFBIG", "ENOSPC", "ESPIPE",
    /*  30 */ "EROFS", "EMLINK", "EPIPE", "EDOM", "ERANGE",
    /*  35 */ "EDEADLK/EDEADLOCK", "ENAMETOOLONG", "ENOLCK", "ENOSYS",
    /*  39 */ "ENOTEMPTY", "ELOOP", "", "ENOMSG", "EIDRM", "ECHRNG",
    /*  45 */ "EL2NSYNC", "EL3HLT", "EL3RST", "ELNRNG", "EUNATCH",
    /*  50 */ "ENOCSI", "EL2HLT", "EBADE", "EBADR", "EXFULL", "ENOANO",
    /*  56 */ "EBADRQC", "EBADSLT", "", "EBFONT", "ENOSTR", "ENODATA",
    /*  62 */ "ETIME", "ENOSR", "ENONET", "ENOPKG", "EREMOTE",
    /*  67 */ "ENOLINK", "EADV", "ESRMNT", "ECOMM", "EPROTO",
    /*  72 */ "EMULTIHOP", "EDOTDOT", "EBADMSG/EFSBADCRC", "EOVERFLOW",
    /*  76 */ "ENOTUNIQ", "EBADFD", "EREMCHG", "ELIBACC", "ELIBBAD",
    /*  81 */ "ELIBSCN", "ELIBMAX", "ELIBEXEC", "EILSEQ", "ERESTART",
    /*  86 */ "ESTRPIPE", "EUSERS", "ENOTSOCK", "EDESTADDRREQ",
    /*  90 */ "EMSGSIZE", "EPROTOTYPE", "ENOPROTOOPT",
    /*  93 */ "EPROTONOSUPPORT", "ESOCKTNOSUPPORT",
    /*  95 */ "EOPNOTSUPP/ENOTSUP", "EPFNOSUPPORT", "EAFNOSUPPORT",
    /*  98 */ "EADDRINUSE", "EADDRNOTAVAIL", "ENETDOWN", "ENETUNREACH",
    /* 102 */ "ENETRESET", "ECONNABORTED", "ECONNRESET", "ENOBUFS",
    /* 106 */ "EISCONN", "ENOTCONN", "ESHUTDOWN", "ETOOMANYREFS",
    /* 110 */ "ETIMEDOUT", "ECONNREFUSED", "EHOSTDOWN", "EHOSTUNREACH",
    /* 114 */ "EALREADY", "EINPROGRESS", "ESTALE",
    /* 117 */ "EUCLEAN/EFSCORRUPTED", "ENOTNAM", "ENAVAIL", "EISNAM",
    /* 121 */ "EREMOTEIO", "EDQUOT", "ENOMEDIUM", "EMEDIUMTYPE",
    /* 125 */ "ECANCELED", "ENOKEY", "EKEYEXPIRED", "EKEYREVOKED",
    /* 129 */ "EKEYREJECTED", "EOWNERDEAD", "ENOTRECOVERABLE",
    /* 132 */ "ERFKILL", "EHWPOISON"
};

#define MAX_ENAME 133


Последнее исправление: brynzacom (всего исправлений: 7)

ооооооо, сегодня ты в несколько раз превзошел себя вчерашнего, тред наверно удалят

IvanRia
()

показал бы лучше команду компиляции, там наверно -Wall -Wextra -Wpedantic -Werror, убрал бы их и не было бы простыни с нечитабельными ворнингами и ошибками, хотя убирать флаги это путь ведущий в никуда, но в данном случае он рекомендован, по поводу тегов, тут используется Markdown это общепринятый стандарт и далеко не только на этом форуме.

IvanRia
()

Откройте для себя вкладку «предпросмотр».

Но вообще, кто-то в прошлый раз посоветовал lorcode и, похоже, [code]он не работает[/code].

Замените везде [code] и [/code] на ```

Jullyfish ★★
()

у тебя в основном implicit-declaration (не подключил нужные хидеры), это у тебя 5-я глава, а ты не научился подключать нужные хидеры, ты с пятой главы начал читать книгу или память затирается за неделю?

IvanRia
()
Ответ на: комментарий от IvanRia

Ага, только при добавлении темы написано:

«Всегда выделяйте вывод терминала и фрагменты исходного кода! Для разметки Markdown (по умолчанию) используйте тройной апостроф ```, для lorcode используйте теги [code] и [/code].»

Jullyfish ★★
()
Ответ на: комментарий от Jullyfish

если он со второй попытки не осилил разметку, то рекомендованный путь это прикрепить скрин, тем более, там красненьким будет выделено, а в markdown не будет и стрелочка «^—–» в markdown все равно поплывет

IvanRia
()
Ответ на: комментарий от brynzacom

то что у тебя NULL undefined это уже кривая установка компилятора, так как этот дефайн в хидерах компилятора находится, ты или установи gcc или удали clang, если ты им пользуешься, sizeof(struct my_struct) вроде и не должно работать, надо как-то так : «sizeof(*(struct *my_struct)NULL);» остальные ошибки это отсутствие хидеров, для sprintf нужен stdio.h, для malloc нужен stdlib.h

IvanRia
()
Ответ на: комментарий от brynzacom

а то что у тебя блокнот, это вообще-то даже не хочется комментировать, под винду учат си++, а не си. Оттого наверно NULL и не признает

IvanRia
()
Последнее исправление: IvanRia (всего исправлений: 1)
Ответ на: комментарий от yars068

Пишу код в Centos Stream в vi. Использую Windows, чтобы общаться с вами (у меня тут русская раскладка установлена).

brynzacom
() автор топика
Ответ на: комментарий от brynzacom

Лайфхак: если поставить сразу после трëх открывающих одиночных кавычек латинскую c, включится подсветка кода :)

yars068 ★★★★★
()
Ответ на: комментарий от brynzacom

Теперь можно и посмотреть наконец.

hashTable.c

Описания структур которые там внутри - видны только внутри этого файла, их надо было в .h пихать. Ты делаешь include ".h" а затем пытаешься использовать struct hashMap, который в этот самом .h не описан - ясное дело будет ругаться. Одиночная строчка «strict hashMap;» без подробностей только сообщает компилятору что такой тип вообще существует - это даёт возможность объявлять указатели на него, но не более, для всего остального нужно описание.

firkax ★★★★★
()
Последнее исправление: firkax (всего исправлений: 2)

Где ты этот код взял? Он в книге приведён в качестве работающего, или там как раз задание его исправить? Или сам писал?

firkax ★★★★★
()
Ответ на: комментарий от firkax

Сам написал (я на C никогда раньше не писал, только учусь), и был уверен, что вся выгода в простоте и правильном именовании типов структур и функций.

brynzacom
() автор топика
Ответ на: комментарий от brynzacom

Что-то это не похоже на самописный код того, кто только начал учиться. Больше похоже на копипаст с применением автоматических средств, так не научишься.

firkax ★★★★★
()
  • Markdown
Пустая строка (два раза Enter) начинает новый абзац. Знак '>' в начале абзаца выделяет абзац курсивом цитирования.
Внимание: прочитайте описание разметки Markdown.
Используйте Ctrl-Enter для размещения комментария