2016-12-07 1 views
2

Wie kann ich jedes einzelne Zeichen aus einer Zeichenfolge lesen, auf die über ein Array von Zeigern zugegriffen wird? Im folgenden Code habe ich zur Zeit ein Array von Zeigern auf Strings namens symCodes in meiner makeCodes Funktion generiert. Ich möchte die Zeichenfolgen jeweils zu einem Zeitpunkt lesen. Ich dachte darüber nach, jeden String miteinander zu verketten und dann das Zeichen durch Zeichen zu durchlaufen, aber die Zeichenfolgen in symCodes könnten jeweils bis zu 255 Zeichen lang sein, also könnte das möglicherweise zu viel sein alles auf einmal zu handhaben. Stattdessen dachte ich, ich könnte jedes Zeichen aus den Strings Zeichen für Zeichen lesen.Lesen einer Zeichenfolge aus einem Array von Zeigern

Ich habe versucht scanf oder nur durchschleifen und immer mit seg faults enden. Am Ende von headerEncode() ist es in der Nähe der Unterseite. Ich malloc genug Speicher für jede einzelne Zeichenfolge, ich versuche, durch das Array der Zeiger zu durchlaufen und jedes einzelne Zeichen auszudrucken, aber am Ende mit einem Seg Fehler.

Alle Vorschläge für eine andere Art, ein Array von Zeigern zu Strings zu lesen, Zeichen für Zeichen, bis zu n Anzahl der Zeichen wird geschätzt.

EDIT 1: Ich habe das Programm so aktualisiert, dass keine Warnungen mehr ausgegeben werden, wenn die Flags "-Wall" und "-W" verwendet werden. Ich bekomme keinen seg-Fehler mehr (yay!), Aber ich weiß immer noch nicht, wie ich meine Frage beantworten soll. Wie kann ich ein Array von Zeigern auf Strings lesen, Zeichen für Zeichen, bis zu n Zeichen?

#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

Ein Teil des Codes fehlt. – chqrlie

+0

@chqrlie ja ein Teil des Programms fehlt, ich habe versucht, alles, was ich vorstellen könnte, dass dies beeinflussen würde, wie das eigentliche Erstellen der Zeichenfolgen und versuchen, jedes Zeichen der Zeichenfolge zu drucken. Das Programm ist viel länger als das, aber bei Bedarf könnte ich alles bereitstellen. – kanyeezus2020

+0

Sie können darüber lesen: [MCVE] –

Antwort

2

Es gibt viele Probleme in Ihrem Code:

  • [major] Funktion compareTwoNodes nicht immer einen Wert zurück. Der Compiler kann solche Probleme erkennen, wenn er angewiesen wird, weitere Warnungen auszugeben.

  • [major] das Mitglied symbol im HuffmanTreeNode sollte int Typ haben. Der Typ char ist als Indexwert problematisch, da er je nach Compilerkonfiguration und Plattformspezifität signiert oder unsigniert sein kann. Sie gehen davon aus, dass char Werte von 0 bis 255 hat, was für die meisten Plattformen falsch ist, wobei char tatsächlich eine Bandbreite von -128 .. 127 hat. Verwenden Sie unsigned char oder int, aber werfen Sie die char Werte auf unsigned char, um eine ordnungsgemäße Förderung sicherzustellen.

  • [major] Vergleich if (globalUniqueSymbols == 256) ist immer falsch, weil globalUniqueSymbols ein unsigned char ist. Die maximale Anzahl der möglichen Byte-Werte ist in der Tat 256 für 8-Bit-Bytes, aber es passt nicht in eine unsigned char, machen globalUniqueSymbols eine int.

  • [major]*uniqueSymbols = globalUniqueSymbols; in Funktion headerEncode speichert globalUniqueSymbols in einem nicht initialisierten Zeiger, auf jeden Fall nicht definiertes Verhalten, wahrscheinlich Segmentierungsfehler.

  • [major]sizeof(uniqueSymbols) ist die Größe eines Zeigers, nicht die Größe des Arrays nicht die Größe des Typs.Anstatt es als sizeof(uniqueSymbols)-7 Hacking, fputc(globalUniqueSymbols, out);

  • [major]fwrite(tooManySym, 1, sizeof(char), out); ist zu falsch, da tooManySym-0 initialisiert wird, das heißt: es ist ein NULL Zeiger. Sie benötigen einen speziellen Wert, der angibt, dass alle Bytes im Quelldatenstrom verwendet werden, verwenden Sie hierzu 0 und schreiben Sie ihn mit fputc(0, out);.

  • Sie haben C-Stil-Kommentare vor der Funktion insert verschachtelt, dies ist kein Fehler, sondern fehleranfällig und als schlechter Stil angesehen.

  • Funktion newNode sollte Typ unsigned long für freq für Konsistenz nehmen.

  • Funktion buildHuffmanTree hat nicht verwendete lokale Variablen: right, top und topNode.

  • Variable i wird in Funktion makeCodes nicht verwendet.

  • viele ungenutzte Variablen in headerEncode: byteStream, c, ch, b ...

  • totalEncodedSym ist ein unsigned long, einen Index des richtigen Typs in den Schleifen verwenden, in denen Sie bei totalEncodedSym stoppen.

  • nicht verwendete Variablen un encodeFile: i, top ...

dieser meisten können durch den Compiler mit den richtigen Warnstufe erkannt werden: gcc -Wall -W oder clang -Weverything ...

Es gibt wahrscheinlich auch Fehler in der Programmlogik, aber Sie können diese nicht sehen, bis Sie die Hauptprobleme oben beheben.

+0

der Code wurde aktualisiert – kanyeezus2020

Verwandte Themen