matematykaszkolna.pl
C Benny: Jak jest zdefiniowany pusty znak w C? Pętla przechodzi mój plik i chce zrobić tak, że jak spotka spację to ma ją usunąć lub zamienić na znak (pusty)?
21 cze 22:33
Jack: jak zrobisz takie ' ' to tlumaczy jako spacje.
21 cze 22:52
Saris: Możesz zamienić na '\0', jeśli nie używasz tego do iterowania się po tekście (jako warunku końca).
21 cze 22:56
undef: po prostu ' ' możesz porównywać do tego lub o kodu ascii int main() { char sp = ' '; printf("%d",sp); return 0; }
21 cze 22:59
Saris: albo rzutujesz 0 na char: sign = char (0); W każdym razie, nie da się usunąć znaku, nieważne czy wstawisz: '', '\0' itd. to i tak będzie tam pusty znak, który ma jakiś rozmiar.
21 cze 23:02
Benny: #include<stdio.h> #include<conio.h> #include<ctype.h> main() { FILE *f1, *f2; f1=fopen("DługiSms.txt", "r"); f2=fopen("KrótkiSms.txt", "w+"); char znak; while(!feof(f1)) { znak=fgetc(f1); if(znak==' ') fputc('', f2); else fputc(znak, f2); } fclose(f1); fclose(f2); getch(); } No i przy '' wywala mi błąd
21 cze 23:05
Metis: Pozbądź się tych polskich znaków z nazwy plików. Może błędnie interpretuje?
21 cze 23:08
Benny: To jest akurat dobrze, bo jak w dam np fputc('a', f2); to wpisze mi w miejsce spacji a
21 cze 23:09
Saris: Jaki błąd ^^
21 cze 23:10
Benny: [Error] empty character constant
21 cze 23:13
Saris: A dobra, > '' < to niepoprawne. Między nawiasy powinieneś coś zawsze wpisać. Zmień na '\0' albo (char) 0 i będzie działać
21 cze 23:13
Mariusz: Saris znakiem '\0' kończysz łańcuch Pusty znak to ''
21 cze 23:16
Benny: jak dałem fputc('char(0)', f2); to wpisało mi ) w miejsce spacji
21 cze 23:18
Benny: Mariusz, tak mi nie działa.
21 cze 23:22
Saris: Nie masz racji '' rzuci Ci błędem, a '\0' to zwykły null, który jest kończy łańcuchy znaków, ale nikt nie broni Ci go wstawić w środku tekstu.
21 cze 23:23
Saris: rany. na końcu łańcuchu*
21 cze 23:23
Saris: nie char(0) tylko > (char) 0 <
21 cze 23:24
jc: @Benny, po drobnych poprawkach działa, choć nie wiem, czy tak, jak sobie tego życzysz. #include<stdio.h> #include<ctype.h> int main() { FILE *f1, *f2; f1=fopen("DlugiSms.txt", "r"); f2=fopen("KrotkiSms.txt", "w+"); char znak; while((znak=fgetc(f1))!=EOF) { if(znak==' ') fputc(' ', f2); else fputc(znak, f2); } fclose(f1); fclose(f2); // getchar(); return 0; }
21 cze 23:25
jc: @Benny, uważaj aby pomiędzy ' ' znajdowała się faktycznie spacja. Mi się nie skopiowała i musiałem dopisać.
21 cze 23:26
Benny: Możesz mi powiedzieć co zmieniłeś w moim?
21 cze 23:29
jc: Przy okazji pewien fragment jest bez sensu. Jeśli znak jest spacją, to pisz spację, w przciwnym wypadku pisz znak. Czyli w każdym wypadku pisz znak! Czy o to chodziło?
21 cze 23:29
Benny: No nie bardzo. Jeśli znak jest spacją to wypisz znak pusty, w przeciwnym wypadku wypisz znak.
21 cze 23:31
jc: wyrzuciłem conio.h Dwie instrukcje złożyłem w jedną standardową: while((znak=fgetc(f1))!=EOF) Zmieniłem getch(), na getchar(), ale i tak skomentowałem, nie wiem jaki jest sens tej isntrukcji. Dopisałem int przed main() i return 0. Bez tego i tak by działało.
21 cze 23:31
jc: A co to jest znak pusty?
21 cze 23:32
Benny: Chodzi o to, że jak natrafi na spację ma ją wyrzucić.
21 cze 23:34
jc: Napisz tak, będzie bardzie uniwersalnie. if( ! isspace(znak) ) fputc(znak, f2); −−− Ja nie chcesz nic pisać, to po prostu nie pisz!
21 cze 23:37
Benny: Możesz mi powiedzieć co oznacza ten warunek?
21 cze 23:39
jc: isspace(znak ) sprawdza, czy znak jest spacją, tabulatorem, przejściem do nowej linii emotka
21 cze 23:41
Benny: Zrobiłem inaczej emotka #include<stdio.h> #include<conio.h> #include<ctype.h> main() { FILE *f1, *f2; f1=fopen("DługiSms.txt", "r"); f2=fopen("KrótkiSms.txt", "w+"); char znak; while(!feof(f1)) { znak=fgetc(f1); if(znak==' ') { znak=fgetc(f1); fputc(toupper(znak), f2); } else fputc(znak, f2); } fclose(f1); fclose(f2); getch(); }
22 cze 00:04
jc: Skąd bierzesz conio.h . Tego chyba nie ma w standardzie? I do czego Ci to potrzebne?
22 cze 00:07
jc: Jest jesze inny problem, w pętli dwa razy czytasz znak, a może się okazać, że już plik się skończył. To co zaproponowałem while((znak=fgetc(f1))!=EOF) jest przyjęte od początku historii C emotka
22 cze 00:11
Benny: Ok, zastosuje się. conio.h ma getch()
22 cze 00:16
jc: Przeczytałem juz co to za biblioteka. Faktycznie poza standardem. A do czego Ci potrzebne getch() ?
22 cze 00:19
Benny: Coś chyba było takiego, że program się kończył i wychodził od razu z wiersza poleceń. Coś chyba takiego wykładowca wspominał. getch() jest po to, aby tak nie było.
22 cze 00:34
Mateusz: Dokładnie, funkcja getch(); lub jak kto woli getchar(); wypisuje na ekran znak wpisany na klawiaturze az do nacisnięcia klawisza enter i jest ona niezbędna gdy uruchamiasz program w środowisku Windows, ponieważ pozwala na zatrzymanie okienka konsoli.
22 cze 06:47
Saris: Nie jest niezbędna
22 cze 11:06
Benny: @P[jc]] Zmieniłem ten warunek w while, ale coś nie pyka. Za dużo literek wyrzuca. Już chyba lepiej zostawić jak jest
22 cze 11:12
jc: @Benny, jaki efekt chcesz uzyskać? Domyślam się, że chcesz pominąć spację, a następny znak po spacji zapisać wielką literą. Zaproponowałbym coś takiego int spacja = 0; while((znak=fgetc(f1))!=EOF) if(isspace(znak) ) spacja = 1; else if (spacja) { fputc(toupper(znak), f2); spacja = 0; } else fputc(znak, f2); W pętli tylko raz czytasz znak sprawdzając przy okazji, czy plik się nie skończył. Co się u Ciebie stanie, jeśli ostatnim znakiem pliku będzie spacja? Być może nic, sprawdź emotka
22 cze 11:38
Benny: Sprawdziłem i zostawia spacje.
22 cze 11:42
jc: Co sprawdziłeś?
22 cze 11:46
Benny: No z tym moim kodem. Dopisałem do pliku spacje na końcu i w nowym pliku ta spacja na końcu też jest.
22 cze 11:55
jc: A miała być, czy nie? Chodzi o to, abyś nie czytał kolejnego znaku, nie mając pewności, czy czasm plik się nie skończył. Nie wiem jak sobie z taką sytuacją radzi system, nie wiem, czy to jest opisane, ale lepiej unikać takich niejasnych sytuacji.
22 cze 12:01
Benny: No nie miało jej być, wiem o co Ci chodzi, ale właśnie nie wiem co w tym wypadku. Polecenie jest takie, że mają być wyrzucone spacje z tekstu i wyraz, który jest po spacji ma zaczynać się dużą literą.
22 cze 12:17
jc: Co do zaproponowanej przeze mnie konstrukcji. Ja bym się wzorował na klasykach. Po prostu, jak wszyscy tak piszą, to łatwiej się potem czyta. Język ANSI C Kernighana i Ritchego, kopiowanie plików. Drugi autor jest twórcą C.
22 cze 12:31
Benny: Powiedz czy dobrze rozumie. Dopóki znak nie jest ostatnią (literą)?: jeśli napotkasz na drodze spacje, usuń ja i zwiększ licznik o 1 w przeciwnym wypadku, jeśli spacja jest niezerowa(tutaj mogę dać if(spacja==1)?) wpisz kolejny znak dużą literą i wyzeruj spację w przeciwnym wypadku wpisz znak.
22 cze 15:09
jc: U mnie spacja to taka zmienna, która pamięta czy poprzednio wczytany znak, to spacja. A co zrobi Twój program, jak napotka dwie lub więcej spacji pod rząd?
22 cze 17:22
Benny: Zostawi je i przejdzie do kolejnego znaku
22 cze 17:43
jc: Efekt działania Twojego programu Jedna spacja duzo spacji JednaSpacja DuzoSpacjiÿ Czy taki miał być wynik? z 5 spacji zostały dwie, a n końcu pojawiła się jakaś litera.
22 cze 17:53
Benny: No nie bardzo. Jak zmienić mój program, aby to poprawnie działało? Bez używania tej funkcji isspace
22 cze 18:08
jc: zamień na znak == ' ' ale to nie jest dobry pomysł, wstaw tabultory i znaki nowej linii. Tabulator też wprowadza spacje, jaka ma być rekacja programu?
22 cze 18:14
jc: isspace(znak) można zamienic na znak == ' ' To nie ma większego znaczenia. Miały być pomijane spacje, będą. A o tabulatorach pewnie nie było mowy.
22 cze 19:27
Benny: Było zaznaczone, że w tekście występują tylko spacje.
22 cze 19:44
Dziadek Mróz: void usunSpacje(char *napis) { char *s1 = source; char *s2 = source; while(*s2 != 0) { *s1 = *s2++; if(*s1 != ' ') { s1++; } } *s1 = 0; } lub void usunSpacje(char *napis) { char *s1, *s2; for (s1 = s2 = napis; *s1 != 0; s1++) { *s2 = *s1; if (*s2 != ' ') { s2++; } } *s2 = 0; } a dalej int main(int argc, char **argv) { char *napis = malloc(strlen("Ala ma kota, kot ma motek") + 1); strcpy(napis, "Ala ma kota, kot ma motek"); usunSpacje(napis); printf("%s", napis); free(napis); return 0; }
25 cze 06:26
Dziadek Mróz: Ale też zauważysz że tracisz swój oryginalny napis, więc musisz go sobie skopiować do jakiegoś bufora przed operacją
25 cze 07:02
Benny: Powiem Ci, że prawie nic nie rozumiem z tego. Zaczynam dopiero C emotka
25 cze 14:19
Dziadek Mróz: rysunek A ok. Wskaźnik − Jaś wskazuje palcem na Basię trzymającą książkę. Palec Jasia jest wskaźnikiem, Jaś jest adresem w pamięci wskaźnika, Basia jest adresem wskazującym, książka jest danymi przechowywanymi w adresie Basi. int a = 4; int *a_wsk = &a; // a_wsk − Jaś, &a − Basia, 4 − książka & to operator pobrania adresu z pamięci * to operator wyłuskania ze wskaźnika, wyciąga dane ze wskazywanej komórki pamięci printf("a: %d, &a: %x\n", a, &a); // nie ma *a bo a nie jest wskaźnikiem printf("a_wsk: %x, &a_wsk: %x, *a_wsk: %d\n", a_wsk, &a_wsk, *a_wsk); Wskaźnik zawiera adres komórki na który wskazuje.
25 cze 18:55
jc: A nie prościej powiedzieć, że wskaźnik to zmienna, w której przechowuje się adres.
25 cze 19:05
Dziadek Mróz: rysunek Ad poprzedniego posta, wynik działania kodu dla a i a_wsk: a: 4, &a: bf887318 a_wsk: bf887318, &a_wsk: bf88731c, *a_wsk: 4 Tablice można traktować jako wskaźnik. Wtedy możemy przesuwać się po elementach inkrementując lub dekrementując wskaźnik. Wskaźnik nieważne jakiego typu ma zawsze rozmiar 4B bo wskaźnik to adres printf("int*: %d, char*: %d, float*: %d\n", sizeof(int*), sizeof(char*), sizeof(float*)); int*: 4, char*: 4, double*: 4 int tab[] = {1, 2, 3, 4}; printf("&tab[0]: %x, tab[0]: %d\n", &tab[0], tab[0]); printf("&tab[1]: %x, tab[1]: %d\n", &tab[1], tab[1]); printf("&tab[2]: %x, tab[2]: %d\n", &tab[2], tab[2]); printf("&tab[3]: %x, tab[3]: %d\n", &tab[3], tab[3]); printf("&tab[4]: %x, tab[4]: %d\n", &tab[4], tab[4]); // wyszliśmy poza rozmiar tab &tab[0]: bfcdbe90, tab[0]: 1 &tab[1]: bfcdbe94, tab[1]: 2 &tab[2]: bfcdbe98, tab[2]: 3 &tab[3]: bfcdbe9c, tab[3]: 4 &tab[4]: bfcdbea0, tab[4]: −1215908956
25 cze 19:09
Dziadek Mróz: Teraz tab po wskaźniku, przyjmujemy że tamta tablica znajduje się w tym samym zakresie pamięci: sizet i; for (i = 0; i < 5; i++) { printf("&(tab+%d): %x, *(tab+%d): %d\n", i, (tab+i), i, *(tab+i)); } &(tab+0): bfcdbe90, *(tab+0): 1 &(tab+1): bfcdbe94, *(tab+1): 2 &(tab+2): bfcdbe98, *(tab+2): 3 &(tab+3): bfcdbe9c, *(tab+3): 4 &(tab+4): bfcdbea0, *(tab+4): −1215908956
25 cze 19:20
Benny: Dziękuje bardzo, poczytam sobie emotka
26 cze 08:44
b.: > Wskaźnik nieważne jakiego typu ma zawsze rozmiar 4B bo wskaźnik to adres Nie zawsze, w systemach 64 bitowych ma rozmiar 8B. A kiedyś miewał 2 B.
26 cze 12:39
Dziadek Mróz: Owszem ale obecnie można zdefiniować rodzaj kompilacji odpowiednim parametrem i na systemie 32b można skompilować program pod system 64b Jest to bodajże opcja −mXX gdzie XX to 32 lub 64
26 cze 14:25
jc: Chyba od dawna gcc kompilował pod różne systemy i procesory ...
26 cze 14:38