2016-02-01 3 views
2

Мне нужно определить «слово» в этом вопросе как любую последовательность символов, которая не содержит пробел или нулевой символ. Например, строка “Hello World” будет содержать 2 слова. Однако на самом деле возможно, что слово будет пустым. т. Е. Нулевые символы. Приговор представляет собой серию слов, разделенных 1 пробелом. Таким образом, “Hello World” будет предложением двух слов. Целью ReverseSentence было бы отменить предложение в терминах слова. Прямо сейчас у меня есть ошибка, при которой программы переходят к функции вызова и распечатывают от a1 до a5. По достижении a5, кажется, что программа прерывается и ядро ​​сбрасывается. Если я заменяю пробел пробелом, он будет считываться на предыдущем входе и заменять в соответствии с количеством пробелов. Где я иду не так?Обратная строка в malloc

ReverseSentence.c

#include <stdlib.h> /* malloc */ 
#include <string.h> /* strcat, strcpy */ 

void ReverseSentence(char *str) 
{ 
    char *newSentence; 
    int i, j, start, len; 
    /* contains the string length of the input */ 
    len = strlen(str); 
    /* position or index in the array */ 
    start = strlen(str); 
    /* malloc */ 
    newSentence = malloc(len + 1); 

    /* loop checks from the right of the sentences */ 
    for (i = len; i >= 0; i--) { 
     /* if index reach the array with a space or zero */ 
     if (str[i] == ' ' || i == 0) { 
      /* allocates memory */ 
      char *word = malloc((start - i) + 1); 
      int c = 0; 

      if (i == 0) 
       /* index remains same */ 
       j = i; 
      else 
       j = i + 1; 

      /* j smaller or equal than the start position */ 
      for (; j <= start; j++) { 
       /*do a incremental*/ 
       word[c++] = str[j]; 
      } 
      /* hits a null char */ 
      word[c] = '\0'; 
      /* string concatenate */ 
      strcat(newSentence, word); 
      /* if index hits a space */ 
      if (str[i] == ' ') 
       strcat(newSentence, " "); /* concatenate space to newSentence */ 
      else 
       strcat(newSentence, "\0"); 
      start = i - 1; 

      /* free memory */ 
      free(word); 
     } 
    } 
    newSentence[len] = '\0'; 
    /* string copy */ 
    /* str is destination, newSentence is the source */ 
    /* copy new string to original string */ 
    strcpy(str, newSentence); 
    /* free memory */ 
    free(newSentence); 
} 

main.c

#include <stdio.h> 
#include "ReverseSentence.h" 

int main() 
{ 
    char a1[] = "Hello World "; 
    char a2[] = "abcdefghi "; 
    char a3[] = " "; 
    char a4[] = "C programming is a dangerous activity"; 
    char a5[] = "a "; /* a sentence with only empty words */ 
    ReverseSentence(a1); 

    printf("Test case 1:\"%s\"\n", a1); /* prints "World Hello" */ 
    ReverseSentence(a2); 

    printf("Test case 2:\"%s\"\n", a2); /* prints "abcdefghi" */ 
    ReverseSentence(a3); 

    printf("Test case 3:\"%s\"\n", a3); /* prints "" */ 

    ReverseSentence(a4); 
    printf("Test case 4:\"%s\"\n", a4); /* prints "activity dangerous a is pro Cgramming" */ 

    ReverseSentence(a5); 
    printf("Test case 5:\"%s\"\n", a5); /* prints " " */ 

    return 0; 
} 

EDIT: новая версия

void ReverseSentence(char *str) 
{ 
    /* holder */ 
    /* pointer to char */ 
    char *newSentence; 
    int i, start, len, lastindex, size; 

    /* contains the string length of the input */ 
    len = strlen(str); 
    lastindex = strlen(str); 
    /* starting position */ 
    start = 0; 
    i = 0; 
    /* malloc */ 
    newSentence = malloc(sizeof(char) * strlen(str)); 

    while (i >= 0) { 
     for (i = len - 1; str[i] != '\0' && str[i] != ' '; i--) { 
      lastindex--; 
     } 

     /* number of chars in string size */ 
     size = len - lastindex; 
     /* Copy word into newStr at startMarker */ 
     strncpy(&newSentence[start], &str[lastindex], size); 

     /* pointer move to right */ 
     start = start + size; 
     /* Space placed into memory slot */ 
     newSentence[start] = ' '; 
     /* start position moves by 1 towards the right */ 
     start = start + 1; 
     /* pointer at len moves to left */ 
     lastindex = lastindex - 1; 
     /* lastindex moves to where len is */ 
     len = lastindex; 
    } 

    /* Copy new string into old string */ 
    for (i = 0; str[i] != '\0'; i++) { 
     str[i] = newSentence[i]; 
    } 

    /* free memory */ 
    free(newSentence); 
} 
+0

