Помогите с обращением строки в C - PullRequest
2 голосов
/ 12 августа 2010

Я пытаюсь изменить строку символов в C

Вот что у меня есть

void reverse(char str[]) {
    int i = 0;

    int length;
    // Get string length
    for (i = 0; str[i] != '\0' ; ++i) {
        length = i;
    }

    char reversed[1000];

    int j;
    j = 0;
    // Reverse it
    for (j = 0; j < length ; ++j) {
        reversed[j] = str[length - j];
    }

}

Я знаю, что reversed содержит строку в обратном порядке, но я не уверенкак изменить исходный str, не выбрасывая нужные мне данные.

Я также не знаю, как установить str в reversed без повторения снова .

Было бы приемлемо сделать еще один ...

    int m;
    m = 0;

    for (m = 0; m < length ; ++m) {
        str[j] = reversed[j];
    }

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

Обновление

Спасибо за все ответы, ребята, и я благодарен за изменения!

Я закончил с этим ...

int main() {

 char str[] = "Reverse me!";

 int length;

 for (length = 0; str[length] != '\0'; length++) {

 }

 printf("length => %d chars\n", length);

 int j, k;
 char c;

 for (j = 0, k = length - 1; j < k; j++, k--) {
  c = str[k];    
  str[k] = str[j];
  str[j] = c;
 } 

 printf("reversed => %s\n", str);

 return 0;
}

Некоторые вещи, которые я теперь знаю ...

  • Существует strlen(), как в PHP.Тем не менее, это еще не обсуждалось в книге, плюс мне нужно познакомиться со строками с нулевым символом в конце.
  • Цикл for может назначать и делать несколько вещей, разделенных запятыми.Я никогда не знал этого!

Так что спросить стоило:)

Ответы [ 4 ]

4 голосов
/ 12 августа 2010

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

Это полная программа для тестирования:

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

// The pointer version.
void reverse1 (char *str) {
    char t;                      // Temporary char for swapping.
    char *s = str;               // First character of string.
    char *e = &(s[strlen(s)-1]); // Last character of string.

    // Swap first and last character the move both pointers
    // towards each other. Stop when they meet or cross.
    while (s < e) {
        t = *s;
        *s++ = *e;
        *e-- = t;
    }
}

// The array version.
void reverse2 (char *str) {
    char t;                // Temporary char for swapping.
    int s = 0;             // First character of string.
    int e = strlen(str)-1; // Last character of string.

    // Swap first and last character the move both pointers
    // towards each other. Stop when they meet or cross.
    while (s < e) {
        t = str[s];
        str[s++] = str[e];
        str[e--] = t;
    }
}

int main (void) {
    char x[] = "This is a string for reversing.";
    printf ("Original: [%s]\n", x);
    reverse1 (x);
    printf ("Reversed: [%s]\n", x);
    reverse2 (x);
    printf ("   Again: [%s]\n", x);
    return 0;
}

и вывод:

Original: [This is a string for reversing.]
Reversed: [.gnisrever rof gnirts a si sihT]
   Again: [This is a string for reversing.]
4 голосов
/ 12 августа 2010

Вы хотите сделать разворот на месте .Вот стандартный алгоритм:

// taken from The C Programming Language
//    by Brian Kernighan and Dennis Ritchie (K&R)
void reverse(char s[])
{
      int c, i, j;

      for (i = 0, j = strlen(s)-1; i < j; i++, j--) {
         c = s[i];
         s[i] = s[j];
         s[j] = c;
      }
}

Обратите внимание, что strlen в значительной степени заменяет ваш первоначальный первый цикл.Это одна из многих стандартных процедур обработки строк, доступных из string.h.

См. Также

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

Комментарии к вашему коду:

void reverse(char str[]) {
    int i = 0;

    int length;
    // Get string length
    for (i = 0; str[i] != '\0' ; ++i) {
        length = i;
    }

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

size_t len = 0; // size_t is an unsigned integer that is large enough to hold the sizes
                // of the biggest things you can have (32 bits on 32 bit computer,
                // 64 bits on a 64 bit computer)
char * s = str;
while (*s) {
    len++;
    s++;
}

Хотя компилятор, вероятно, сможетчтобы сделать эту оптимизацию для вас.

Вы должны знать, однако, что есть стандартная строковая функция strlen (#include <string.h>), которая будет измерять длину строки символа, используя тот же общий алгоритм (смотритедля конца), но обычно оптимизируется для целевого процессора.

len = strlen(str);

Ваш код еще раз:

    char reversed[1000];

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

int * p = malloc( 8 * sizeof(int) ); // allocate an array of 8 ints
/* ... work on p ... */
free(p);
/* ... don't access the memory pointed to by p anymore ... */
p = 0;

В семействе malloc есть и другие функции.Есть calloc, который выделяет память и очищает, устанавливает ее на 0. Существует также функция с именем strdup (которая отсутствует в стандартном C, но очень широко доступна в string.h), которая принимает строку и выделяетдубликат этого.Это действительно просто:

char * strdup(const char * str) {
    size_t len = strlen(str);
    char * s = malloc(len+1);
    if (!s) {
        return s;
    }
    return strcpy(s,str); // This could have been memcpy since you know the size
                          // and memcpy might have been faster on many processors
}

Еще одна полезная функция выделения памяти - alloca (не в стандарте C, но широко доступна, и аналогичные функциональные возможности доступны с массивами переменной длины в C99).Это здорово, но работает не так, как malloc.Он выделяет память, которую можно использовать только до тех пор, пока текущая функция не вернется, поскольку эта память выделяется так же, как память для локальных переменных (из стека).

Больше вашего кода:

    int j;
    j = 0;
    // Reverse it
    for (j = 0; j < length ; ++j) {
        reversed[j] = str[length - j];
    }

Код:

void reverse_in_place(char * str, size_t len) {
   size_t i, j;
   for (i = 0, j = len - 1; i < j ; i++, j--) {
        char a = str[i];
        char z = str[j];
        str[i] = z;
        str[j] = a;
   }
}

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

0 голосов
/ 25 февраля 2014

Обращение строки в C с помощью указателей

#include<stdio.h>
char *srcptr = "Hello!";
char *destptr;
unsigned int length = 0;
void main(void)
{
   while(*(ptr++) != '\0')
   {
       length++;
   }
   //at the end of while loop, pointer points to end of string 
   while(length--)
   {
        *destptr++ = *ptr--;
   }
    //append null at the end
    *destptr = '\0';
    printf("%s",ptr);
 }
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...