Dodanie znaku do stringa

Dodanie znaku do stringa
FN
  • Rejestracja:prawie 9 lat
  • Ostatnio:około 5 lat
  • Postów:38
0

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

Kopiuj
#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ęć.

edytowany 1x, ostatnio: kq
AK
Dlaczego sygnujesz to C++? To zwykle C ze streamem zamiast FILE
Delor
  • Rejestracja:ponad 6 lat
  • Ostatnio:około 2 lata
1

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

Kopiuj
for(j=0;j<(rozmiar&&zrodlo[i]);j++){
FN
  • Rejestracja:prawie 9 lat
  • Ostatnio:około 5 lat
  • Postów:38
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ął.

Delor
  • Rejestracja:ponad 6 lat
  • Ostatnio:około 2 lata
0
Kopiuj
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.

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

Przy niezerowych rozmiar i zrodlo[i] otrzymasz

Kopiuj
j<(true)

czyli

Kopiuj
j<1

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

edytowany 1x, ostatnio: Delor
FN
  • Rejestracja:prawie 9 lat
  • Ostatnio:około 5 lat
  • Postów:38
0

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

Delor
  • Rejestracja:ponad 6 lat
  • Ostatnio:około 2 lata
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ęć?

edytowany 1x, ostatnio: Delor
Delor
  • Rejestracja:ponad 6 lat
  • Ostatnio:około 2 lata
0
Kopiuj
(j < rozmiar) && zrodlo[i]

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

edytowany 1x, ostatnio: Delor
FN
  • Rejestracja:prawie 9 lat
  • Ostatnio:około 5 lat
  • Postów:38
0

Nic to nie daje.

Delor
  • Rejestracja:ponad 6 lat
  • Ostatnio:około 2 lata
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.

FN
  • Rejestracja:prawie 9 lat
  • Ostatnio:około 5 lat
  • Postów:38
0
Kopiuj
==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.

MarekR22
Moderator C/C++
  • Rejestracja:ponad 17 lat
  • Ostatnio:około 2 godziny
0

https://wandbox.org/permlink/G8jVQfe9zp0aiDWs

Kopiuj
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;
}

Jeśli chcesz pomocy, NIE pisz na priva, ale zadaj dobre pytanie na forum.
edytowany 2x, ostatnio: MarekR22
FN
  • Rejestracja:prawie 9 lat
  • Ostatnio:około 5 lat
  • Postów:38
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ć.

MarekR22
nie kodź w stylu C, ale użyj C++, czyli std::string. Nie będziesz musiał sam zarządzać pamięcią.
FN
Mam taki wymóg to jest na zajęcia
MarekR22
tak się domyślałem. Szczerze dałem taki kod celowo. Taki gotowiec wymagający myślenia. Jak poprawisz dosłownie parę linijek, będzie spełniać wymagania na zajęcia.
AK
  • Rejestracja:prawie 7 lat
  • Ostatnio:około 2 miesiące
  • Postów:3561
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


Bo C to najlepszy język, każdy uczeń ci to powie
tajny_agent
  • Rejestracja:ponad 11 lat
  • Ostatnio:ponad rok
  • Postów:1340
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.


"I love C++. It's the best language in the world right now for me to write the code that i need and want to write"
~ Herb Sutter

Zarejestruj się i dołącz do największej społeczności programistów w Polsce.

Otrzymaj wsparcie, dziel się wiedzą i rozwijaj swoje umiejętności z najlepszymi.