2016-12-07 33 views
2

如何從通過指針數組訪問的字符串中讀取每個單獨的字符?在下面的代碼中,我目前已經在我的makeCodes函數中生成了一個名爲symCodes的字符串指針數組。我想一次讀取8個字符的字符串,我想將每個字符串連接在一起,然後通過char循環該char,但symCodes中的字符串最多可以有255個字符,所以我覺得這可能太多了全部一次處理。相反,我認爲我可以從字符串中逐個字符地讀取每個字符。從指針數組中讀取字符串

我試過scanf或只是循環播放,總是以seg故障結束。在headerEncode()的末尾,它接近底部。我爲每個單獨的字符串malloc足夠的內存,我嘗試循環指針數組並打印出每個單獨的字符,但最後是seg故障。

任何有關讀取指向字符串的指針數組的其他方法的建議,最多可以輸入n字符數。

編輯1:我更新了程序,在使用-Wall和-W標誌時不再輸出警告。我不再遇到seg錯誤(耶!),但我仍然不確定如何去解決我的問題,我怎樣才能讀取字符串指針數組,最多n個字符?

#include <stdio.h> 
#include <stdlib.h> 
#include <string.h> 
#include "huffman.h" 

#define FAIL 0 
#define SUCCESS 1 

/* global 1 day arrays that hold chars and their freqs from file */ 

unsigned long globalFreqs[256] = {0}; 
unsigned char globalUsedCh[256] = {0}; 
char globalCodes[256] = {0}; 
unsigned char globalUniqueSymbols; 
unsigned long totalCount = 0; 

typedef struct HuffmanTreeNode* HTNode; 



struct HuffmanTreeNode* globalSortedLL; 
/* 
    struct has the input letter, the letters frequency, and the left and irght childs 
*/ 
struct HuffmanTreeNode 
{ 
    char symbol; 
    unsigned long freq; 
    char *code; 
    struct HuffmanTreeNode *left, *right; 
    struct HuffmanTreeNode* next; 
}; 

/* does it make sense to have a struct for the entire huffman tree to see its size? */ 
struct HuffmanTree 
{ 
    unsigned size; 
}; 

/*generate new node with given symbol and freq */ 
struct HuffmanTreeNode* newNode(char symbol, int freq) 
{ 
    struct HuffmanTreeNode* newNode = malloc(sizeof(struct HuffmanTreeNode)); 
    newNode->symbol = symbol; 
    newNode->freq = freq; 
    newNode->left = newNode->right = NULL; 
    return newNode; 
} 

/*current work in progress, i believe this is the way to insert it for a BST 
/* will change for HuffmanTreenode once working 
/* 
*/ 

struct HuffmanTreeNode* insert(struct HuffmanTreeNode* node, struct HuffmanTreeNode* htnNew) 
{ 

    struct HuffmanTreeNode* currentNode = node; 

    if(currentNode == NULL || compareTwoNodes(htnNew, currentNode)) 
    { 
    htnNew->next = currentNode; 
    return htnNew; 
    } 
    else 
    { 
    while(currentNode->next != NULL && compareTwoNodes(currentNode->next, htnNew)) 
    { 
     currentNode = currentNode->next; 
    } 
    htnNew->next = currentNode->next; 
    currentNode->next = htnNew; 
    return node; 
    } 
} 

int compareTwoNodes(struct HuffmanTreeNode* a, struct HuffmanTreeNode* b) 
{ 
    if(b->freq < a->freq) 
    { 
    return 0; 
    } 
    if(a->freq == b->freq) 
    { 
    if(a->symbol > b->symbol) 
     return 1; 
    return 0; 
    } 
    if(b->freq > a->freq) 
    return 1; 
} 

struct HuffmanTreeNode* popNode(struct HuffmanTreeNode** head) 
{ 
    struct HuffmanTreeNode* node = *head; 
    *head = (*head)->next; 
    return node; 
} 

/*convert output to bytes from bits*/ 
/*use binary fileio to output */ 
/*put c for individual character byte*/ 
/*fwrite each individual byte for frequency of symbol(look at fileio slides) */ 

/* 
    @function: 
    @param: 
    @return: 
*/ 
int listLength(struct HuffmanTreeNode* node) 
{ 
    struct HuffmanTreeNode* current = node; 
    int length = 0; 
    while(current != NULL) 
    { 
    length++; 
    current = current->next; 
    } 
    return length; 
} 

/* 
    @function: 
    @param: 
    @return: 
*/ 
void printList(struct HuffmanTreeNode* node) 
{ 
    struct HuffmanTreeNode* currentNode = node; 

    while(currentNode != NULL) 
    { 
    if(currentNode->symbol <= ' ' || currentNode->symbol > '~') 
     printf("=%d", currentNode->symbol); 
    else 
     printf("%c", currentNode->symbol); 
    printf("%lu ", currentNode->freq); 
    currentNode = currentNode->next; 
    } 
    printf("\n"); 
} 

