2012-04-24 74 views
1

所以我在C編程類,我認爲自己是一個好的程序員,但我遇到了一些我不太明白如何去思考通過。我正在編寫一個使用多個頭文件的壓縮器,並且有兩個用於創建可執行文件的c文件。我已經正確包含頭文件(我認爲),讓他們在同一個目錄中,並說鏈接器混亂爲頭文件中聲明的函數(C)

#include "myLib.h" 

現在。這是我堅持的部分。在一個文件中,我有一個調用在頭文件中聲明的函數的主要方法。這些函數的源代碼位於前面提到的另一個.c文件中。當我編譯:

gcc -Wall TestCmp.c LZWCmp.o 

哪裏TestCmp.c是包含主文件和LZWCmp.o是其他.c文件的目標文件。 我得到編譯錯誤,告訴我四個聲明的方法中有三個是未定義的引用。爲什麼連接器會接受這些方法中的一種存在,而不是其他三種?

任何幫助,將不勝感激。謝謝!

下面是TestCmp.c

#include <stdio.h> 
#include <assert.h> 
#include <limits.h> 
#include "LZWCmp.h" 
#include "SmartAlloc.h" 
#include "MyLib.h" 

/*function pointer to the CodeSink function in TestCmp, which function simply prints each 4-byte uint sent to it as 8 hex digits. It does so 8 integers per line, with one space between each pair of integers, and no space after the final integer, just an EOL.*/ 
void sink(void *pointer, uint code) { 
    printf("%08X ", code); 
} 

void main() { 
    int numCodes; /*Number of codes that compressor starts with understanding*/ 
    LZWCmp *cmp = malloc(sizeof(struct LZWCmp)); /*allocate memory for compressor state*/ 
    CodeSink ptr = sink; /*set sodesink pointer to sink function*/ 
    uchar letter; /*letter for intake and compression*/ 

    printf("Enter symbol count: "); 
    scanf(" %d", &numCodes); 
    while(letter != '\n') { 
     letter = getchar(); 
    } 

    LZWCmpInit(cmp, numCodes, ptr, NULL); /*Initialize compressor */ 

    while(letter < UCHAR_MAX) { 
     letter = getchar(); 
     LZWCmpEncode(cmp, letter);  /*Send letter to encoder*/ /*FIRST FUNCTION TO NOT WORK*/ 
    } 

    LZWCmpStop(cmp); /*Finish program when finding EOF character*/ 
    LZWCmpDestruct(cmp); /*Free memory space*/ 

} 

的源代碼和myLib.h

#ifndef MYLIB_H 
#define MYLIB_H 

#define BITS_PER_BYTE 8 

typedef unsigned char uchar; 
typedef unsigned long ulong; 
typedef unsigned int uint; 
typedef unsigned short ushort; 

#ifdef LITTLE_ENDIAN 

#define UShortEndianXfer(val) ((val) >> 8 | (val) << 8} 

#else 

#define UShortEndianXfer(val) (val) 

#endif 

#endif 

的源代碼和LZWCmp.h

#ifndef LZW_H 
#define LZW_H 

#include "MyLib.h" 

#define RECYCLE_CODE 4096 // Recycle dictionary rather than add this code 

/* Function pointer to method to call when a code is completed and ready for 
* transmission or whatever. The void * parameter can point to anything, 
* and gives hidden information to the function so that it can know what 
* file, socket, etc. the code is going to. The uint is the next 32 bits 
* worth of compressed output. */ 
typedef void (*CodeSink)(void *, uint code); 

/* One node in a trie representing the current dictionary. Use symbols 
* to traverse the trie until reaching a point where the link for a 
* symbol is null. Use the code for the prior link, and add a new code in 
* this case. Each node has as many links and codes as there are symbols */ 
typedef struct TrieNode { 
    ushort *codes; 
    struct TrieNode **links; 
} TrieNode; 

