Strona 1 z 2

[C++] program zamieniający tekst na pisany wielkimi literami

: 8 sie 2011, o 00:20
autor: diego_maradona

Kod: Zaznacz cały

// uppercase_letter.cpp : main project file.


#include "stdafx.h"
#include <iostream>
#include <cctype>

using namespace std;

int i;

void enter ( char str[] );
void toUppercase ( char str[] );
void print (char str[] );



int main()
{
    char text[999];
	

	cout<<"Program converts letters in your text to uppercase \n ";

	enter ( text );
	cout<<endl;
	toUppercase ( text );
	cout<<endl;
	print ( text );
	cout<<endl;




	cout<<endl;
	system("PAUSE");
}

void enter ( char str[] )
{
	for ( i= 0 ; i < 999 ; i++)
	{	cin >> str[i];
	 if (str[i]== '\n')
		break;
	}
}

void toUppercase ( char str[] )
{
	for ( i = 0 ; i < 999 ; i++)
		str[i] = static_cast<char>(toupper( str[i] ));
}

void print ( char str[] )
{
	for (i = 0 ; i < 999 ; i++)
		cout<< str[i] << endl;
}

po naciśnięciu klawisza enter program powinien wyświetlić wszystkie wpisane wcześniej litery jako WIELKIE.
Problem w tym , że tak nie jest , wygląda na to że warunek w if'ie jest zawsze prawdą . Jak rozgryźć tę instrukcję warunkową?

[C++] program zamieniający tekst na pisany wielkimi literami

: 8 sie 2011, o 10:57
autor: void_t
Powiem tak: piszesz na siłę w tym C++.
Niepotrzebnie IMO, ale proszę: tutaj jest kod (21 linii), który rozwiązuje to co tam próbowałeś zrobić w 58 liniach.

Kod: Zaznacz cały

#include <iostream>
#include <cstring>
#include <cstdio>

#define BUFSIZ 1024
#define to_upper(p) ((p >= 'a' && p <= 'z') ? (p & ~0x20) : p)

int main(int argc, char **argv)
{
	char buf[BUFSIZ];
	char *p;

	std::cout << "Program converts letters in your text to uppercase\n";
	
	memset(buf, 0, BUFSIZ);
	fgets(buf, BUFSIZ - 1, stdin);
	
	for (p = buf; *p; *p = to_upper(*p), p++);
	printf("%s\n", buf);
}
BTW, tak: tutaj też mamy ładną mieszankę funkcji C z C++.
PS. Makro to_upper robi dokładnie to samo co (chyba) funkcja toupper(), z tym, że teraz wiesz jak.

[C++] program zamieniający tekst na pisany wielkimi literami

: 8 sie 2011, o 11:09
autor: PMichalak
Myślę, że taki kod jest o wiele czytelniejszy.

Kod: Zaznacz cały

///Pawel Michalak
#include<iostream>
#include<algorithm>
using namespace std;

const char d = 'A' - 'a';

char toUpper(char c)
{
    if('a' <= c and c <= 'z') return c+d;
    else return c;
}

int main()
{
    string s;
    cin >> s;
    for(string::iterator i = s.begin(); i != s.end(); ++i)
        *i = toUpper(*i);
    cout << s;
    return 0;
}
albo taki:

Kod: Zaznacz cały

///Pawel Michalak
#include<iostream>
#include<algorithm>
using namespace std;

const char d = 'A' - 'a';

char toUpper(char c)
{
    if('a' <= c and c <= 'z') return c+d;
    else return c;
}

int main()
{
    string s;
    cin >> s;
    transform(s.begin(), s.end(), s.begin(), toUpper);
    cout << s;
    return 0;
}

[C++] program zamieniający tekst na pisany wielkimi literami

: 8 sie 2011, o 12:15
autor: void_t
Śmiem powątpiewać w czytelność podobnie jak w wydajność.

Kod: Zaznacz cały

const char d = 'A' - 'a';
Przecież to i tak zawsze wynosi 0x20.

Poza tym:

Kod: Zaznacz cały

