funkcja pobierająca dokładnie n znaków

funkcja pobierająca dokładnie n znaków
CR
  • Rejestracja:prawie 9 lat
  • Ostatnio:prawie 6 lat
  • Postów:28
0

Witam,
Próbuje zrobić zadanie, w którym mam do napisania funkcję pobierającą z klawiatury najbliższe n znaków, włącznie z odstępami, tabulatorami i znakami nowej linii.
Problem polega na tym, że nie wiem jak zrobić, aby program po wpisaniu maksymalnej ilości znaków zaprzestał ich pobierania bez przechodzenia do nowej linii (jeśli wklepana została maksymalna ilość znaków).

Czy powinienem użyć w takim wypadku gets() / fgets() operując na łańcuchach?

Poniżej moja funkcja.

Kopiuj
#include <stdio.h>
#include <ctype.h>
#define MAX 10
int main()
{
	char ch;
	int n;
	
	while (n != MAX + 1){
		if (ch = getchar() || isspace(ch))
			n++;
	}
	return 0;

} 
kq
Moderator C/C++
  • Rejestracja:prawie 12 lat
  • Ostatnio:około 5 godzin
  • Lokalizacja:Szczecin
2

Skąd to isspace? Nie ma nic o tym w warunkach zadania.

Po prostu n razy wykonaj getchar


CR
  • Rejestracja:prawie 9 lat
  • Ostatnio:prawie 6 lat
  • Postów:28
0

Chyba nie bardzo rozumiem jak powtórzyć getchar n razy.
Czy mam użyć np. pętli for, czy do while? Niezależnie czego używałem, zawsze musiałem zaakceptować wprowadzony wiersz enterem, przy czym mogło to być 10 znaków ale również 20.

Nie chcę, aby funkcja pozwalała na wklepywanie znaków po załóżmy dziesiątej spacji/literze/enterze itp. (dlatego też dodałem isspace(ch), bo chodzi również o znaki niedrukowane)

0
crystalsky napisał(a):

Chyba nie bardzo rozumiem jak powtórzyć getchar n razy.
Czy mam użyć np. pętli for, czy do while? Niezależnie czego używałem, zawsze musiałem zaakceptować wprowadzony wiersz enterem, przy czym mogło to być 10 znaków ale również 20.

Nie chcę, aby funkcja pozwalała na wklepywanie znaków po załóżmy dziesiątej spacji/literze/enterze itp. (dlatego też dodałem isspace(ch), bo chodzi również o znaki niedrukowane)

To chyba będzie ci potrzebna biblioteka ncurses.h jak chcesz się bawić w zaawansowane sterowanie terminalem

mlyszczek
  • Rejestracja:ponad 8 lat
  • Ostatnio:ponad 8 lat
  • Lokalizacja:Wrocław
  • Postów:167
1

if (ch = getchar() || isspace(ch)) ten warunek nie ma zbyt wiele sensu. getchar odczytuje ze standardowego wejścia jeden znak (również białe znak) i zwraca go w postaci unsigned char. (ch = getchar()) zwróci kod ascii, więc będzie prawdą ZAWSZE, bo nie da się (w normalny sposób bez kombinowania z remapem) z klawiatury wprowadzić '\0' aby warunek też zwrócił 0. Teraz isspace(ch) zwróci 1 gdy ch == 0x20, a nie ma takiej potrzeby bo już getchar zwróci w tym przypadku 1.

Tak naprawdę funkcja isspace zostanie wykonana tylko w przypadku, gdy ch == '\0' (inaczej getchar zwraca prawdę i program od razu skacze do bloku if bez sprawdzania drugiego warunku), a gdy ch == '\0' to nie ma już sensu sprawdzać isspace bo wiemy ze 100% pewnością, że zwróci on 0.

Wniosek, isspace można wypieprzyć bo kompletnie, ale to kompletnie nic sensownego nie robi.

