Wypisanie liczb w odwrotnej kolejności cyfr

0

Chciałbym napisać dalszy część kodu która odwróci liczby do 5000 a na razie napisałem do 1000 czy ma ktoś pomysł jakbym mógł to dalej napisać bo zatrzymałem się w miejscu?

#include <iostream>
#include <fstream>
#include<string.h>
#include<windows.h>

using namespace std;
int liczba;

int zamien(int liczba)
{
    if (liczba<10) return liczba;
    if (liczba<100) return liczba/10+(liczba%10)*10;
    if (liczba<1000) return liczba%10*100+liczba/100+((liczba/10)%10)*10;
}


int pierwsza(int liczbaDoSprawdzenia)
{
    int dzielnik=liczbaDoSprawdzenia/2;
    while ((liczbaDoSprawdzenia%dzielnik)!=0) dzielnik--;
    return dzielnik;
}



int main()
{
    fstream plik,plik2;
    plik.open("c:/x/2/liczby_przyklad.txt");

cout <<zamien(5)<<endl;
cout <<zamien(7)<<endl;
cout <<zamien(15)<<endl;
cout <<zamien(512)<<endl;
cout <<zamien(723)<<endl;
cout <<zamien(99)<<endl;


/*while (!plik.eof())
{
        plik>>liczba;
        if (pierwsza(liczba)==1) cout<<liczba<<endl;
}*/
    plik.close();
}
4

@Kaczorek:

A jak brzmi zadanie pierwotne? Jakoś nie stykam się od "kilku lat" z maturami.

Tak jak próbuję zgadnąć o co chodzi, to granica 5000 mi sie jawi jako sztuczna, bo następna jest 10000.
Jak sie ma zagadnienie l.pierwszej do odwracania w tym zadaniu, bo dla mnie nie da się powiedzieć w kategoriach dobrze / źle, dopóki nie wyjaśnisz

Kod na forum prezentuj jako MVP, zminimalizowany tylko do tego, co pokaże problem. Np otwarcie strima do niczego chyba nie potrzebne, tylko zaciemnia i zniechęca do próbowania

2

Jak rozumiem chodzi o wypisanie cyfr liczby w odwrotnej kolejności. Można to zrobić tak. Rozwiązanie na pałę, ale po co kombinować?

#include<stdio.h>

typedef unsigned int uint;

uint invert (uint n) {
    char buff[20];
    int len = sprintf(buff, "%u", n);
    for(int i = 0; i < len/2; i++) {
        char tmp = buff[len-i-1];
        buff[len-i-1] = buff[i];
        buff[i] = tmp;
    }
    sscanf(buff, "%u", &n);
    return n;
}

int main() {
    uint n;
    while(scanf("%u", &n) == 1) {
        printf("%u\n", invert(n));
    }
}
2
#include <iostream>
#include <string>
using namespace std;

int main()
{
	string str;
	for(unsigned value;/*file*/cin>>value;cout<<string(str.rbegin(),str.rend())<<endl) str=to_string(value);
	return 0;
}
1

@_13th_Dragon: Spoko rozwiązanie, jednak odwróci wszystko, również znaki, które nie są liczbami, myślę, że jest mniej czytelne, przynajmniej dla mnie. Poza tym, jak dla mnie, należy oddzielić faktyczną część zadania (funkcja invert w moim przykładzie) od części pozwalającej to testować.

2
elwis napisał(a):

@_13th_Dragon: Spoko rozwiązanie, jednak odwróci wszystko, również znaki, które nie są liczbami,

Jakim cudem? unsigned value; cin>>value;

elwis napisał(a):

myślę, że jest mniej czytelne, przynajmniej dla mnie.

Piszesz w C kiedy w tagu jak wół stoi C++, więc poducz się trochę C++ i będziesz umieć przeczytać jednego for'a

elwis napisał(a):

