Dodanie znaku do stringa

0

Mam napisać gotową funkcję która doda znak podany do stringa co 3 znak.
Mój kod

#include <iostream>
#include <cstring>
#include <cmath>
using namespace std;
char* wstaw(const char* zrodlo, char symbol)
{
    int n = strlen(zrodlo);
    int rozmiar = n + floor(n / 3) + 1;
    int i, j = 0;
    char* t = new char[rozmiar];
    for (j = 0; j < (rozmiar && zrodlo[i]); j++) {
        if (j % 3 == 0) {
            t[j] = symbol;
        }
        else {
            t[j] = zrodlo[i];
            i++;
        }
    }
    t[j] = '\0';
    return t;
}
int main(int argc, char* argv[])
{
    char* a = NULL;
    if (argc != 3) {
        cerr << "Nieprawidlowa ilosc przekazanych argumentow(3)!" << endl;
        cout << "Wymagane argumenty to:./nazwa,napis,symbol" << endl;
        return -1;
    }
    else {
        a = wstaw(argv[1], argv[2][0]);
        cout << a;
        if (a)
            delete[] a;
        a = 0;
    }
    return 0;
}

Program się kompiluje,ale nie działa przy uruchomieniu,coś mi się wydaje że jest z tymi rozmiarami nie rozumiem tego zbyt dobrze.
Mógłby mi ktoś wytłumaczyć dlaczego int rozmiar ma taki wzór bo akurat ten fragment jest przepisany z zajęć.

1

Jak bym postawił na ten warunek w pętli:

for(j=0;j<(rozmiar&&zrodlo[i]);j++){
0

Właśnie też coś tak sądzę,ale nie wiem właśnie jak to zrobić ani ten rozmiar wgl skąd on się wziął.

0
int rozmiar=n+floor(n/3)+1;

rozmiar = długość źródła + długość źródła/3 z obcięciem części ułamkowej + 1 (na \0).
Możliwe że jest o 1 za mały.

j<(rozmiar&&zrodlo[i])

Przy niezerowych rozmiar i zrodlo[i] otrzymasz

j<(true)

czyli

j<1

Prawdopodobnie nawiasy dałeś w niewłaściwych miejscach.

0

Nadal nie czaję co poprawić.
I dlaczego dzielimy zródło na 3?

1

I dlaczego dzielimy zródło na 3?

bo:

Mam napisać gotową funkcję która doda znak podany do stringa co 3 znak.

Co do:

Nadal nie czaję co poprawić.

Co chciałeś sprawdzić tym warunkiem? Ty go napisałeś czy też przepisany z zajęć?

0
(j < rozmiar) && zrodlo[i]

Jeżeli mamy miejsce w ciągu docelowym i (&&) ciąg źródłowy nie skończył się.

0

Nic to nie daje.

0

To debugger i analizujesz krok po kroku co się stało, jak się pozmieniały zmienne. Łatwiej zrozumieć i wyłapać ewentualne błędy.

0
==11695== Memcheck, a memory error detector
==11695== Copyright (C) 2002-2017, and GNU GPL'd, by Julian Seward et al.
==11695== Using Valgrind-3.13.0 and LibVEX; rerun with -h for copyright info
==11695== Command: ./3 Ala\ ma\ kota X
==11695== 
==11695== Use of uninitialised value of size 4
==11695==    at 0x1088BA: wstaw(char const*, char) (3.cpp:10)
==11695==    by 0x1089E4: main (3.cpp:31)
==11695== 
==11695== Invalid read of size 1
==11695==    at 0x1088BA: wstaw(char const*, char) (3.cpp:10)
==11695==    by 0x1089E4: main (3.cpp:31)
==11695==  Address 0xbe951d43 is not stack'd, malloc'd or (recently) free'd
==11695== 
==11695== 
==11695== Process terminating with default action of signal 11 (SIGSEGV)
==11695==  Access not within mapped region at address 0xBE951D43
==11695==    at 0x1088BA: wstaw(char const*, char) (3.cpp:10)
==11695==    by 0x1089E4: main (3.cpp:31)
==11695==  If you believe this happened as a result of a stack
==11695==  overflow in your program's main thread (unlikely but
==11695==  possible), you can try to increase the size of the
==11695==  main thread stack using the --main-stacksize= flag.
==11695==  The main thread stack size used in this run was 8388608.
==11695== 
==11695== HEAP SUMMARY:
==11695==     in use at exit: 16 bytes in 1 blocks
==11695==   total heap usage: 2 allocs, 1 frees, 18,960 bytes allocated
==11695== 
==11695== LEAK SUMMARY:
==11695==    definitely lost: 0 bytes in 0 blocks
==11695==    indirectly lost: 0 bytes in 0 blocks
==11695==      possibly lost: 0 bytes in 0 blocks
==11695==    still reachable: 16 bytes in 1 blocks
==11695==         suppressed: 0 bytes in 0 blocks
==11695== Reachable blocks (those to which a pointer was found) are not shown.
==11695== To see them, rerun with: --leak-check=full --show-leak-kinds=all
==11695== 
==11695== For counts of detected and suppressed errors, rerun with: -v
==11695== Use --track-origins=yes to see where uninitialised values come from
==11695== ERROR SUMMARY: 2 errors from 2 contexts (suppressed: 0 from 0)
Naruszenie ochrony pamięci (zrzut pamięci)


Błędy przy wywołaniu.

0

https://wandbox.org/permlink/G8jVQfe9zp0aiDWs

template<typename Input, typename Output, typename T>
Output copyWithPeriodicallyInserted(Input b, Input e, T v, size_t period, Output out)
{
    assert(period > 0);
    using diffType = typename std::iterator_traits<Input>::difference_type;
    if (std::distance(b, e) <= static_cast<diffType>(period)) return std::copy(b, e, out);

    size_t insertCount = (std::distance(b, e) - 1) / period;
    for (unsigned i = 0; i < insertCount; ++i) {
         out = std::copy(b, b + period, out);
         b += period;
         *out++ = v;
     }
    return std::copy(b, e, out);
}

std::string periodicallyInserted(const std::string &src, char ch, unsigned period)
{
    assert(period > 0);
    if (src.size() <= period) return src;

    std::string result;
    unsigned insertCount = (src.size() - 1) / period;
    result.reserve(src.size() + insertCount);

    copyWithPeriodicallyInserted(src.begin(), src.end(), ch, period, std::back_inserter(result));

    return result;
}
0

Nie chcę takiego kodu,bo nie mogę tworzyć żadnych templatów wiem,że to jest jakiś jeden mały błąd wystaczy go poprawić i będzie działać.

0

Dlaczego sygnujesz to C++? To zwykle C ze streamem zamiast FILE?

Praktyka alokowania w funkcji i zwalniania poza funkcją jest podatna na błedy. Użycie C++ std:string upraszcza ten temat radykalnie

0

@FrageN: Używasz niezainicjalizowanej zmiennej i.
Warunek j % 3 ==0 będzie spełniony również dla j == 0, czyli na samym początku. Dla wywołania wstaw("aaaaaaaaaaaaa", '1') dostaniesz 1aa1aa1aa...

"Osadź" pętle na indeksach tekstu wejściowego, będzie łatwiej.

1 użytkowników online, w tym zalogowanych: 0, gości: 1