char toUpper(char c)
Zakładając że korzystasz z gcc/MinGW <= 4.4 to nie będzie wymuszone na niej inline, w zwiazku z czym za każdym razem zobaczysz w kodzie wynikowym kosztowne 'call'.
Oczywiście w tym przypadku nie ma to znaczenia, bo input będzie i tak krótki. Nie ma jednak potrzeby prezentować takiego stylu programowania, bo jest on poprostu zły.

Dalej: kto jeszcze używa w instrukcjach warunkowych operatorów 'and', 'or', etc?

Kod: Zaznacz cały

string s;
String? Owszem. To jest akurat dobry pomysł, ale już ten iterator niekoniecznie.

No ale tego właśnie niestety uczy C++.

[C++] program zamieniający tekst na pisany wielkimi literami

: 8 sie 2011, o 16:57
autor: diego_maradona
Dzięki , ale nie pytałem o bardziej optymalne algorytmy , tylko o to, dlaczego funkcja if jest zawsze prawdziwa. Przespałem się z tym zadaniem, i zauważyłem że operator common input (cin ) pomija nie tylko spacje ale także wciśnięcia klawisza enter(i wszystkie inne "puste" znaki ).
Zamieniłem na cin.get i teraz if działa jak należy, ale to nie koniec moich zmartwień, niby program teraz spełnia swoją funkcję, ale skąd te dziwne znaki w konsoli? Zamieniłem jeszcze rozmiar tablicy text na 41, bo przy 999 jest totalny bałagan.


[C++] program zamieniający tekst na pisany wielkimi literami

: 8 sie 2011, o 17:13
autor: void_t
No temu, że nie wyzerowałeś pamięci, to że napisałeś

Kod: Zaznacz cały

char text[999];
nie znaczy, że w przestrzeni, która zostanie przydzielona tej tablicy jest pusto. Musisz taki bufor wyczyścić, używając chociażby instrukcji memset.

[C++] program zamieniający tekst na pisany wielkimi literami

: 8 sie 2011, o 17:58
autor: diego_maradona
Ok, pozbyłem się tego problemu na dwa sposoby

Pierwszy- liczenie znaków i ograniczenie przez tą liczbę powtórzeń pętli znajdującej się w funkcji print.

Kod: Zaznacz cały

#include "stdafx.h"
#include <iostream>
#include <cctype>

using namespace std;

int i,signs;


void enter ( char str[] );
void toUppercase ( char str[] );
void print (char str[] );



int main()
{
    char text[999];
	

	cout<<"Program converts letters in your text to uppercase \n ";

	enter ( text );
	cout<<endl;
	toUppercase ( text );
	cout<<endl;
	print ( text );
	cout<<endl;




	cout<<endl;
	system("PAUSE");
}

void enter ( char str[] )
{
	
	
	for ( i= 0 ; i < 999 ; i++)
	{	
		
		cin.get(str[i]);
	 if (str[i] == '\n')
		break;
	 signs++;
	}
}

void toUppercase ( char str[] )
{
	for ( i = 0 ; i < 999 ; i++)
		str[i] = static_cast<char>(toupper( str[i] ));
}

void print ( char str[] )
{
	for (i = 0 ; i < signs ; i++)
		cout<< str[i] ;
}
drugi- dodanie funkcji initialise

Kod: Zaznacz cały

// uppercase_letter.cpp : main project file.


#include "stdafx.h"
#include <iostream>
#include <cctype>

using namespace std;

int i;

void initialise (char str[]);
void enter ( char str[] );
void toUppercase ( char str[] );
void print (char str[] );



int main()
{
    char text[999];
	

	cout<<"Program converts letters in your text to uppercase \n ";

	initialise (text);
	enter ( text );
	cout<<endl;
	toUppercase ( text );
	cout<<endl;
	print ( text );
	cout<<endl;




	cout<<endl;
	system("PAUSE");
}

void enter ( char str[] )
{
	
	
	for ( i= 0 ; i < 999 ; i++)
	{	
		
		cin.get(str[i]);
	 if (str[i] == '\n')
		break;
	 
	}
}