/* 
    @function: 
    @param: 
    @return: 
*/ 
void buildSortedList() 
{ 
    int i; 
    for(i = 0; i < 256; i++) 
    { 
    if(!globalFreqs[i] == 0) 
    { 
     globalSortedLL = insert(globalSortedLL, newNode(i, globalFreqs[i])); 
    } 
    } 

    printf("Sorted freqs: "); 
    printList(globalSortedLL); 
    printf("listL: %d\n", listLength(globalSortedLL)); 
} 
/* 
    @function: isLeaf() 
    will test to see if the current node is a leaf or not 
    @param: 
    @return 
*/ 

int isLeaf(struct HuffmanTreeNode* node) 
{ 
    if((node->left == NULL) && (node->right == NULL)) 
    return SUCCESS; 
    else 
    return FAIL; 
} 

/*where I plan to build the actual huffmantree */ 
/* 
    @function: 
    @param: 
    @return: 
*/ 
struct HuffmanTreeNode* buildHuffmanTree(struct HuffmanTreeNode* node) 
{ 
    int top = 0; 
    struct HuffmanTreeNode *left, *right, *topNode, *huffmanTree; 
    struct HuffmanTreeNode* head = node; 
    struct HuffmanTreeNode *newChildNode, *firstNode, *secondNode; 

    while(head->next != NULL) 
    { 
    /*grab first two items from linkedL, and remove two items*/ 
    firstNode = popNode(&head); 
    secondNode = popNode(&head); 
    /*combine sums, use higher symbol, create new node*/ 
    newChildNode = newNode(secondNode->symbol, (firstNode->freq + secondNode->freq)); 
    newChildNode->left = firstNode; 
    newChildNode->right = secondNode; 
    /*insert new node, decrement total symbols in use */ 
    head = insert(head, newChildNode); 
    } 

    return head; 
} 

void printTable(char *codesArray[]) 
{ 
    int i; 
    printf("Symbol\tFreq\tCode\n"); 
    for(i = 0; i < 256; i++) 
    { 
    if(globalFreqs[i] != 0) 
    { 
     if(i <= ' ' || i > '~') 
     { 
     printf("=%d\t%lu\t%s\n", i, globalFreqs[i], codesArray[i]); 
     } 
     else 
     { 
     printf("%c\t%lu\t%s\n", i, globalFreqs[i], codesArray[i]); 
     } 
    } 
    } 
    printf("Total chars = %lu\n", totalCount); 
} 

void makeCodes(
    struct HuffmanTreeNode *node,  /* Pointer to some tree node */ 
    char *code,   /* The *current* code in progress */ 
    char *symCodes[256], /* The array to hold the codes for all the symbols */ 
    int depth)   /* How deep in the tree we are (code length) */ 
{ 
    char *copiedCode; 
    int i = 0; 

    if(isLeaf(node)) 
    { 
     code[depth] = '\0'; 
     symCodes[node->symbol] = code; 
     return; 
    } 

    copiedCode = malloc(255*sizeof(char)); 
    memcpy(copiedCode, code, 255*sizeof(char)); 

    code[depth] = '0'; 
    copiedCode[depth] = '1'; 
    makeCodes(node->left, code, symCodes, depth+1); 
    makeCodes(node->right, copiedCode, symCodes, depth+1); 
} 

/* 
    @function: getFileFreq() 
    gets the frequencies of each character in the given 
    file from the command line, this function will also 
    create two global 1d arrays, one for the currently 
    used characters in the file, and then one with those 
    characters frequencies, the two arrays will line up 
    parallel 
    @param: FILE* in, FILE* out, 
    the current file being processed 
    @return: void 
*/ 
void getFileFreq(FILE* in, FILE* out) 
{ 
    unsigned long freqs[256] = {0}; 
    int i, t, fileCh; 

    while((fileCh = fgetc(in)) != EOF) 
    { 
     freqs[fileCh]++; 
     totalCount++; 
    } 
    for(i = 0; i < 256; i++) 
    { 
     if(freqs[i] != 0) 
     { 
      globalUsedCh[i] = i; 
      globalFreqs[i] = freqs[i]; 
      if(i <= ' ' || i > '~') 
      { 
       globalUniqueSymbols++; 
      } 
      else 
      { 
       globalUniqueSymbols++; 
      } 
     } 
    } 
    /* below code until total count is for debugging purposes */ 
    printf("Used Ch: "); 
    for(t = 0; t < 256; t++) 
    { 
    if(globalUsedCh[t] != 0) 
      { 
     if(t <= ' ' || t > '~') 
     { 
      printf("%d ", globalUsedCh[t]); 
     } 
     else 
      printf("%c ", globalUsedCh[t]); 
     } 
    } 
    printf("\n"); 
    printf("Freq Ch: "); 
    for(t = 0; t < 256; t++) 
    { 
     if(globalFreqs[t] != 0) 
     { 
      printf("%lu ", globalFreqs[t]); 
     } 
    } 
    printf("\n"); 
    /* end of code for debugging/vizualazation of arrays*/ 
    printf("Total Count %lu\n", totalCount); 
    printf("globalArrayLength: %d\n", globalUniqueSymbols); 
} 


