Pobrany łańcuch wypisywany wspak z krzaczkami

0

Witam, mam pewien problem z małym programem, który pobiera łańcuch i wyświetla go wspak. Wszystko jest niby ok, ale gdy łańcuch przekroczy 11 znaków to oprócz wypisania go wspak wyskakują jeszcze jakieś krzaczki. Mało tego, gdy dodam printfa wypisującego ilość znaków pobranego łańcucha to łańcuch ten wspak ma zawsze jakieś krzaczki. Ja nie potrafię tu zauważyć żadnej zależności, byłbym wdzięczny za zerknięcie na to trzeźwym okiem.

#include<stdio.h>
#include<string.h>

int main()
{
        char slowo [30];
        int dl, i, k;
        scanf("%s", slowo);
        dl = strlen(slowo);
        printf("Dlugosc podanego lancucha to %d znakow.\n", dl);
        char wspak[dl+1];
        for (i=0, k=dl-1; k>=0; i++, k--)
                wspak[i] = slowo[k];
        printf("%s\n", wspak);
        return 0;
}

Przykładowo:

wspak
Dlugosc podanego lancucha to 5 znakow.
kapsw=�>���t�
 
1

Witaj. Spróbuj może zastąpić linijkę:

char wspak[dl+1];
kodem:
char wspak[30];

Działa?

(Nie bardzo możesz utworzyć statyczną tablicę na podstawie dynamicznej wartości)

PS. To chyba tylko częściowo rozwiązuje problem. Sprawdzałem tylko kod dla krótkich tekstów, ale dla dłuższych nadal są krzaczki.

EDIT:

Tutaj mam prowizoryczne rozwiązanie (bo sam nie jestem jakimś znawcą C, wręcz przeciwnie ;) ). Spróbuj wyświetlać odwrócony tekst znak po znaku, czyli:

#include <stdio.h>

int main()
{
        char slowo[30];
        int dl, i, k;
        scanf("%s", slowo);
        dl = strlen(slowo);
        printf("Dlugosc podanego lancucha to %d znakow.\n", dl);
        char wspak[30];
        for (i=0, k=dl-1; i!=dl; i++, k--)
        {
            wspak[i] = slowo[k];
            printf("%c", wspak[i]);
        }

        return 0;
}

Wydaje mi się, że przy wyświetlaniu całego ciągu znaków, wyświetlany zostaje także jakiś dodatkowy znak, który został wrzucony na sam koniec odwróconego tekstu.
W przypadku, gdy ostatni element wyrazu wspak stanie się NULLem, nie ma już krzaczków:

#include <stdio.h>

int main()
{
        char slowo[30];
        int dl, i, k;
        scanf("%s", slowo);
        dl = strlen(slowo);
        printf("Dlugosc podanego lancucha to %d znakow.\n", dl);
        char wspak[30];
        for (i=0, k=dl-1; i!=dl; i++, k--)
        {
            wspak[i] = slowo[k];
        }
        wspak[dl]=NULL;
        printf("%s", wspak);

        return 0;
}
0

Pamietaj ze zawsze wypisanie jest do napotkania znaku "\0" lub NULL. Z tego wzgledu zazwyczaj okresla sie dlugosc tablicy + 1 znak na znak "zera". Rzecz kolejna NIE WOLNO tworzyc tablic w taki sposob jak ty to zrobiles
char tab[dl+1];
Jest to blad, bo moze nastapic przez to wyciek pamieci i nie jest do konca sprecyzowane czy nie poruszasz sie poza obszarem pamieci przydzielonym aplikacji. Jesli chcesz rezerwowac pamiec na tablice dynamiczna w c robi sie to chyba za pomoca malloc.

Wypisywanie mozna latwo przeprowadzic przez rekurencje i bardzo dobrze sie to sprawdza zamiast tego rozwiazania. U ciebie wystarczy dodac poza ostatni wczytany znak znak \0 recznie przypisac, no i zmienic tablice na dynamiczna naprawde a potem pamietac o zwolnieniu pamieci.


#include <iostream>
#include <cstdlib>
#include <ctime>

using namespace std;

void wspak(string a)
{
    int len=a.length();
    while(len--)
    {
        cout << a[len];
    }
}

void rek(string a,int length)
{
    if(length>=0)
    {
        cout << a[length];
        rek(a,length-1);
    }
}