/* Current state of the LZW compressor. */ 
typedef struct LZWCmp { 
    TrieNode *head; /* Head pointer to first TrieNode */ 
    CodeSink sink; /* Code sink to send bits to */ 
    void *sinkState; /* Unknown object to send to sink for state */ 
    int numSyms;  /* Symbol count, also size of TrieNodes */ 
    int nextCode;  /* Next code to be assigned */ 
    int numBits;  /* Number of bits per code currently */ 
    uint nextInt;  /* Partially-assembled next int of output */ 
    int bitsUsed;  /* Number of valid bits in top portion of nextInt */ 
    TrieNode *curLoc; /* Current position in trie */ 
    short lastSym; /* Most recent symbol encoded */ 
} LZWCmp; 

/* Initialize a LZWCmp given the number of symbols and the CodeSink 
* to which to send completed codes; */ 
void LZWCmpInit(LZWCmp *cmp, int numSyms, CodeSink sink, void *sinkState); 

/* Encode "sym" using LZWCmp. Zero or more calls of the code sink 
* may result */ 
void LZWCmpEncode(LZWCmp *cmp, uchar sym); 

/* Mark end of encoding (send next code value to code sink) */ 
void LZWCmpStop(LZWCmp *cmp); 

/* Free all storage associated with LZWCmp (not the sinkState, though, 
* which is "owned" by the caller */ 
void LZWCmpDestruct(LZWCmp *cmp); 

#endif 

至於源我正在編譯的對象,它是一個包含LZWCmp中給出的四個函數的教授給我們的.o文件。 h文件。如果我們的TestCmp.c文件正常工作,那麼我應該可以毫無問題地訪問LZCmp.o文件中的函數。

+3

這還不足以診斷問題,您是如何編譯'LZWCmp'以及源代碼如何查看的? – 2012-04-24 18:08:51

+0

@DanielFischer我們應該如何編譯一個.h文件來創建一個目標文件? – 2012-04-24 18:35:59

+1

@SangeethSaravanaraj這是另一個'.c'文件。 – 2012-04-24 18:37:52

回答

1

OK ..很少修改你的代碼,我能(鏈接和)編譯代碼。該文件如下:

文件名:TestCmp.c

#include <stdlib.h> 
#include <stdio.h> 
#include <assert.h> 
#include <limits.h> 
#include "LZWCmp.h" 
//#include "SmartAlloc.h" 
#include "MyLib.h" 

/*function pointer to the CodeSink function in TestCmp, which function simply prints each 4-byte uint sent to it as 8 hex digits. It does so 8 integers per line, with one space between each pair of integers, and no space after the final integer, just an EOL.*/ 
void sink(void *pointer, uint code) { 
    printf("%08X ", code); 
} 

int main(void) 
{ 
    int numCodes; /*Number of codes that compressor starts with understanding*/ 
    LZWCmp *cmp = malloc(sizeof(struct LZWCmp)); /*allocate memory for compressor state*/ 
    CodeSink ptr = sink; /*set sodesink pointer to sink function*/ 
    uchar letter; /*letter for intake and compression*/ 

    printf("Enter symbol count: "); 
    scanf(" %d", &numCodes); 
    while(letter != '\n') { 
     letter = getchar(); 
    } 

    LZWCmpInit(cmp, numCodes, ptr, NULL); /*Initialize compressor */ 

    while(letter < UCHAR_MAX) { 
     letter = getchar(); 
     LZWCmpEncode(cmp, letter);  /*Send letter to encoder*/ /*FIRST FUNCTION TO NOT WORK*/ 
    } 

    LZWCmpStop(cmp); /*Finish program when finding EOF character*/ 
    LZWCmpDestruct(cmp); /*Free memory space*/ 

    return 0; 

} 

文件名:MyLib.h

#ifndef MYLIB_H 
#define MYLIB_H 

#define BITS_PER_BYTE 8 

typedef unsigned char uchar; 
typedef unsigned long ulong; 
typedef unsigned int uint; 
typedef unsigned short ushort; 

#ifdef LITTLE_ENDIAN 

#define UShortEndianXfer(val) ((val) >> 8 | (val) << 8} 