edytowany 2x, ostatnio: mlyszczek
Zobacz pozostały 1 komentarz
mlyszczek
Ale to nie spełni oczekiwań autora, bo autor chce aby można było wpisać 10 znaków, a ten warunek pozwoli na wpisanie 10 wyrazów.
MarekR22
@mwl4 czy ty wiesz, że to co napisałeś, nie zadziała zgodnie z twoim oczekiwaniem, bo przecinek tak nie działa jak ci się wydaje?
kq
A to dlaczego? Ten kod jest analogiczny do if((ch = getchar()), isspace(ch)). Jeśli tam nie ma UB z kolejnością dostępu (sequence points / sequenced after/before) to wydaje się być ok - nawet jeśli zapis nietypowy.
mwl4
No właśnie. Ja doskonale wiem co oznacza przecinek w takim zapisie ;)
kq
Może if(isspace(ch = getchar()) by było czytelniejsze?
MarekR22
Moderator C/C++
  • Rejestracja:około 17 lat
  • Ostatnio:2 minuty
2

stawiam na to, że autor chce bezpośredniego dostępu do klawiatury, a tymczasem nie zdaje sobie sprawy, że tak naprawdę korzysta ze standardowego wejścia skojarzonego z plikiem emulowanym przez klawiaturę.
Ergo dopóki user nie naciśnie enter nie będzie miał interakcji z programem, bo po prostu taka jest natura konsoli (pliku klawiatury).

Prawie na pewno musi wykroczyć poza standardowe biblioteki, by osiągnąć zamierzony cel.
Pod Windows może skorzystać z conio.h, albo lepiej z ncurses, które dostępne jest na wszystkie platformy, ale jest z nim nieco więcej rzeczy do zrobienia.


Jeśli chcesz pomocy, NIE pisz na priva, ale zadaj dobre pytanie na forum.
edytowany 1x, ostatnio: MarekR22
mlyszczek
  • Rejestracja:ponad 8 lat
  • Ostatnio:ponad 8 lat
  • Lokalizacja:Wrocław
  • Postów:167
0

@MarekR22 Problem nie leży tak naprawdę po stronie funkcji getchar a po stronie terminala. getchar bierze jeden znak ze strumienia, a w konsoli strumień jest domyślnie buforowany i flushowany dopiero po znaku nowej linii. Aby mieć natychmiastową reakcję przy getchar, w Linuksie trzeba przestawić terminal aby nie buforował znaków. Można to zrobić za na przykład tak system("/bin/stty raw"); Nie wiem jak to można zrobić na Windowsie.

#errata, trochę się zamotałem, nigdzie nie napisałeś, ze problem jest po stronie getchar, a że taka jest natura termina. Ale to wciąż można zmienić prosto bez ncurses.

edytowany 3x, ostatnio: mlyszczek
CR
  • Rejestracja:prawie 9 lat
  • Ostatnio:prawie 6 lat
  • Postów:28
0

Dziękuję wszystkim za odpowiedzi.
Może po prostu ja źle rozumiem zadanie, bo wątpię, aby ta funkcja miała być aż tak skomplikowana, bo mimo wszystko są to wciąż początki.
W drugim wariancie tego zadania funkcja ma kończyć działanie właśnie po wprowadzeniu n znaków, spacji, tabulatora lub znaku nowej linii, ale wciąż jestem zależny od przesłania wprowadzonego wiersza enterem, więc i tak automatycznie funkcja by kończyła swoją pracę, ponieważ enter został użyty (a co ze spacją i tabulatorem?).

Kopiuj
#include <stdio.h>
#define MAX 10
int main()

{
	char ch;
	int n;
	
	for (n = 0; n < MAX + 1; n++){
		ch = getchar();
		if (ch == '\t' || ch == ' ' || ch == '\0')
			break;
	}
	return 0;
		
} 
edytowany 1x, ostatnio: crystalsky
Zobacz pozostałe 9 komentarzy
KA
@mlyszczek: Jak odbierasz znaczki z klawiatury to masz gwarancje. Ale jeśli masz otwarty deskryptor dajmy na to modemu, to możesz mieć i kodowanie 9-cio bitowe i dodatkowe kody sterujące, a wtedy zrzutowanie na char-a grozi śmiercią :)
mlyszczek
A jak chcesz do getc, które przyjmuje FILE * (otrzymywane przez fopen) przekazać deskryptor do urządzenia szeregowego, które przyjmuje int otrzymywane z open;)
KA
A to urządzenia nie da się otworzyć za pomocą fopen() :)? A potem użyć getw, żeby mieć pewność, że wczytujesz wsio ;)? Oczywiści wspomnianego int-a to ja mogę dostać także z otwartego obiektu typu FILE. Chociażby przez fileno(3).
mlyszczek
Właśnie sprawdziłem u siebie i faktycznie za pomocą fopen otworzyłem uarta! Nigdy by mi to przez myśl nie przyszło, że tak można. Zwracam honor w takim razie i kajam się nisko. I dzięki za ciekawostkę:)
KA
De facto fopen(3) i open(2) różnią się przede wszystkim tym, że fopen(3) zgodnie z tym, co wskazuje numerek 3 jest częścią standardu C, a open(2) - jest biblioteką systemową i definiuje to POSIX / SUS / cokolwiek o co się teraz ludzie ciągną po sądach. Ale jedno i drugie otwiera pliki, więc jak masz tylko uarta wystawionego jako plik to jednym i drugim raczej go otworzysz ;)
datdata
  • Rejestracja:prawie 11 lat
  • Ostatnio:prawie 7 lat
  • Postów:957
