Форум программистов
 

Восстановите пароль или Зарегистрируйтесь на форуме, о проблемах и с заказом рекламы пишите сюда - alarforum@yandex.ru, проверяйте папку спам!

Вернуться   Форум программистов > C/C++ программирование > Общие вопросы C/C++
Регистрация

Восстановить пароль
Повторная активизация e-mail

Купить рекламу на форуме - 42 тыс руб за месяц

Ответ
 
Опции темы Поиск в этой теме
Старый 19.12.2017, 17:57   #1
Вероника99
Форумчанин
 
Регистрация: 15.12.2013
Сообщений: 414
По умолчанию Выделение памяти Си

Здравствуйте. Задача следующая: дан текст. Пользователь вводит слово,которое нужно заменить в тексте и слово,на которое нужно заменить. Проблема заключается в том,что когда пользовательно вводить второе слово такой же длины как и первое,либо меньшей дины,то все нормально;но если пользователь вводит второе слово более длинное, происходит аварийное завершение программы. Подскажите пожалуйста,как правильно организовать выделение памяти так,чтобы не было этой проблемы. Спасибо
Код:
int main(int argc, char* argv[])
{
        char *text=NULL;
        char word1[20];
        char word2[20];
        text = (char*)calloc(1, sizeof(char));
        text=DataFromFile(text,argv[1]);
        puts("\nResults from file:");
        puts(text);
 
        puts("Enter identifier do you want to replace?");
        gets(word1);
        puts("Enter new identifier");
        gets(word2);
 
        //printf("\n%s\n",find(text, word1));
        printf("\n%s\n",del(text, word1,word2));
        free(text); 
    
 
       system("pause");
    return 0;
}
 
 
char *del (char *s, char *t1, char *t2)
{
   char *p, *t;
   int i=1;
   int l=strlen(t2);
   s = (char*)realloc(s, strlen(s)*sizeof(char)+l); //проблема здесь
   for ( p = strstr (s, t1) ; p ; p = strstr (s, t1) )
   {
      t = strdup (p + strlen (t1) );
      memset (p, 0, sizeof(p) );
      s = (char*)realloc(s, strlen(s)*sizeof(char)+l*i); //и здесь
      i++;
      strcpy (p, t2);
      strcat (p, t);
      free (t);
   }
   return s;
}
Вероника99 вне форума Ответить с цитированием
Старый 19.12.2017, 22:08   #2
Вероника99
Форумчанин
 
Регистрация: 15.12.2013
Сообщений: 414
По умолчанию

Не подскажите?
Вероника99 вне форума Ответить с цитированием
Старый 19.12.2017, 22:37   #3
p51x
Старожил
 
Регистрация: 15.02.2010
Сообщений: 15,695
По умолчанию

А что подсказывать то? У вас лежат в ряд несколько дестких кубиков, вы хотите заменить два из них на три. На сколько в итоге изменится количество кубиков (длина ряда)?

Код:
s = (char*)realloc(s, strlen(s)*sizeof(char)+l); //проблема здесь
Зачем это тут?

Код:
      t = strdup (p + strlen (t1) );
      memset (p, 0, sizeof(p) );
Зачем вы копируете остаток в другую строку? Зачем нулите?

Код:
strcpy (p, t2);
Вы понимаете, что р это указатель на часть старой сторки и после реаллок она может уехать?

По факту вам надо реаллок на +разницу в размере слов и сдвиг элементов. Хотя можно топорно: создаем новую строку, и три strcpy.
p51x вне форума Ответить с цитированием
Старый 20.12.2017, 00:42   #4
Вероника99
Форумчанин
 
Регистрация: 15.12.2013
Сообщений: 414
По умолчанию

Вроде бы исправила:
Код:
char *del (char *s, char *t1, char *t2) //
{
    char *result;
    int i, cnt = 0;
    int newWlen = strlen(t2);
    int oldWlen = strlen(t1);
     t1 = strcat( t1," ");
 
    for (i = 0; s[i] != '\0'; i++)
    {
        if (strstr(&s[i], t1) == &s[i])
        {
            cnt++;
 
    
            i += oldWlen - 1;
        }
    }
 
    result = (char *)malloc(i + cnt * (newWlen - oldWlen) + 1);
 
    i = 0;
    while (*s)
    {
     
        if ((strstr(s,t1 ) == s))
        {
            strcpy(&result[i], t2);
            i += newWlen;
            s += oldWlen;
        }
        else
            result[i++] = *s++;
    }
 
    result[i] = '\0';
 
   
   return result;
}
Теперь волнует еще одна проблема:входной файл содержит код программы. Как сделать так,чтобы при замене например i на j, с этим еще не менялись идентификаторы содержащие введенное i. Сейчас например есть ввожу то же i, слово printf меняется на prjntf. Как вариант сделала:
Код:
 t1 = strcat( t1," ");
но он не подходит на все случаи, например: a[i] не поменяет. Как организовать вот такое условие?
Вероника99 вне форума Ответить с цитированием
Старый 20.12.2017, 18:53   #5
New man
Форумчанин
 
