Я пытаюсь увеличить значения в массиве символов C, и он продолжает терпеть неудачу - помощь? - PullRequest
0 голосов
/ 17 августа 2010

Вот код моей функции:

char * increment_b_string(char * b_string)
{
    char * ret_string = (char *) malloc(7);

    ret_string = "001aaa";

    if (*(b_string + 2) == '9')
    {
        *(ret_string +2) == '0';

        if (*(b_string + 1) == '9')
        {
            *(ret_string +1) = '0';
            *(ret_string) = *(b_string) + 1;
        } else {
            *(ret_string + 1) = *(b_string + 1) + 1;
        }
    } else {
        *(ret_string + 2) = *(b_string + 2) + 1;
    }

    return ret_string;
}

Есть какие-нибудь мысли о том, почему это может не сработать?

Общая идея заключается в том, что b_string будет содержать значение типа "123aaa". Часть «ааа» не имеет значения и никогда не изменится. Только первые 3 числа будут. Их нужно увеличивать, как если бы они были целыми числами. Ведущие нули должны быть сохранены в начале. Таким образом, если вход «004aaa», выход должен быть «005aaa». Это только нужно подняться до "300aaa", поэтому я не рассматриваю ничего более этого. Это школьное задание по программированию, отсюда и очень надуманный характер проблемы.

Спасибо.

Редактировать: я изменил свою функцию. Вот что это сейчас.

void increment_b_string(char * b_string)
{   
    if (b_string[2] == '9')
    {
        b_string[2] == '0';

        if (b_string[1] == '9')
        {
            b_string[1] = '0';
            b_string[0] += 1;
        } else {
            b_string[1] += 1;
        }
    } else {
        b_string[2] += 1;
    }
}

Предполагая, что b_string изначально заполнена ...

strcpy (b_string, "001aaa");

... это было бы правильно? Моя программа все еще демонстрирует то же поведение, но это может быть ошибка где-то еще в коде.

Ответы [ 6 ]

14 голосов
/ 17 августа 2010

Вы не можете увеличивать или изменять строковый литерал - они только для чтения в C, что вы и делаете.

char * ret_string = (char *) malloc(7);
ret_string = "001aaa";

Не делает то, что вы думаете, он не копируетстрока в нерабочее пространство, на которое указывает ret_string, устанавливает значение ret_string, указывающее на строковый литерал "001aaa".Используйте это вместо:

 char * ret_string = (char *) malloc(7);
 strcpy(ret_string,"001aaa");
2 голосов
/ 17 августа 2010

Например, я бы инициализировал ret_string через:

char * ret_string = strdup("001aaa");

В настоящее время вы присваиваете ret_string строковому литералу, что вы не хотите делать, когда собираетесь изменять строку.

Обратите внимание, что вы должны позвонить free(ret_string), когда закончите.Реализация strdup содержит malloc.

Во-вторых, вам может быть проще пройти через логику функции, если вы используете синтаксис b_string[i] вместо *(b_string + i).Они эквивалентны.

Редактировать:

Поскольку strdup не является ANSI C, вы всегда можете определить свою собственную функцию с той же функциональностью, например:

char *strdup (const char *s) {
    char *d = (char *)(malloc (strlen (s) + 1));
    if (d == NULL) return NULL;
    strcpy (d,s);
    return d;
}

Ссылка:

strdup () - что он делает в C?

1 голос
/ 17 августа 2010

Ниже приведен код для достижения желаемого.Включено переписывание вашей приращенияОн использует strtol (string to long) и sprintf для преобразования строки в int и обратно соответственно.Предполагается, что строка символов, для которой будет работать increment_b_string, всегда имеет формат dddccc (d = цифра, c = символ)., the_string = "000aaa"
после, the_string = "001aaa"

1 голос
/ 17 августа 2010

Ничего из этого не было проверено, но следующее должно работать хорошо.

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

/* Many libc implementations have strdup, but some don't */
char * strdup(const char * str) {
     char * copy = malloc(strlen(str)+1);
     if (copy) {
         strcpy(copy, str);
     }
     return copy;
}


/* This increments the first ASCII integer it finds within the string by one.
 * The integer is treated as though it is base 10 for the purposes of incrementing
 * and in the event that the upper digit is '9' before the increment it is '0' after
 * the increment and the carry digit is lost.
 */ 
char * increment_b_string_inplace(char * str) {
     char * s = str;
     while (*s) {  /* Look for where the number starts. */
        char c = *s;
        if (isdigit(c)) { 
            /* This is the start of a number! */
            char * e = s+1;
            unsigned carry;
            while (isdigit(*++e) ) {;} /* find where the number ends */ 
            e--;  /* we went 1 too far, so back up */
            do {   /* Do the actual increment. ][
                unsigned i = *e - '0';
                i++;
                carry = i % 10; /* this should always be 0 or 1 */
                *e = (char)('0' + (i / 10) );
                e--;
            } while (e<=s && carry);
        }
    }
    return str;
}


/* This is the function you originally wanted. */
char * increment_b_string(const char * b_string)
{
    char * str = strdup(b_string);

    if (!str) {
        return str;
    }
    return increment_b_string_inplace(str);
}

Вы могли бы также прочитать все целое число в переменную int, увеличить его, а затем превратить обратно в строку.

0 голосов
/ 18 августа 2010

решение со строгим C89, без malloc / strdup и более гибкое для переменных строк ввода:

char *inc_bstr(char *str)
{
  char *e,f[] = "%03ld%s";
  long i = strtol(str,&e,10)+1;
  f[2] = '0'+(e-str);
  sprintf(str,f,i>300?300:i,e);
  return str;
}

...
char x1[]="0aaa";
puts(inc_bstr(x1));
...
char x2[]="00aaa";
puts(inc_bstr(x2));
...
char x3[]="000aaa";
puts(inc_bstr(x3));
...
char x4[]="0000aaa";
puts(inc_bstr(x4));
...
char x5[]="00000aaa";
puts(inc_bstr(x5));
...
char x6[]="0000bb";
puts(inc_bstr(x6));
...
char x7[]="000";
puts(inc_bstr(x7));
...
char x8[]="000xxx",z=99;
while( z-- )
  puts(ins_bstr(x8));
0 голосов
/ 17 августа 2010

Кроме того, ваша ret_string будет иметь один или два нуля спереди, которые должны быть чем-то другим, если выполняются предложения else. Чтобы это исправить, вам нужно инициализировать ret_string из b_string, а не из константы:

char * ret_string = strdup(b_string);
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...