2016-12-07 2 views
2

Comment lire chaque caractère d'une chaîne accessible via un tableau de pointeurs? Dans le code ci-dessous j'ai actuellement généré un tableau de pointeurs aux chaînes appelées, symCodes, dans ma fonction makeCodes. Je veux lire les chaînes de 8 caractères à la fois, j'ai pensé à concaténer chaque chaîne ensemble, puis faire défiler ce char par char, mais les chaînes de symCodes pourraient contenir jusqu'à 255 caractères, donc je pense que ça pourrait être trop tout à gérer à la fois. Au lieu de cela, j'ai pensé que je pouvais lire chaque caractère des cordes, caractère par caractère.Lecture d'une chaîne à partir d'un tableau de pointeurs

J'ai essayé scanf ou j'ai simplement bouclé et je me retrouve toujours avec des erreurs de segmentation. À la fin de headerEncode(), c'est près du fond. Je malloc assez de mémoire pour chaque chaîne individuelle, j'essaie de faire une boucle à travers le tableau de pointeurs et d'imprimer chaque caractère individuel, mais je me retrouve avec une faute de seg.

Toute suggestion d'une manière différente de lire un tableau de pointeurs sur des chaînes, caractère par caractère, jusqu'à n quantité de caractères est appréciée.

EDIT 1: J'ai mis à jour le programme afin qu'il ne produise plus d'avertissement lors de l'utilisation des options -Wall et -W. Je ne reçois plus de faute de seg (yay!) Mais je ne sais toujours pas comment aborder ma question, comment puis-je lire un tableau de pointeurs sur des chaînes, caractère par caractère, jusqu'à n quantité de caractères?

#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

Une partie du code est manquante. – chqrlie

+0

@chqrlie oui une partie du programme est manquante, j'ai essayé de fournir tout ce que je pouvais imaginer qui affecterait cela, comme la création réelle des chaînes et en essayant d'imprimer chaque caractère de la chaîne. Le programme est beaucoup plus long que cela, mais si nécessaire, je pourrais fournir tout cela. – kanyeezus2020

+0

Vous pouvez lire à ce sujet: [MCVE] –

Répondre

2

Il y a beaucoup de problèmes dans votre code:

  • [principale] fonction compareTwoNodes ne renvoie pas toujours une valeur. Le compilateur peut détecter de tels problèmes s'il est demandé de produire plus d'avertissements.

  • [principale] le membre symbol dans le HuffmanTreeNode devrait avoir le type int. Le type char est problématique en tant que valeur d'index, car il peut être signé ou non signé en fonction de la configuration du compilateur et des spécificités de la plate-forme. Vous supposez que char a des valeurs de 0 à 255, ce qui est incorrect pour la plupart des plates-formes où char a effectivement une plage de -128 .. 127. Utilisez unsigned char ou int mais attribuez la valeur char à unsigned char pour assurer une promotion adéquate.

  • [principale] comparaison if (globalUniqueSymbols == 256) est toujours faux parce globalUniqueSymbols est un unsigned char. Le nombre maximal de valeurs d'octet possibles est en effet 256 pour les octets de 8 bits, mais il ne rentre pas dans un unsigned char, faire globalUniqueSymbols et int.

  • [] majeurs *uniqueSymbols = globalUniqueSymbols; en fonction headerEncode magasins globalUniqueSymbols dans un pointeur non initialisé, le comportement non défini définitivement, faute de segmentation probable.

  • [majeure]sizeof(uniqueSymbols) est la taille d'un pointeur, et non la taille de la matrice pas la taille du type.Au lieu de piratage comme sizeof(uniqueSymbols)-7, fputc(globalUniqueSymbols, out);

  • [principale]fwrite(tooManySym, 1, sizeof(char), out); est trop incorrect, puisque tooManySym est initialisé à 0, à savoir: il est un pointeur NULL. Vous avez besoin d'une valeur spéciale pour indiquer que toutes les valeurs d'octets sont utilisées dans le flux source, utilisez 0 pour cela et écrivez-la avec fputc(0, out);.

  • Vous avez imbriqué des commentaires de style C avant la fonction insert, il ne s'agit pas d'un bogue mais d'une erreur sujette à des erreurs et d'un mauvais style.

  • la fonction newNode doit prendre le type unsigned long pour freq pour la cohérence.

  • La fonction buildHuffmanTree a des variables locales inutilisées: right, top et topNode. La variable i est inutilisée dans la fonction makeCodes.

  • nombreuses variables inutilisées dans headerEncode: byteStream, c, ch, b ...

  • totalEncodedSym est un unsigned long, utilisez un indice du type approprié dans les boucles où vous vous arrêtez à totalEncodedSym.

  • variables inutilisées un encodeFile: i, top ...

La plupart d'entre eux peuvent être détectés par le compilateur avec le niveau d'avertissement approprié: gcc -Wall -W ou clang -Weverything ...

Il sont probablement aussi des erreurs dans la logique du programme, mais vous ne pouvez pas les voir tant que vous n'avez pas résolu les problèmes majeurs ci-dessus.

+0

le code a été mis à jour – kanyeezus2020