void toUppercase ( char str[] )
{
	for ( i = 0 ; i < 999 ; i++)
		str[i] = static_cast<char>(toupper( str[i] ));
}

void print ( char str[] )
{
	for (i = 0 ; i < 999 ; i++)
		cout << str[i] ;
}

void initialise ( char str[] )
{
	for (i = 0 ; i < 999 ; i++)
		 str[i]=0;
}


Wciąż jednak nurtuje mnie to skąd się wzięły wcześniej te tajemnicze znaki i dlaczego akurat takie, jakaś wiadomość z zaświatów czy co? :D

[C++] program zamieniający tekst na pisany wielkimi literami

: 8 sie 2011, o 18:15
autor: void_t
Napisałem w moim ostatnim poście: dlatego, że przydzielona pamięć jest zwykle zaśmiecona jakimiś danymi pozostawionymi np przez inny program.

[C++] program zamieniający tekst na pisany wielkimi literami

: 8 sie 2011, o 19:07
autor: soku11
@void_t:
1. Pisze się w takim języku, w jakim jest wygodniej.
2. Ilość linijek kodu nie jest żadnym wyznacznik dobrze napisanego programu.
3. Funkcja to_upper, toUpper itd - jest ona już napisana w cctype. Nie widzę sensu w pisaniu jej od nowa. W dodatku stosowanie magicznych liczb (0x20) i operacji bitowych jest tylko zaciemnieniem kodu.
4. W C++ do tworzenia stałych stosuje się static const, a zamiast tego typu makr stosuje się funkcje inline.
5. W C++ do obsługi strumieni stosuje się cout/cin.
5. Co jeśli ktoś poda więcej niż 1024 znaki?
6. Jaki jest sens wpychania wszystkiego w jedną linię (18 linijka)?
7. printf jako pierwszego argumentu wymaga ciągu formatującego.
8. Zmienne powinno się deklarować w jak najwęższym zakresie (patrz *p).
8. Przedwczesna optymalizacja jest źródłem wszelkiego zła. Nie jesteśmy w antycznych czasach, kiedy trzeba analizować asma w poszukiwaniu wydajności. Dodatkowo kompilatory są na tyle inteligentne, że potrafią optymalizować wywołania prostych funkcji. Zdecydowanie lepiej jest napisany kod użytkownika PMichalak. Szczególnie ten drugi - w stylu C++ korzystając z jego zalet, bez zbędnych zabaw i kombinacji. Tylko niepotrzebnie definiuje ponownie toUpper. Kod jest czysty i łatwy w utrzymaniu (poza kilkoma szczególikami) - według mnie.
9. Rzeczywiście trochę dziwnie używać and i or. Ale jak jemu tak wygodnie, to w czym problem?
10. Co jest złego w zastosowaniu iteratora?
11. C++ uczy prawidłowego obiektowego podejścia do programowania. Uwierz, że nie wszystko różne od C jest złe. Zaraz poleci hasło żeby pisać TYLKO w prostym notatniku i pisać ręcznie makefile'a (swoją drogą make to też już antyczne narzędzie). Każdemu na początku swojej przygody z programowaniem wydaje się, że istnieje wyłącznie jeden poprawny język. Z doświadczeniem to na szczęście przechodzi :)

[C++] program zamieniający tekst na pisany wielkimi literami

: 8 sie 2011, o 20:09
autor: void_t
Ad1. Zdecydowanie. Ale nie zawsze wybór języka jest właściwy.
Ad2. Nikt nie mówił, że ilość linijek wyznacza cokolwiek. Stwierdziłem jedynie oczywisty fakt.
Ad3. No jest, to prawda - napisałem bo taką miałem ochotę.
Ad4. True.
Ad5. True.
Ad5b. Zostaną przetworzone tylko 1023 znaki. Autor zapisał statyczny bufor, zrobiłem to i ja.
Ad6. A co to za różnica? Zacytuję:
Ale jak jemu tak wygodnie, to w czym problem?
Ad7. True. To błąd bezpieczeństwa. Za chwile poprawię.
Ad8. Najwęższym zakresie?
Ad8b. Bez wątpienia Knuth miał rację. Ale jesteśmy dalej w czasach w których w dalszym ciągu człowiek jest mądrzejszy od kompilatora i potrafi stworzyć (w pewnych przypadkach) wydajniejszy kod.
Ad10. Właściwie to nic jeśli mowa o C++
Ad11. Polemizowałbym. Natomiast nie powiedziałem jakoby cokolwiek innego od C jest złe. Pisać w prostym notatniku? Chyba bym nie widział na oczy po 10 minutach. Makefile? Nie, takie rzeczy się generuje. Ponownie: nie mówię, że istnieje jeden poprawny język. Ale twierdzę, że C > C++.

