Не могу напечатать строку в обратном порядке в C - PullRequest
0 голосов
/ 20 сентября 2011

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

#include<stdio.h>
#include<string.h>
int main (int argc, char **argv)
{
        char *string;
        int n;
        printf("Enter a string\n");
        scanf("%s",string);
        printf("\n");
        n = strlen(string);
        printf("%d",n);
        while(n != 0)
        {
                printf("%c",string[n]);
                n--;
        }
        return(0);
}

Может кто-нибудь объяснить мне, почему я получаю эту ошибку сегментации? Операционная система: Ubuntu, компилятор: gcc

Ответы [ 5 ]

6 голосов
/ 20 сентября 2011

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

Чтобы быть полезным, либо выделите некоторую память и назначьте ее указателю:

char *string = malloc(1000);  // big enough for string

, либо сделайте все это вОднажды:

char string[1000];

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

2 голосов
/ 20 сентября 2011

%s с scanf ничего не выделяет. Вызывающий должен выделить. Даже если вы выделяли что-то, поскольку вы не знаете, какой будет длина строки во входном потоке, это похоже на выполнение gets, что плохо по соображениям безопасности и стабильности.

Одна из самых простых вещей, которые вы можете сделать, - это предварительно установить постоянное количество символов и использовать fgets:

char string[256];

if (!fgets(string, sizeof(string), stdin))
{
   // TODO: handle error
}

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

char *buf = NULL;
size_t current_len = 0, current_alloc = 0;
int c = 0;
int should_continue = 1;

while (should_continue)
{
   // Read a character...
   c = fgetc(stdin);

   // If c is EOF or a newline, let's zero-terminate the buffer and terminate
   // the loop...
   if (c == EOF || c == '\n')
   {
      c = 0;
      should_continue = 0;
   }

   if (current_len + 1 > current_alloc)
   {
      // Need to grow the buffer.
      void *newbuf;
      size_t newsize;

      newsize = current_alloc ? current_alloc * 2 : 256;
      newbuf = realloc(buf, newsize);
      if (!newbuf) { /* TODO: handle error */ }

      current_alloc = newsize;
      buf = newbuf;
   }

   // We've ensured capacity, now add the character.
   buf[current_len++] = c;
}

// TODO: use buf as string...

// Now free since we're done
free(buf);

Что касается обращения строки, то это всего лишь пример типичного способа работы со строками в стиле C:

// Reverse the string in-place...

void reverse(char *s)
{
   if (*s)
   {
      char *t = s + strlen(s) - 1;

      while (s < t)
      {
         char u = *s;
         *s++ = *t;
         *t-- = u;
      }
   }
}

С этим после прочтения вы можете сделать:

reverse(string);
puts(string);
2 голосов
/ 20 сентября 2011

Есть несколько проблем с вашим кодом, которые я выделил:

- вы не выделяете память для строки

- вы пытаетесь получить доступ к элементу массива, который находится за пределами

- вы забыли уменьшить n, так что у вас будет бесконечный цикл

Помните, что массивы в C основаны на 0.

#include<stdio.h>
#include<string.h>
int main (int argc, char **argv)
{
        char *string = malloc(100); //forgot to allocate memory
        int n;
        printf("Enter a string\n");
        scanf("%s",string);
        printf("\n");
        n = strlen(string);
        printf("%d",n);
        while(n != 0)
        {
                n--; //forgot to decrement here, so infinite loop
                     //crash was also from here, string[n] is not a valid index
                printf("%c",string[n]);
        }
        return(0);
}
0 голосов
/ 21 сентября 2011

Вы объявили строку как char * и не указали адрес, поэтому он указывает на адрес переменной.

0 голосов
/ 20 сентября 2011

Как @wallyk уже сказал:

char* string

на самом деле указатель на символ. Вы должны выделить память для строки, используя либо

malloc or calloc

так что вы можете сделать что-то вроде:

char* string;
string = (char*) malloc( 50 * sizeof(char) );

, который выделит 50 символов для строки. Если ваша строка содержит более 50 символов, просто выделите ее соответствующим образом.

Другой способ сделать это - вместо создания указателя вы можете (не динамически) распределять память следующим образом:

char string[50]

Это также выделит 50 символов для строки.

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