int main()
{
    string slowo;
    cin >> slowo;
    wspak(slowo);
    cout << endl;
    rek(slowo,slowo.length()-1);
    cout << endl;
    system("pause");
    return 0;
}
0

@Krycho:

  1. mylisz się, można tak deklarować tablice, ale jest to specyficzne dla kompilatora - ot takie jego rozszerzenie, nie każdy na to pozwala.
  2. wypisywanie napisu wspak przy użyciu rekurencji? To jest jakaś masakra, spróbuj tak wypisać ciąg kilku tysięcy znaków. Już nie wspominam nawet o wydajności i sensie takiego rozwiązania...
0
byku_guzio napisał(a)

@Krycho:

  1. mylisz się, można tak deklarować tablice, ale jest to specyficzne dla kompilatora - ot takie jego rozszerzenie, nie każdy na to pozwala.
  2. wypisywanie napisu wspak przy użyciu rekurencji? To jest jakaś masakra, spróbuj tak wypisać ciąg kilku tysięcy znaków. Już nie wspominam nawet o wydajności i sensie takiego rozwiązania...

Moze wolno, przepraszam jesli wprowadzam w blad. Nas ucza c++ i tam za probe deklaracji tablicy w taki sposob Od razu by bylo 2 bez patrzenia na kod w ogole. Jesli w c jest to mozliwe to zwracam honor.

Wiem ze rekurencja nie jest dobrym sposobem, ot tak podalem mu, zeby wiedzial jak to wyglada i dziala. Podalem tez druga wersje duzo szybsza w przypadku dluzszych ciagow wyrazow.

0

Ta funkcja mogłąby np. wyglądać tak:

void odwroc(char *tekst) {
    int len = 0;
    int i;
    /* Sprawdza wielkość tablicy */
    for (i = 0; *(tekst + i) != '\0'; i++) len++;
    printf("Dlugosc tekstu to: %d\n", len);
    /* OK, mamy już długość tablicy, więc wypisujemy tablicę w odwrotnej kolejności */
    for (i = len -1; i >= 0; i--) printf("%c", *(tekst + i));
}

char wspak[dl+1]; - tak nie można deklarować tablicy, wyrażenie w [] musi być stałą - tak jest w standardzie, czasami kompilator pozwala na takie rzeczy, ale u mnie na studiach byłoby to uznane za błąd.
Jak już chcesz dynamicznie tworzyć tablicę to spróbuj tak:

 
char *wspak; /* Wskaźnik */
wspak = (char*) malloc (sizeof(char) * (dl + 1)); /* Teraz masz tablicę wspak o rozmiarze dl + 1 */

A tej pętli to w ogóle nie możesz napisać tak:

for(i=dl-1; i >=0; i--)

Skoro masz już rozmiar tekstu?

0

Dziękuje za odpowiedzi. Mój problem głównie polegał na tym, że nie wziąłem pod uwagę faktu, że przy wpisywaniu łańcucha wspak do nowej tablicy jest to już tablica znaków, a nie łańcuch i co za tym idzie nie pojawia się tam już automatycznie znak '\0', tylko tyle. Takie małe zaćmienie.
Co do tej deklaracji

char wspak[dl+1];

to sobie muszę jeszcze poczytać, co wolno a czego nie, jakie są czego konsekwencje. Mam po prostu styczność z C (a nawet ogólnie z jakimkolwiek językiem) trochę ponad 3 miechy, a uczyć tak na dobrą sprawę zacząłem się dopiero teraz, nie przerabiałem jeszcze szczegółowo tablic.
@byku_guzio, nie wiń od razu ludzi. Nie wiem jakiego masz wykładowcę (o ile masz), ale mój na pierwszym roku sporą część czasu poświęca na rozwiązywanie zagadnień czysto matematycznych. Na zajęciach tworzy algorytmy, zakładając, że samo C mamy opanowane perfekcyjnie i wypomina nam braki w edukacji. Także nie wszystko jest od razu czarne lub białe ;)

0

Ale ja nie winię wykładowcy, po prostu nie koniecznie trzeba zawsze bezkrytycznie podchodzić do tego co przedstawiają. O to chodzi, żeby też samemu szukać informacji, wiedzy, a wykładowca jak to człowiek - ma prawo czegoś nie wiedzieć, gdzieś się pomylić, mieć własne zdanie i poglądy na dany temat. Ważne, żeby umiejętnie korzystać z tego co przekazuje i rozszerzać sobie wiedzę.

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