как изменить под динамический массив?

358
09 февраля 2017, 00:46
using namespace std;
void ProbelVoid(char *str)
{
    char *str1=new char [512];
    int  i = 0;
    for (char* a = str, *b = str1; *a; ++a, ++b, i++)
    {
        for (; *a == ' ' && *(a + 1) == ' '; a++);
        *b = *a;
    }
    str1[i] = '\0';
    strcpy_s(str, strlen(str1), str1);
}
int main()
{

    ifstream in("1.txt");
    if (!in)
    {
        cout << "Ошибка: не могу открыть входной файл ";
        system("pause");
        return-1;
    }
    char *str=new char[512];
    in.getline(str, 512);
    cout << "Изначальная строка\n" << str;
    ProbelVoid(str);
    cout << "\n\nИзменённая строка\n" << str;
    ofstream out("output.txt");
    out << str;
    cout << endl;     
    out.close();
    in.close();
    system("pause");
    return 0;
}

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

Answer 1

В С++ уже имеется класс, который инкапсулирует в себе динамический массив символов. Это класс std::string.

Для чтения из потока строк можно использовать стандартную функцию std::getline.

Также в C++ имеется стандартный алгоритм std::unique который позволяет исключить из строки повторяющиеся символы.

Ниже приведена демонстрационная программа, которая показывает, как использовать указанные средства. В этой программе вместо файла для простоты используется строковый поток, а вывод осуществляется также не в файл, а на консоль. Программу не сложно модифицировать, заменив строковый поток и консоль на входной и выходной файлы.

#include <iostream>
#include <algorithm>
#include <sstream>
int main() 
{
    std::istringstream is( "Hello,      World!\nI   am learning   C++" );
    std::string s;
    while ( std::getline( is, s ) && !s.empty() )
    {
        auto it = std::unique( s.begin(), s.end(),
                               []( char c1, char c2 )
                               {
                                   return ( c1 == ' ' || c1 == '\t' ) && ( c1 == c2 );
                               });
        s.erase( it, s.end() );                            
        std::cout << s << std::endl;                     
    }
    return 0;
}

Вывод на консоль

Hello, World!
I am learning C++

Как видно из вывода, повторяющиеся знаки пробелов исключены из входной строки.

Если входной файл может содержать пустые строки, то второе условие из цикла while следует убрать. Например,

while ( std::getline( is, s ) )

Но можно это условие включить для записи результирующих строк в выходной файл, то есть можно не писать пустые строки в выходной файл. Например,

    if ( !s.empty() ) std::cout << s << std::endl;
Answer 2

А почему бы вам не решить вашу задачу проще и короче?

int main(int argc, const char * argv[])
{
    char cur, last = 0;
    while(cin.get(cur))
    {
        if (isspace(cur) && isspace(last)) continue;
        cout << (last = cur);
    }
}

Из всего ввода выбрасываются дублируемые пробельные символы:

qwtdcas jahsghj   hbdjhbhjd      dyuygd yeduy  tyuyd
qwtdcas jahsghj hbdjhbhjd dyuygd yeduy tyuyd
^Z

Длина строки совершенно неважна :)

Если нужно ограничиться одной строкой - после

        cout << (last = cur);

добавьте

        if (cur == '\n') break;
READ ALSO
Не коректное чтение значения из std::cin в std::string

Не коректное чтение значения из std::cin в std::string

При считывании потока из командной строки в переменную с помощью std::getline не дает ввести данные, перескакиваетКак можно считать строку с пробелами...

301
Найти стороны треугольника [требует правки]

Найти стороны треугольника [требует правки]

Даётся n и массив с размером nВсе числа в размешку

331
Как отдебажить большой sql-запрос?

Как отдебажить большой sql-запрос?

Есть большой sql-запрос (почти на 1500 строк), доставшийся по наследству, но не функционирующий правильноНужно отдебажить

344