1

Upewnij się czy na pewno musisz robić to, o czym piszesz. Jeśli to zadanie podczas początkowej nauki podstaw, zapewne rozwiązanie, które "wczyta" dowolną ilość znaków, a zapisze tylko n może być wystarczające, a Ty za bardzo kombinujesz :)


"A human being should be able to change a diaper, plan an invasion, butcher a hog, conn a ship, design a building, write a sonnet, balance accounts, build a wall, set a bone, comfort the dying, take orders, give orders, cooperate, act alone, solve equations, analyze a new problem, pitch manure, program a computer, cook a tasty meal, fight efficiently, die gallantly. Specialization is for insects." Robert Heinlein.
Kliknij, aby dodać treść...

Pomoc 1.18.8

Typografia

Edytor obsługuje składnie Markdown, w której pojedynczy akcent *kursywa* oraz _kursywa_ to pochylenie. Z kolei podwójny akcent **pogrubienie** oraz __pogrubienie__ to pogrubienie. Dodanie znaczników ~~strike~~ to przekreślenie.

Możesz dodać formatowanie komendami , , oraz .

Ponieważ dekoracja podkreślenia jest przeznaczona na linki, markdown nie zawiera specjalnej składni dla podkreślenia. Dlatego by dodać podkreślenie, użyj <u>underline</u>.

Komendy formatujące reagują na skróty klawiszowe: Ctrl+B, Ctrl+I, Ctrl+U oraz Ctrl+S.

Linki

By dodać link w edytorze użyj komendy lub użyj składni [title](link). URL umieszczony w linku lub nawet URL umieszczony bezpośrednio w tekście będzie aktywny i klikalny.

Jeżeli chcesz, możesz samodzielnie dodać link: <a href="link">title</a>.

Wewnętrzne odnośniki

Możesz umieścić odnośnik do wewnętrznej podstrony, używając następującej składni: [[Delphi/Kompendium]] lub [[Delphi/Kompendium|kliknij, aby przejść do kompendium]]. Odnośniki mogą prowadzić do Forum 4programmers.net lub np. do Kompendium.

Wspomnienia użytkowników

By wspomnieć użytkownika forum, wpisz w formularzu znak @. Zobaczysz okienko samouzupełniające nazwy użytkowników. Samouzupełnienie dobierze odpowiedni format wspomnienia, zależnie od tego czy w nazwie użytkownika znajduje się spacja.

Znaczniki HTML

Dozwolone jest używanie niektórych znaczników HTML: <a>, <b>, <i>, <kbd>, <del>, <strong>, <dfn>, <pre>, <blockquote>, <hr/>, <sub>, <sup> oraz <img/>.

Skróty klawiszowe

Dodaj kombinację klawiszy komendą notacji klawiszy lub skrótem klawiszowym Alt+K.

Reprezentuj kombinacje klawiszowe używając taga <kbd>. Oddziel od siebie klawisze znakiem plus, np <kbd>Alt+Tab</kbd>.

Indeks górny oraz dolny

Przykład: wpisując H<sub>2</sub>O i m<sup>2</sup> otrzymasz: H2O i m2.

Składnia Tex

By precyzyjnie wyrazić działanie matematyczne, użyj składni Tex.

<tex>arcctg(x) = argtan(\frac{1}{x}) = arcsin(\frac{1}{\sqrt{1+x^2}})</tex>

Kod źródłowy

