2009-07-14 5 views
0

avait été des années depuis que j'ai écrit ma dernière ligne en C, maintenant j'essaie de recommencer à faire fonctionner et utiliser que comme une extension pour php.comment retourner un script dans c/gcc?

ceci est une fonction facile à créer "petits urls"

permet de dire:

a0bg a0bf a0bh

le problème que je vais avoir est quand je dois "incrément" un chaîne comme zzz puis je me suis: erreur Bus

autrement si j'incrémenter abr par exemple, j'obtenu le résultat: abs

à un moment donné, je pense que mon problème ici renvoie le résultat de la chaîne

à la fois le code sont pleinement fonctionnel que je les affecté ici.

à compilez J'utilise: gcc -o append_id_test.c append_id

Je suis sur le léopard

OS X quand je le fais, cela fonctionne: (s'il vous plaît attention sur l'appel à la fonction append_id)

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

char* append_id(char*); 
int main(void) { 
    char *x; 
    char *incremented; 

    x = "aaab"; 

    printf("%s\n", append_id(x)); // should print 00000 (lenght 5) 


    incremented = (char *) malloc((strlen(x) + 2) * sizeof(char)); 
    incremented = append_id(x); 

    printf("---> %s\n", incremented); // should print 00000 (lenght 5) 

} 

char* append_id(char *id) { 

    int x; 
    char* new_id; 
    int id_size = strlen(id); 

    new_id = (char *) malloc((strlen(id) + 2) * sizeof(char)); 

    for (x = 0; x < id_size; x++) 
    { 
     new_id[x] = '0'; 
    } 

    strcat(new_id, "0"); 

    return new_id; 
} 

mais l'ensemble du code ne fonctionne pas (comme vous voyez l'appel à la fonction append_id a été faite de la même manière que l'exemple ci-dessus)

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


char* append_id(char*); 
char* increment_id(char*, int); 
char* get_next_id(char*); 


int main(int argc, char *argv[]) { 
    char *x; 
    int a; 

    x = "zz"; 

    printf("incrementando %s -> %s\n", "zz", get_next_id(x)); 

    return 0; 
} 


char * get_next_id(char *last_id) 
{ 
    int x, pos; 
    char *next_id; 
    char is_alnum = 1; 

    // if the last id is -1 (non-existant), start at the begining with 0 
    if (strlen(last_id) == 0) 
    { 
     next_id = "0"; 
    } 
    else 
    { 

     // check the input 
     for(x = 0; last_id[x]; x++) 
     { 
      if(!isalnum(last_id[x])) 
      { 
       is_alnum = 0; 
       break; 
      } 
     } 

     if (is_alnum == 0) 
     { 
      return ""; 
     } 


     // all chars to lowercase 
     for(x = 0; last_id[x]; x++) 
     { 
      last_id[x] = tolower(last_id[x]); 
     } 


     // loop through the id string until we find a character to increment 
     for (x = 1; x <= strlen(last_id); x++) 
     { 
      pos = strlen(last_id) - x; 

      if (last_id[pos] != 'z') 
      { 
       next_id = increment_id(last_id, pos); 
       break; // <- kill the for loop once we've found our char 
      } 
     } 

     // if every character was already at its max value (z), 
     // append another character to the string 
     if (strlen(next_id) == 0) 
     { 
      next_id = (char *) malloc((strlen(last_id) + 2) * sizeof(char)); 
      next_id = append_id(last_id); 
     } 

    } 


    return next_id; 
} 



char* append_id(char *id) { 

    int x; 
    char* new_id; 
    int id_size = strlen(id); 

    new_id = (char *) malloc((strlen(id) + 2) * sizeof(char)); 

    for (x = 0; x < id_size; x++) 
    { 
     new_id[x] = '0'; 
    } 

    strcat(new_id, "0"); 

    return new_id; 
} 