Poza tym, jak dla mnie, należy oddzielić faktyczną część zadania (funkcja invert w moim przykładzie) od części pozwalającej to testować.

Jest oddzielona jak najbardziej: string(str.rbegin(),str.rend()) - zamiast twego invert()

1

@_13th_Dragon: Widzisz, nawet przeoczyłem to, że wczytujesz do uinta. Rzeczywiście oddzieli.
Po co mam pisac w C++ skoro mogę napisać w C? Zamień stdio.h na cstdio i styknie. Wybrałem takie rozwiązanie, bo bardziej mi odpowiada, lepiej pokazuje ideę, która stoi za programem. Moim zdaniem takie rozwiązanie jest prostsze do zrozumienia, STL to dość złożona sprawa, łatwo o błąd czy niezrozumienie, zwłaszcza dla początkującego.
Jeśli chodzi o wątpliwości związane z wydajnością (w komentarzu powyżej) to myslę, że nie ma co dzielić włosa na czworo. Nie licząc bardzo szczególnych przypadków, wyrażenie idei jest znacznie ważniejsze niż optymalizacja, tym bardziej, że większość z nich kompilator zrobi za nas. Również, należy uważać na przedwczesną optymalizację, to duży błąd!
Co do samej czytelności to już niech każdy sam sobie oceni, który kawałek kodu łatwiej mu przeczytać.

0
elwis napisał(a):

@_13th_Dragon: Widzisz, nawet przeoczyłem to, że wczytujesz do uinta. Rzeczywiście oddzieli.
Po co mam pisac w C++ skoro mogę napisać w C? Zamień stdio.h na cstdio i styknie. Wybrałem takie rozwiązanie, bo bardziej mi odpowiada, lepiej pokazuje ideę, która stoi za programem. Moim zdaniem takie rozwiązanie jest prostsze do zrozumienia, STL to dość złożona sprawa, łatwo o błąd czy niezrozumienie, zwłaszcza dla początkującego.
Jeśli chodzi o wątpliwości związane z wydajnością (w komentarzu powyżej) to myslę, że nie ma co dzielić włosa na czworo. Nie licząc bardzo szczególnych przypadków, wyrażenie idei jest znacznie ważniejsze niż optymalizacja, tym bardziej, że większość z nich kompilator zrobi za nas. Również, należy uważać na przedwczesną optymalizację, to duży błąd!
Co do samej czytelności to już niech każdy sam sobie oceni, który kawałek kodu łatwiej mu przeczytać.

Kolejny kto nie rozumie cytatu Knuth'a w związku z czym uznaje że liczenie polowy wartości jeden raz zamiast na każdym kroku pętli to optymalizacja, nie, to zwyczajne zmniejszenie czytelności, bo każdy normalny programista zaczyna szukać gdzie w pętli zmieniasz to len skoro połowę liczysz na każdym kroku, zaś ciężko się szuka czarnego kota w czarnym pokoju zwłaszcza kiedy go tam nie ma, zaś zabiera to czas więc zmniejsza czytelność kodu. Musisz zrozumieć że czytelność = odwrotność czasu który trzeba poświęcić aby ten kod przeczytać. Więc jak dla ciebie przeczytanie 15 wierszy jest szybsze niż 2 wierszy to oznacza nie słabą czytelność zaś zwykłą ignorancję.

0

@_13th_Dragon: Kto to jest normalny programista? Nigdy nie spotkałem. Ludzie tak bardzo różnie rozumieją programowanie… akurat len/2 wynika stąd, że potrzebuję iterować tablicę tylko do połowy, bo inaczej druga połowa odwróci działanie pierwszej połowy. Naprawdę uważasz, że należy stworzyć zmienną half_of_len albo middle, w sumie mogłoby i być middle, tylko, że to aż linia więcej, a zgodnie z twoją dziwną logiką, kod krótszy to kod prostszy i łatwiejszy do przeczytania. Nie zawsze tak jest. Jak dla mnie, ma to niewielkie znaczenie. Może i być middle zamiast len/2.