#else 

#define UShortEndianXfer(val) (val) 

#endif 

#endif 

文件名:LZWCmp.h

#ifndef LZW_H 
#define LZW_H 
#include <stdio.h> 
#include "MyLib.h" 

#define RECYCLE_CODE 4096 // Recycle dictionary rather than add this code 

/* Function pointer to method to call when a code is completed and ready for 
* transmission or whatever. The void * parameter can point to anything, 
* and gives hidden information to the function so that it can know what 
* file, socket, etc. the code is going to. The uint is the next 32 bits 
* worth of compressed output. */ 
typedef void (*CodeSink)(void *, uint code); 

/* One node in a trie representing the current dictionary. Use symbols 
* to traverse the trie until reaching a point where the link for a 
* symbol is null. Use the code for the prior link, and add a new code in 
* this case. Each node has as many links and codes as there are symbols */ 
typedef struct TrieNode { 
    ushort *codes; 
    struct TrieNode **links; 
} TrieNode; 

/* Current state of the LZW compressor. */ 
typedef struct LZWCmp { 
    TrieNode *head; /* Head pointer to first TrieNode */ 
    CodeSink sink; /* Code sink to send bits to */ 
    void *sinkState; /* Unknown object to send to sink for state */ 
    int numSyms;  /* Symbol count, also size of TrieNodes */ 
    int nextCode;  /* Next code to be assigned */ 
    int numBits;  /* Number of bits per code currently */ 
    uint nextInt;  /* Partially-assembled next int of output */ 
    int bitsUsed;  /* Number of valid bits in top portion of nextInt */ 
    TrieNode *curLoc; /* Current position in trie */ 
    short lastSym; /* Most recent symbol encoded */ 
} LZWCmp; 

/* Initialize a LZWCmp given the number of symbols and the CodeSink 
* to which to send completed codes; */ 
void LZWCmpInit(LZWCmp *cmp, int numSyms, CodeSink sink, void *sinkState); 

/* Encode "sym" using LZWCmp. Zero or more calls of the code sink 
* may result */ 
void LZWCmpEncode(LZWCmp *cmp, uchar sym); 

/* Mark end of encoding (send next code value to code sink) */ 
void LZWCmpStop(LZWCmp *cmp); 

/* Free all storage associated with LZWCmp (not the sinkState, though, 
* which is "owned" by the caller */ 
void LZWCmpDestruct(LZWCmp *cmp); 

#endif 

文件名:LZWCmp.c(這是我介紹了將被傳遞給make命令是什麼 - 見下文)

#include "LZWCmp.h" 

void LZWCmpInit(LZWCmp *cmp, int numSyms, CodeSink sink, void *sinkState) 
{ 
    printf("LZWCmpInit \n"); 
} 

void LZWCmpEncode(LZWCmp *cmp, uchar sym) 
{ 
    printf("LZWCmpEncode \n"); 
} 

void LZWCmpStop(LZWCmp *cmp) 
{ 
    printf("LZWCmpStop \n"); 
} 

void LZWCmpDestruct(LZWCmp *cmp) 
{ 
    printf("LZWCmpDestruct \n");  
} 

make命令:

gcc -Wall TestCmp.c LZWCmp.h MyLib.h LZWCmp.c 

希望這有助於!

+0

您能突出顯示您所做的更改嗎? – woodstok 2012-04-25 05:27:04

+1

@MIkhail我在'TestCmp.c'中爲'LZWCmp.c'添加了一個存根'#include'SmartAlloc.h'',因爲我們沒有這個存根,所以''包括'#include ''''LZWCmp.h' 'printf',而'MyLib.h'沒有改變。在'gcc'命令中,我已經通過了所需的文件。 – 2012-04-25 05:43:24

+0

你能否解釋一下如何修復它?我知道你將.h文件添加到編譯器中,但我並不真正瞭解如何修復我得到的錯誤。是否因爲你明確告訴鏈接器使用這些添加的文件進行編譯? – MustangeSilenna 2012-05-06 19:52:49