Z mojej strony EOT.

[C++] program zamieniający tekst na pisany wielkimi literami

: 9 sie 2011, o 22:22
autor: abc666
Hmm \(\displaystyle{ C > C++}\) ale \(\displaystyle{ C \subset C++}\)
Ciekawa własność.

[C++] program zamieniający tekst na pisany wielkimi literami

: 10 sie 2011, o 10:19
autor: Quaerens
void_t, pisząc C>C++ masz na myśli, że C jest twoim zdaniem potężniejszy czy tam praktyczniejszy? Nie wiem jak taką relację tłumaczyć

[C++] program zamieniający tekst na pisany wielkimi literami

: 10 sie 2011, o 10:46
autor: void_t
Mam na myśli, że C jest bardziej użyteczny, prostszy, a co za tym idzie pozbawiony zbędnych kruczków składniowych i idiotycznych wieloznaczności. Jeśli nie wydaje się nikomu abym wyrażał swoje myśli precyzyjnie, proponuję poczytać trochę na stackoverflow - ktoś kiedyś zrobił bardzo dobre podsumowanie (aktualnie zgubiłem urla).

[C++] program zamieniający tekst na pisany wielkimi literami

: 10 sie 2011, o 13:20
autor: wszamol
void_t pisze:Mam na myśli, że C jest bardziej użyteczny, prostszy.
No tak, ale to jest Twoje zdanie, co kto lubi a to, że kiedyś ktoś zrobił porównanie... co z tego jak np. mnie lepiej pisze się w c++. To jest kwestia własnych upodobań i tyle, ale tak jak wyżej powiedzieli, c++ jest rozwinięciem c, więc nie wiem jak czyste c może być bardziej użyteczne

[C++] program zamieniający tekst na pisany wielkimi literami

: 10 sie 2011, o 23:33
autor: soku11
Kopiowałem numery i mi się kilka razy powtórzyło - heh.
2. Napisałeś w drugim zdaniu pierwszego swojego posta o ilości linijek. Po prostu odczytałem to jako skrytykowanie kodu, bo ma więcej linijek.
5b. Skoro podałeś swoje rozwiązanie, to powinno być ono poprawne. Nie wiem czemu tłumaczysz się kodem autora. Jak masz dłuższy tekst, to po prostu zadanie nie będzie wykonane poprawnie.
6. Stwierdzenie napisałem w kontekście używania konstrukcji and i or. Wszystko w jednej linijce zaciemnia kod przez co staje się on trudniejszy w utrzymaniu. Rada na przyszłość.
8. Używasz p wyłącznie w pętli - zdefiniuj je w pętli a nie na początku funkcji.
8b. Z ciekawości - podasz przykład, w którym ktoś szukał wydajności poprzez modyfikację kodu asm bądź używanie nieprzenośnych wstawek asma?
10. Nie rozumiem. Wytykasz błąd użycia iteratora w przypadku C++. Temat dotyczy C++, więc po co o tym pisałeś? I napisz w kontekście nie-C++ co jest złego w iteratorach. Programując często ich używam i nigdy problemów nie zaobserwowałem.
11. A co miał znaczyć ten fragment:
No ale tego właśnie niestety uczy C++.
I znów z ciekawości: jakie są kruczki składniowe i wieloznaczności. Ja z kolei słyszałem (podkreślam to słyszałem, bo ja nie mam żadnych problemów), że kompatybilność z podstarzałym C powoduje jakieś problemy.