Krótkie fragmenty kodu

Wszelkie jednolinijkowe instrukcje języka programowania powinny być zawarte pomiędzy obróconymi apostrofami: `kod instrukcji` lub ``console.log(`string`);``.

Kod wielolinijkowy

Dodaj fragment kodu komendą . Fragmenty kodu zajmujące całą lub więcej linijek powinny być umieszczone w wielolinijkowym fragmencie kodu. Znaczniki ``` lub ~~~ umożliwiają kolorowanie różnych języków programowania. Możemy nadać nazwę języka programowania używając auto-uzupełnienia, kod został pokolorowany używając konkretnych ustawień kolorowania składni:

```javascript
document.write('Hello World');
```

Możesz zaznaczyć również już wklejony kod w edytorze, i użyć komendy  by zamienić go w kod. Użyj kombinacji Ctrl+`, by dodać fragment kodu bez oznaczników języka.

Tabelki

Dodaj przykładową tabelkę używając komendy . Przykładowa tabelka składa się z dwóch kolumn, nagłówka i jednego wiersza.

Wygeneruj tabelkę na podstawie szablonu. Oddziel komórki separatorem ; lub |, a następnie zaznacz szablonu.

nazwisko;dziedzina;odkrycie
Pitagoras;mathematics;Pythagorean Theorem
Albert Einstein;physics;General Relativity
Marie Curie, Pierre Curie;chemistry;Radium, Polonium

Użyj komendy by zamienić zaznaczony szablon na tabelkę Markdown.

Lista uporządkowana i nieuporządkowana

Możliwe jest tworzenie listy numerowanych oraz wypunktowanych. Wystarczy, że pierwszym znakiem linii będzie * lub - dla listy nieuporządkowanej oraz 1. dla listy uporządkowanej.

Użyj komendy by dodać listę uporządkowaną.

1. Lista numerowana
2. Lista numerowana

Użyj komendy by dodać listę nieuporządkowaną.

* Lista wypunktowana
* Lista wypunktowana
** Lista wypunktowana (drugi poziom)

Składnia Markdown

Edytor obsługuje składnię Markdown, która składa się ze znaków specjalnych. Dostępne komendy, jak formatowanie , dodanie tabelki lub fragmentu kodu są w pewnym sensie świadome otaczającej jej składni, i postarają się unikać uszkodzenia jej.

Dla przykładu, używając tylko dostępnych komend, nie możemy dodać formatowania pogrubienia do kodu wielolinijkowego, albo dodać listy do tabelki - mogłoby to doprowadzić do uszkodzenia składni.

W pewnych odosobnionych przypadkach brak nowej linii przed elementami markdown również mógłby uszkodzić składnie, dlatego edytor dodaje brakujące nowe linie. Dla przykładu, dodanie formatowania pochylenia zaraz po tabelce, mogłoby zostać błędne zinterpretowane, więc edytor doda oddzielającą nową linię pomiędzy tabelką, a pochyleniem.

Skróty klawiszowe

Skróty formatujące, kiedy w edytorze znajduje się pojedynczy kursor, wstawiają sformatowany tekst przykładowy. Jeśli w edytorze znajduje się zaznaczenie (słowo, linijka, paragraf), wtedy zaznaczenie zostaje sformatowane.

  • Ctrl+B - dodaj pogrubienie lub pogrub zaznaczenie
  • Ctrl+I - dodaj pochylenie lub pochyl zaznaczenie
  • Ctrl+U - dodaj podkreślenie lub podkreśl zaznaczenie
  • Ctrl+S - dodaj przekreślenie lub przekreśl zaznaczenie

Notacja Klawiszy

  • Alt+K - dodaj notację klawiszy

Fragment kodu bez oznacznika

  • Alt+C - dodaj pusty fragment kodu

Skróty operujące na kodzie i linijkach:

  • Alt+L - zaznaczenie całej linii
  • Alt+, Alt+ - przeniesienie linijki w której znajduje się kursor w górę/dół.
  • Tab/⌘+] - dodaj wcięcie (wcięcie w prawo)
  • Shit+Tab/⌘+[ - usunięcie wcięcia (wycięcie w lewo)

Dodawanie postów:

  • Ctrl+Enter - dodaj post
  • ⌘+Enter - dodaj post (MacOS)