0
elwis napisał(a):

@_13th_Dragon: Kto to jest normalny programista? Nigdy nie spotkałem. Ludzie tak bardzo różnie rozumieją programowanie… akurat len/2 wynika stąd, że potrzebuję iterować tablicę tylko do połowy, bo inaczej druga połowa odwróci działanie pierwszej połowy. Naprawdę uważasz, że należy stworzyć zmienną half_of_len albo middle, w sumie mogłoby i być middle, tylko, że to aż linia więcej, a zgodnie z twoją dziwną logiką, kod krótszy to kod prostszy i łatwiejszy do przeczytania. Nie zawsze tak jest. Jak dla mnie, ma to niewielkie znaczenie. Może i być middle zamiast len/2.

Normalny to ten który przynajmniej:

  • nie zniekształca sensownych zasad
  • nie pisze nadmiarowego kodu
  • nie nagina pojęć pod swoją ignorancję

Co do dodatkowego wiersza a zmiennej middle - dodatkowy wiersz wcale nie jest potrzebny:

    for(int i = 0, middle=len/2; i < middle; i++)

Ten kod co napisałeś znacznie lepiej wygląda w postaci:

for(int i=0,k=len-1;i<k;++i,--k)
{
        char temp=buff[i];
        buff[i]=buff[k];
        buff[k]=temp;
}

Zauważ że nie ma żadnych dzieleni na każdym kroku, zaś zamiast 4-ch operacji odejmowania masz jedną dekrementacje.
Można to również zapisać:

for(int i=0,k=len-1;i<k;++i,--k) buff[i]^=buff[k],buff[k]^=buff[i],buff[i]^=buff[k];

No ale oczywiście aby to było czytelne to czytający musi rozumieć co to za "znak potęgi" i co tu robi (właściwie podstawy z pierwszych stron każdego kursu).

2
_13th_Dragon napisał(a):

Ten kod co napisałeś znacznie lepiej wygląda w postaci:

for(int i=0,k=len-1;i<k;++i,--k)
{
        char temp=buff[i];
        buff[i]=buff[k];
        buff[k]=temp;
}

Niby czemu "lepiej wygląda"? Jak na moje to fakt, że odwracasz do połowy jest bezsensownie ukryty tutaj.

Co do tego, że masz len/2 w warunku, to czy uważasz, że kompilator też nie będzie potrafił zamienić tego w len >> 1?

A jak już mamy się kłócić co byłoby czytelniejsze, to mamy std::swap zamiast pisać to z palca i się zastanawiać czy zrobiliśmy w dobrej kolejności indeksy albo nie rypnęliśmy babola z brakiem warunku jak w Twoim kodzie. Dodatkowo CPU umieją już w registry renaming i takie "wynalazki" tylko szkodzą w kodzie zamiast pomagać. Biedni Twoi studenci jak im dajesz taki bezsensowny wyrzyg zbędnego bełkotu jako kod do analizy.

Oczywiście "uproszczony" kod wg Smoka (z poprawką na babola jakiego zrobił) się kompiluje gorzej - https://godbolt.org/z/8f5MdTaYG

0

@_13th_Dragon: To rozwiązanie z k i i ma w sobie pewną elegancję, choć jak na mój gust wymaga złamania linii kilka razy. Się łatwiej taki kod czyta. Natomiast pomysł z XORem jest ciekawy, ale za dużo programowałem w językach wyższego poziomu, żeby pisać taki kod. Doceniam C za prostotę, kiedy muszę napisać coś bliższego sprzętowi i doceniam, że w C99 można pisać ładny niskopoziomowy kod, zamiast uprawiać programistyczny sport lat 90tych i wcześniej. Tylko nie mam ochoty tak bardzo odwracać swojej uwagi od właściwych problemów. Jak odpowiada ci taki kod to szanuję to. Każdy ma swój gust.

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