считывает массив справа налево, затем strcat слово после проверки попадает в пробел, а затем скопирует строку в новую строку –

+0

Здесь он уже падает с a1. –

+0

В вашей новой версии есть хотя бы одна проблема: 'newSentence = malloc (sizeof (char) * strlen (str))'. Вы не выделяете достаточно памяти, вы не учитываете нулевой терминатор. Вы должны выделить еще один байт. Но есть и другие проблемы. BTW: 'sizeof (char)' всегда '1' для определения, поэтому вам не нужно его писать. –

ответ

2

Ваш код н безопасный. Вы никогда не инициализируете newSentence, так как malloc() выделяет, но не инициализирует память (в отличие от calloc()). Таким образом, вы начинаете с мусорного предложения, где вы добавляете что-то новое (strcat()). В зависимости от мусора в выделенной памяти может отсутствовать 0, и вы получаете доступ к некоторой нераспределенной области памяти.

+2

Не только это не безопасно, это неправильно. Вы _must_ инициализируете буфер 'newSentence' после вызова' malloc', например 'newSentence [0] = 0'. –

+0

@michael Walz Получил это. Я вышел с другим решением. будет редактировать мой пост сверху –

2

В дополнение к ответу Маттиаса: вы не выделяете достаточно памяти, я просто сделал дикое предположение и добавил 1 к аргументам, переданным в malloc.

newSentence = malloc(len + 2); // +2 instead of +1 

и

char *word = malloc((start - i) + 2); // +2 instead of +1 

И теперь он не откажет больше. Таким образом, здесь определенно переполнение буфера.

Я не притворяюсь, что программа совершенно правильная. Вы должны посмотреть на это.

1

Ваш метод слишком сложный. Он имеет несколько вопросов:

  • вы не инициализировать newSentence: поскольку malloc памяти неинициализированная, вы призываете к непредсказуемому поведению при копировании слов в его конце с strcat. Вы можете исправить это с *newSentence = '\0';

  • при копировании слова в выделенных word буфера, вы итерация ДО и в то числе start, затем добавить '\0' в конце. Вы фактически пишете один байт слишком много за последнее слово (случай i == 0). Это вызывает неопределенное поведение.

  • strcat(newSentence, "\0"); ничего не делает.

  • выделение буфера для каждого найденного слова расточительно, вы можете просто скопировать слово с memcpy или с помощью простого цикла for.

Вы могли бы упростить следующие шаги:

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

Вот код:

char *ReverseSentence(char *str) { 
    int len = strlen(tmp); /* length of the string */ 
    char *tmp = strdup(str); /* copy of the string */ 
    int i;  /* index into the copy */ 
    int j = len; /* index into the string */ 
    int n;  /* length of a word */ 
    for (i = 0; i < len;) { 
     n = strcspn(tmp + i, " "); /* n is the length of the word */ 
     j -= n;      /* adjust destination offset */ 
     memcpy(str + j, tmp + i, n); /* copy the word */ 
     i += n;      /* skip the word */ 
     if (tmp[i] != '\0') {  /* unless we are at the end */ 
      j--; 
      str[j] = tmp[i];   /* copy the separator */ 
      i++; 
     } 
    } 
    free(tmp);      /* free the copy */ 
    return str; 
} 
+0

спасибо за помощь. Я вышел с другим решением. будет редактировать мой пост сверху. –

0

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

  • Вы не выделить достаточно памяти, вы не» t учитывает нулевой ограничитель. Вы должны выделить еще один байт.

  • в вашем первом for циклах вы позволяете i стать -1. Цикл должен остановиться, когда i равен нулю: измените свой for оператор следующим образом: for(i=len-1; tr[i] != ' ' && i >= 0; i--). Вы ошибочно полагаете, что первый байт перед буфером str равен нулю, поэтому str[i]!='\0' ошибочен. BTW, получающий один байт до того, как буфер str дает неопределенное поведение.

  • Возможно, есть другие проблемы.

Смежные вопросы