char* increment_id(char *id, int pos){ 
    char current, new_char; 
    char * new_id ; 
    int x; 

    new_id = (char *) malloc((strlen(id) + 1) * sizeof(char)); 


    current = id[pos]; 

    if (current >= 0x30 && current <= 0x39) 
    { 
     if (current < 0x39) 
     { 
      new_char = current + 1; 
     } 
     else // if we're at 9, it's time to move to the alphabet 
     { 
      new_char = 'a'; 
     } 
    } 
    else // move it up the alphabet 
    { 
     new_char = current + 1; 
    } 


    for (x = 0; x < strlen(id); x++) 
    { 
     if (x == pos) { 
      new_id[x] = new_char; 
     } 
     else { 
      new_id[x] = id[x]; 
     } 
    } 


    // set all characters after the one we're modifying to 0 
    if (pos != (strlen(new_id) - 1)) 
    { 
     for (x = (pos + 1); x < strlen(new_id); x++) 
     { 
      new_id[x] = '0'; 
     } 
    } 

    return new_id; 
} 
+2

Je vois malloc mais je ne vois pas de free ... – fortran

+1

Dire "ce petit bout de mon code fonctionne, mais cet autre segment avec 2 autres fonctions qui est 4 fois plus gros," n'est pas très utile . – dborba

+0

Je voulais juste vous montrer le contexte du problème: ce que je pense (et je ne suis pas sûr, c'est que le problème commence sur la ligne 74 de la deuxième partie) –

Répondre

2

S'il vous plaît compilez avec -Wall la prochaine fois;)

Pour commencer, avant d'utiliser tolower et isalnum,

#include <ctype.h> 

En second lieu, vous assignez x (périmètre principal) pour pointer un littéral de chaîne, qui est const. Par conséquent, vous obtiendrez une violation de la mémoire lorsque vous essayez d'écrire dessus en minuscules. Essayez initialisant à, disons,

char x[] = "zz"; 

Vous devez également next_id dans get_next_id initialiser:

char *next_id = NULL; 

plus tard, ne fonctionne pas strlen sur un pointeur NULL:

// if every character was already at its max value (z), 
// append another character to the string 
if (!next_id || !strlen(next_id)) 
{ 
    next_id = append_id(last_id); 
} 

En append_id, vous devez mettre fin à null avant d'utiliser strcat:

for (x = 0; x < id_size; x++) 
{ 
    new_id[x] = '0'; 
} 
new_id[id_size] = 0; 

Ça marche. Il ya un lot des choses mal avec votre code. Vous mentionnez

avait été années que j'ai écrit ma dernière ligne C

J'espère vraiment vous avez eu une meilleure idée il y a ce années, semble que vous êtes inconscient de beaucoup de fondamental C concepts de mémoire, de chaîne et de pointeur.

+0

Pendant le développement, je cours souvent avec '-pedantic -Wall -Wextra -Wshadow', ce qui est un peu bruyant, mais toujours utile. – ephemient

0

Je vais probablement vérifier les boucles for dans get_next_id. Vous itérez le pointeur sans limite. Où cela finit-il?

// check the input 
    for(x = 0; last_id[x]; x++) 
    { 
      if(!isalnum(last_id[x])) 
      { 
        is_alnum = 0; 
        break; 
      } 
    } 

Faites la même chose que vous avez fait sur append_id. Obtenez la taille du pointeur reçu (int id_size = strlen (id);) puis répétez le pointeur last_id en fonction de cette longueur.

Je pense que ce qui se passe est que votre boucle ne se termine jamais. last_id [x] retournera un caractère, pas une condition. Donc, ce sera toujours vrai, à moins qu'il y ait le cas que le caractère actuel est zéro.

+0

Les chaînes C sont terminées par un caractère nul. last_id [x] sera 0 à la fin d'une chaîne. – p00ya

+0

Je pense que c'est un problème, car char * x = "zz" n'est pas null terminé (au moins ne pouvait pas être assuré). Il attribue une valeur de "zz" (quel que soit ce que cela signifie) au pointeur x. Je ne sais même pas quelle adresse ce sera. – Freddy

1

autres que d'oublier de libérer votre mémoire, vous avez deux questions, sur les lignes 12 et 72. Sur la ligne 12, vous devez déclarer « zz » comme un tableau de caractères, pas une chaîne littérale:

char x[] = "zz"; 

Sur la ligne 72, next_id sera nul si tous les caractères sont à leur valeur maximale. strlen (null) provoquera un autre segfault.

if (!next_id) 
Questions connexes