Регистрация: 24.01.2011
Сообщений: 774
По умолчанию

Делить текст на слова, проверять на соответствие слова.

Только такое лучше писать всё же с помощью std::string хотя бы, а не char*.
a.k.a. Angelicos Phosphoros
Мой сайт
New man вне форума Ответить с цитированием
Старый 20.12.2017, 19:38   #6
Croessmah
Вредный кошак
Участник клуба
 
Аватар для Croessmah
 
Регистрация: 14.10.2012
Сообщений: 1,159
По умолчанию

Чтение строки с перераспределением буфера:
Код:
//-----------------------------------------------------------------------
//----------------------read_string_and_allocate-------------------------
//-----------------------------------------------------------------------
//Чтение строки произвольной длины из потока ввода
char * read_string_and_allocate ()
{
    int buffer_size = 64 ;//Размер буфера для чтения
    int buffer_size_divizer = 1 ; //Делитель для размера буфера. Изначально равен 1, далее станет понятно почему
    int offset_in_buffer = 0 ; //Смещение в буфере изначально равно нулю
    int length ;
    char * buffer = (char*)malloc ( buffer_size ) ; //Выделяем память под буфер
 
    if ( buffer == NULL ) //Если не удалось выделить, то
    {
        return NULL ; //Возвращаем ноль
    }
    buffer[0] = '\0' ;
    //Цикл до тех пор, пока не считаем всю строку целиком в буфер
    while ( 1 )
    {
        //Считываем строку из потока ввода
        //Причем считываем в буфер, со смещением равным offset_in_buffer
        //В качестве размера буфера передаем отношение размера буфера к делителю(buffer_size_divizer)
        if ( fgets( buffer + offset_in_buffer , buffer_size/buffer_size_divizer , stdin ) == NULL )
        {
            //Если нарвались на ошибку чтения, то выводим сообщение об ошибке
            printf ("\nRead error. Please, try again\n") ;
            fflush(stdout) ;//сбрасываем поток вывода
            fscanf ( stdin , "%*[^\n]" ) ; //Считываем символы, оставшиеся в потоке ввода
            free (buffer) ;//Освобождаем память, занятую буфером
            return NULL ; //Возвращаем ноль
        }
        else //Если прочитали успешно, то
        {
            //Вычисляем размер считанной строки (не считая '\0') и не считая ранее считанных символов (это контролируется смещением)
            length = strlen (buffer+offset_in_buffer) ;
            if ( buffer[length-1+offset_in_buffer] != '\n' ) //Если последний символ в строке (опять же, смещение контролирует начало отсчета, чтобы не считать уже считанные ранее символы) не равен '\n' ,
            //значит считали еще не все символы из потока
            {
                //Увеличиваем размер буфера равным в два раза больше текущего
                buffer_size *= 2 ;
                char * buffer_temp = buffer ;//Сохраняем указатель на буфер, чтобы в случае ошибки освободить память
                //Перевыделяем память нового размера
                //realloc сам скопирует старые даные в новую память
                buffer = (char*)realloc ( buffer , buffer_size ) ;
                if ( buffer == NULL ) //Если память выделить не удалось, то
                {
                    free ( buffer_temp ) ; //Освобождаем память
                    return NULL ; //вернем 0
                }
                //Теперь у нас доступна только половина буфера
                //ведь в первой половине буфера у нас находятся символы
                //уже считанные ранее, поэтому
 
                //К текущему смещению прибавляем длину строки, это
                //позволит потом считывать строку дальше в буфер со смещением, не задевая уже считанные символы
                offset_in_buffer += length ;
                //Устанавливаем делитель для размера буфера
                //это укажет, что теперь нам доступен не весь размер буфера, а лишь половина
                buffer_size_divizer = 2 ;
                //в результате это приведет к чтению только во вторую половину буфера без переполнения
            }
            else //Если же последний считанный символ равен '\n', то
            {
 
                buffer[length-1+offset_in_buffer] = '\0' ; //Заменяем символ конца строки на символ '\0'
                break ;//и выходим из цикла
            }
        }
    }
    return buffer ; //Возвращаем указатель на буфер со строкой
}
Croessmah вне форума Ответить с цитированием
Ответ


Купить рекламу на форуме - 42 тыс руб за месяц

Опции темы Поиск в этой теме
Поиск в этой теме:

Расширенный поиск


Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
выделение памяти в Си Артэс Общие вопросы C/C++ 2 12.09.2012 10:57
Выделение памяти Dady 1992 Общие вопросы C/C++ 2 26.06.2012 18:45
Распределение памяти. Динамическое выделение памяти с++ Tolian92 Помощь студентам 8 14.05.2012 21:44
Выделение памяти в С++ Dj-IIyIIc Общие вопросы C/C++ 4 18.10.2010 14:39
До выделение памяти MAKTE Общие вопросы C/C++ 4 20.05.2008 21:34