void headerEncode(FILE* in, FILE* out, char *symCodes[256]) 
{ 
    char c; 
    int i, ch, t, q, b, z; 
    char *a; 
    char *fileIn; 
    unsigned char *uniqueSymbols; 
    unsigned char *byteStream; 
    unsigned char *tooManySym = 0; 
    unsigned long totalEncodedSym; 


    *uniqueSymbols = globalUniqueSymbols; 


    totalEncodedSym = ftell(in); 
    rewind(in); 

    fileIn = malloc((totalEncodedSym+1)*sizeof(char)); 
    fread(fileIn, totalEncodedSym, 1, in); 
    if(globalUniqueSymbols == 256) 
    { 
     fwrite(tooManySym, 1, sizeof(char), out); 
    } 
    else 
    { 
     fwrite(uniqueSymbols, 1, sizeof(uniqueSymbols)-7, out); 
    } 
    for(i = 0; i < 256; i++) 
    { 
     if(globalFreqs[i] != 0) 
     { 
      fwrite(globalUsedCh+i, 1, sizeof(char), out); 
      fwrite(globalFreqs+i, 8, sizeof(char), out); 
     } 
    } 
    for(t = 0; t < totalEncodedSym; t++) 
    { 
      fwrite(symCodes[fileIn[t]], 8, sizeof(char), out); 
    } 
    for(q = 0; q < totalEncodedSym; q++) 
    { 
     symCodes[q] = malloc(255*sizeof(char)); 
     a = symCodes[q]; 
     while(*a != '\0') 
      printf("%c\n", *(a++)); 
    } 

    printf("Total encoded symbols: %lu\n", totalEncodedSym); 
    printf("%s\n", fileIn); 
} 

void encodeFile(FILE* in, FILE* out) 
{ 
    int top = 0; 
    int i; 
    char *code; 
    char *symCodes[256] = {0}; 
    int depth = 0; 

    code = malloc(255*sizeof(char)); 

    getFileFreq(in, out); 
    buildSortedList(); 
    makeCodes(buildHuffmanTree(globalSortedLL), code, symCodes, depth); 
    printTable(symCodes); 
    headerEncode(in, out, symCodes); 



    free(code); 
} 

/* 
void decodeFile(FILE* in, FILE* out) 
{ 

}*/ 
+0

部分代碼丟失。 – chqrlie

+0

@chqrlie是程序的一部分缺失,我試圖提供我能想象到的會影響這個的所有內容,例如字符串的實際創建以及試圖打印字符串的每個字符。該計劃比這更長,但如果需要,我可以提供所有這些。 – kanyeezus2020

+0

你可以閱讀關於這個:[MCVE] –

回答

2

有在你的代碼中的許多問題:

  • [大]功能compareTwoNodes並不總是返回值。如果指示輸出更多警告,編譯器可以檢測到這些問題。

  • [主要]構件symbolHuffmanTreeNode應具有類型int。類型char作爲索引值是有問題的,因爲它可以是有符號或無符號的,具體取決於編譯器配置和平臺特性。您假設char的值從0255,對於大多數平臺而言這是不正確的,其中char實際上的範圍爲-128 .. 127。使用unsigned charint,但將char的值轉換爲unsigned char以確保正確提升。

  • [大]比較if (globalUniqueSymbols == 256)永遠是假的,因爲globalUniqueSymbolsunsigned char。對於8位字節,可能的字節值的最大數量的確爲256,但它不適合unsigned char,使globalUniqueSymbolsint

  • [主要]*uniqueSymbols = globalUniqueSymbols;在功能headerEncode存儲globalUniqueSymbols到未初始化的指針,絕對不確定的行爲,可能段故障。

  • [大]sizeof(uniqueSymbols)是指針的大小,而不是數組的大小而不是類型的大小。相反,盜號的爲sizeof(uniqueSymbols)-7fputc(globalUniqueSymbols, out);

  • [大]fwrite(tooManySym, 1, sizeof(char), out);是不正確也是如此,因爲tooManySym被初始化爲0,即:它是一個NULL指針。您需要一個特殊的值來說明源數據流中使用的所有字節值,請使用0作爲該值,並使用fputc(0, out);來寫入。

  • 你在函數insert之前嵌套了C風格的註釋,這不是一個錯誤,而是容易出錯並被認爲是不好的風格。

  • 函數newNode爲了保持一致性,應採用unsigned long的類型爲freq

  • 功能buildHuffmanTree有未使用的局部變量:right,toptopNode

  • 變量i未在功能makeCodes中使用。在headerEncode

  • 許多未使用的變量:byteStreamcchb ...

  • totalEncodedSymunsigned long,用在哪裏,你停在totalEncodedSym環的正確類型的索引。

  • 未使用的變量未encodeFileitop ...

大多數這些可以通過適當的警告級別的編譯器可以檢測:gcc -Wall -Wclang -Weverything ...

有可能也是程序邏輯中的錯誤,但在解決上述主要問題之前,您無法看到這些錯誤。

+0

代碼已被更新 – kanyeezus2020