2016-12-07 30 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