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
21 cze 23:41
Benny: Zrobiłem inaczej
#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
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ź
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
25 cze 14:19
Dziadek Mróz:
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:
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
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