как вернуть скрипт в c / gcc? - PullRequest
0 голосов
/ 14 июля 2009

прошло много лет с тех пор, как я написал свою последнюю строку на C, теперь я пытаюсь начать снова, чтобы сделать какую-то функцию и использовать ее, а не как расширение для php.

это простая функция для создания "маленьких URL"

скажем так:

a0bg a0bf a0bh

Проблема, с которой я сталкиваюсь, заключается в том, что когда мне нужно "увеличить" строку типа zzz , тогда я получаю: Ошибка шины

в противном случае, если я увеличу abr , например, я получу результат: abs

В какой-то момент я думаю, что моя проблема здесь в возвращении строкового результата

оба кода полностью функциональны, так как я разместил их здесь.

для компиляции я использую: gcc append_id_test.c -o append_id

Я на OS X Leopard

когда я это делаю, это работает: (пожалуйста, обратите внимание на вызов функции 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;
}

но весь код не работает (как вы видите, вызов функции append_id был выполнен так же, как и в приведенном выше примере)

#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;
}

Ответы [ 3 ]

2 голосов
/ 14 июля 2009

Пожалуйста, скомпилируйте с -Wall в следующий раз;)

Для начала, перед использованием tolower и isalnum,

#include <ctype.h>

Во-вторых, вы назначаете x (в основной области видимости) для указания на строковый литерал, который является константой. Следовательно, вы получите нарушение памяти, когда попытаетесь переписать его при нижнем регистре. Попробуйте инициализировать, скажем,

char x[] = "zz";

Вы также должны инициализировать next_id в get_next_id:

char *next_id = NULL;

Позже, не запускайте strlen для нулевого указателя:

// 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);
}

В append_id вам необходимо завершить null перед использованием strcat:

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

Это просто заставляет его работать. Есть много вещей не так с вашим кодом. Вы упоминаете

прошло много лет с тех пор, как я написал свою последнюю строку в C

Я действительно надеюсь, что вы лучше поняли это несколько лет назад, похоже, вы не обращаете внимания на многие фундаментальные понятия памяти C, строки и указатели.

1 голос
/ 14 июля 2009

Кроме того, что вы забыли освободить память, у вас есть две проблемы, в строках 12 и 72. В строке 12 вы должны объявить "zz" как массив символов, а не как строковый литерал:

    char x[] = "zz";

В строке 72 значение next_id будет нулевым, если все символы имеют максимальное значение. strlen (null) вызовет еще один segfault.

    if ( !next_id )
0 голосов
/ 14 июля 2009

Я, вероятно, проверю циклы for в get_next_id. Вы повторяете указатель без ограничения. Где это заканчивается?

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

Сделайте то же самое, что вы сделали на append_id. Получите размер полученного указателя (int id_size = strlen (id);), затем итерируйте указатель last_id на основе этой длины.

Я думаю, что ваш цикл никогда не заканчивается. last_id [x] вернет символ, а не условие. Так что это будет всегда верно, если только не будет случая, когда текущий символ равен нулю.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...