• Najnowsze pytania
  • Bez odpowiedzi
  • Zadaj pytanie
  • Kategorie
  • Tagi
  • Zdobyte punkty
  • Ekipa ninja
  • IRC
  • FAQ
  • Regulamin
  • Książki warte uwagi

Tablice znakow - wpisywanie w tablice i odczytywanie.

Object Storage Arubacloud
0 głosów
344 wizyt
pytanie zadane 13 grudnia 2021 w C i C++ przez Raven2221 Nowicjusz (200 p.)

Witam!

Jestem studentem pierwszego roku informatyki, i walcze z zadaniami z tablicami znakow - pewnie to nic trudnego, ale nie moge niestety poradzic sobie z jednym poleceniem. Oto tresc:

Napisz program w języku ANSI C, który pobierze od użytkownika liczbę naturalną n  , a następnie do 100-elementowej tablicy typu char wpisze znaki podane przez użytkownika, a następnie skopiuje do kolejnej statycznej 100-elementowej tablicy tab_rev typu char znaki zapisane w odwrotnej kolejności.

Następnie tablicę ze znakami w odwrotnej kolejności wypisujemy na ekran.

Zastanów się nad wczytywaną ilością znaków do tablicy typu char!

Nie piszemy kodu wypisującego elementy na ekranie oraz nie usuwamy linii print_tab(tab,n)!!!

W przypadku sytuacji błędnych program wypisuje komunikat: BŁĄD i kończy działanie.

Probowalem roznych opcji- najpierw z uzyciem scanf do wpisywania w tablice, ale scanf uparcie konczy wpisywanie na spacjach, a tu trzeba uwzglednic spacje i inne znaki specjalne. Probowalem z getcharem, ale w tym wypadku, jezeli wpisze mniej znakow niz zadeklarowalem to brak uzupelniany jest dziwnym znakiem. Wklejam najlepsza z opcji jakie udalo mi sie do tej pory wymyslec:

//Tablica ktora pobiera n znakow typu char, a potem je wypisuje w kolejnosci odwrotnej
#include <stdio.h>
#include <stdlib.h>
int main()
{
int n;
char tab[100];
scanf("%d", &n);


for(int i=0; i!=n+1; i++)
{
tab[i]= getchar();
}
printf("%s\n", tab);

char tab_rev[100];
int j=0;
for(int i=n; i>0; i--)
{
    tab_rev[j]=tab[i-1];
    printf("%s", tab_rev);
}

A to wynik.

1 odpowiedź

+1 głos
odpowiedź 14 grudnia 2021 przez j23 Mędrzec (194,920 p.)
edycja 14 grudnia 2021 przez j23

Popraw na:

for(int i = n - 1, j = 0; i >= 0; --i, ++j) {
    tab_rev[j] = tab[i];
}

tab_rev[n] = 0;
printf("%s\n", tab_rev);

Napisz program w języku ANSI C, który pobierze od użytkownika liczbę naturalną n, a następnie do 100-elementowej tablicy typu char wpisze znaki podane przez użytkownika (...)

Fajnie, że autor tego zadania napisał, po co ta "liczba naturalna n". Nie żebym nie wiedział, o co chodzi, ale ktoś początkujący może mieć problem ze zrozumienie tak sformułowanego zadania.

komentarz 14 grudnia 2021 przez Raven2221 Nowicjusz (200 p.)
edycja 14 grudnia 2021 przez Raven2221

Niestety, wszystkie te zadania sa tak formulowane, a to jedno z bardziej logicznych, bywa o wiele gorzej :)

I niestety- to nie rozwiazuje mojego problemu. Chodzi glownie o to, zeby dobrze zapisac znaki w pierwszej tabeli. Jak uzyje zwyklej funkcji wpisywania za pomoca scanf (czyli np scanf("%s", tab) ) to wszystko wczyta sie pieknie do pierwszej spacji, a chodzi o to, zeby do tabeli wpisywaly sie rowniez spacje. Jak uzyje sformulowania scanf("%[^\n]")  - czyli wg. wykladow opcji na uwzglednienie spacji to do drugiej tabeli nie wpisuje sie nic, program sie wylacza. Jak uzyje opcji getchar() to wszystko pieknie sie wpisuje, ale niestety zostaja dodatkowe znaki - tak jak na dolaczonym screenie wyzej (jak podamy 4 ala, to drukuje sie "ala?" zamiast "ala" - drukuje sie takze znak null). Probowalem zrobic petle if ktora hamowalaby wpisywanie przy wpisaniu niedozwolonych znakow - najpierw chcialem to zrobic wygodnie za pomoca wyrazenia regularnego, ale niestety najwyrazniej tak sie nie da, wiec wypisalem mozolnie wszystkie dozwolone znaki. Tylko ze blad wystepuje za kazdym jednym razem, nie wazne co tam nie wpisze. Wydaje mi sie, ze program odczytuje pierwszy "enter" i od razu chce go wpisywac do tablicy, co skutkuje bledem. Zamieszczam moj kod, z kilkoma opcjami ktore probowalem i komentarzami zeby bylo jasniej.

 

//Tablica ktora pobiera n znakow typu char, a potem je wypisuje w kolejnosci odwrotnej
#include <stdio.h>
#include <stdlib.h>
#include <regex.h>
int main()
{
int n;
char tab[100];
scanf("%d", &n);

//Proste wpisywanie do tablicy tab, niestety bez uwzglednienia spacji - a spacje musza byc uwzglednione w zadaniu
scanf("%s", tab);

//Wpisywanie do tablicy max 99 dowolnych znakow, bez znaku nowej linii - dziala w visual studio i to calkiem dobrze, ale nie na stronce na ktorej mam zlozyc odpowiedz. Tam nie drukuje nic (zakladam, ze to nic to albo znak nowej linii albo (null))

//scanf("%99[^\n]", tab);


//Chcialem zrobic petle sprawdzajaca zawartosc tabeli, i wypisujacej "BLAD" jezeli zawartosc tej tabeli jest nieprawidlowa. Niestety - jezeli ta petla jest dolaczona, komunikat "BLAD" drukuje sie za kazdym razem - w tablice wpisywany jest (null) - dlaczego?

// for(int i=0; i!=n+1; i++)
// {
// if(tab[i]!='q' ||tab[i]!='w' ||tab[i]!='e' ||tab[i]!='r' ||tab[i]!='t' ||tab[i]!='y' ||tab[i]!='u' ||tab[i]!='i' ||tab[i]!='o' ||tab[i]!='p' ||tab[i]!='a' ||tab[i]!='s' ||tab[i]!='d' ||tab[i]!='f' ||tab[i]!='g' ||tab[i]!='h' ||tab[i]!='j' ||tab[i]!='k' ||tab[i]!='l' ||tab[i]!='z' ||tab[i]!='x' ||tab[i]!='c' ||tab[i]!='v' ||tab[i]!='b' ||tab[i]!='n' ||tab[i]!='m' ||tab[i]!=',' ||tab[i]!='.' ||tab[i]!='!' ||tab[i]!='?' ||tab[i]!=':' ||tab[i]!='\n' ||tab[i]!=' ' ||tab[i]!='1' ||tab[i]!='2' ||tab[i]!='3' ||tab[i]!='4' ||tab[i]!='5' ||tab[i]!='6' ||tab[i]!='7' ||tab[i]!='8' ||tab[i]!='9' ||tab[i]!='0' ||tab[i]!='-' ||tab[i]!='=')
// {
// printf("co jest nie tak -%s" ,tab[i]);
// return 0;
// }
// }


// Metoda z getchar() - dziala, ale wypisuje dodatkowe znaki, jezeli ilosc znakow jest mniejsza niz zadeklarowana -tj. jezeli zadeklaruje ze podam 5 znakow, a podam 3 to dwa brakujace znaki zostana uzupelnione znakami ?. Np wpisze 4 i slowo "ala" i otrzymam slowo "?ala"

// for(int i=0; i!=n+1; i++)
// {
// tab[i]= getchar();
// if(tab[i]!='[a-zA-Z0-9]')
// {
// printf("BLAD");
// return 0;
// }
// }
printf("%s\n", tab);

//Drukowanie tablicy odwrotnej - dziala.

char tab_rev[100];
int j=0;
for(int i=n; i>0; i--)
{
    tab_rev[j]=tab[i-1];
    printf("%c", tab_rev[j]);
    j++;
}
//printf("%s", tab_rev);
}

 

komentarz 14 grudnia 2021 przez j23 Mędrzec (194,920 p.)

I niestety- to nie rozwiazuje mojego problemu.

Tamto co miałeś, było źle napisane, więc poprawiłem.

Metoda z getchar() - dziala, ale wypisuje dodatkowe znaki, jezeli ilosc znakow jest mniejsza niz zadeklarowana

No to tak zrób:

int c, i = 0;

while (i < n && (c = getchar()) != EOF) {
	tab[i++] = c; 
}

if (i != n) {
	// coś poszło nie tak
}

for(int i=n; i>0; i--)
{
    tab_rev[j]=tab[i-1];
    printf("%c", tab_rev[j]);
    j++;
}

Przy takim zapisie sens tablicy tab_rev jest żaden. Równie dobrze możesz od razu wypisywać tab[i-1].

komentarz 14 grudnia 2021 przez Raven2221 Nowicjusz (200 p.)
Super, z wykorzystaniem tego dziala jak powinno - co prawda na stronie zadanie dalej sie nie zalicza, ale nie mam pojecia dlaczego, to juz sprobuje zalatwic z prowadzacym zajecia.
komentarz 14 grudnia 2021 przez j23 Mędrzec (194,920 p.)

No a obsługę błędów zrobiłeś poprawnie? Wypisuje BŁĄD, jeśli n jest większy od 100 lub liczba znaków jest mniejsza niż n?

(...) oraz nie usuwamy linii print_tab(tab,n)!!!

Nie wiem, jak to rozumieć, ale chyba tą funkcją powinieneś wypisać tablicę.

komentarz 14 grudnia 2021 przez Raven2221 Nowicjusz (200 p.)

Nie, nie zabralem sie jeszcze za to, zmordowalo mnie to zadanie, przeszedlem do nastepnych. Ale po kolejnych modyfikacjach kodu mam juz inny komunikat bledu:

Brawo :-)

[+] Test #1. OK
[ ] Test #2. Time limit exceeded
[ ] Test #3. 
Twoja odpowiedź to: A6�C"��� |woe.
Poprawna odpowiedź to: BŁĄD
[ ] Test #4. 
Twoja odpowiedź to: .
Poprawna odpowiedź to: BŁĄD
[ ] Test #5. 
Twoja odpowiedź to: oatat.
Poprawna odpowiedź to: atat
[+] Test #6. OK
[+] Test #7. OK
[+] Test #8. OK
[+] Test #9. OK
[+] Test #10. OK

6 of 10 test(s) passed.

Nie wiem co mam uznac za blad, ani jak to zaimplementowac. Jedyne co mi przychodzi do glowy to uzycie switch'a i jako case'y poszczegolne znaki na klawiaturze. Wszystko inne wyswietlaloby komunikat "blad". Z tym, ze to czasochlonne, pewnie istnieje jakies inne, prostsze rozwiazanie.

I teoretycznie tak - powinienem uzyc tamtej funkcji, ale ona nie dziala prawidlowo, nie wypisuje wszystkich znakow. Nie wiem nawet jak dziala, nigdzie nie zostalo do objasnione. Wiec postanowilem ja zignorowac.

komentarz 14 grudnia 2021 przez j23 Mędrzec (194,920 p.)

Pokaż cały kod po porawkach.

Nie wiem nawet jak dziala

Łatwo się domyślić, jak działa. Pierwszy parametr to adres tablicy ze znakami, drugi - ilość znaków do wyświetlenia.

komentarz 15 grudnia 2021 przez Raven2221 Nowicjusz (200 p.)

Niby jest tak jak mowisz - ta funkcja powinna wyswietlac tablice, ale wyswietla najczesciej tylko jej ostatni znak.

Kod po przerobkach:

#include <stdio.h>
#include <stdlib.h>

int main()
{
int n,i;
char tab[100];
char tab_rev[100];
scanf("%d", &n);
    
for(i=0; i!=n; i++)
    {
        scanf("%c", &tab[i]);
        if(tab[i]=='\n')
        i--;
    }    
    printf("tab 5 %c\n", tab[5]);
    printf("tab 4 %c\n", tab[4]);
    printf("tab 3 %c\n", tab[3]);
    printf("tab 2 %c\n", tab[2]);
    printf("tab 1 %c\n", tab[1]);
    printf("tab 0 %c\n", tab[0]);
for(int i = n - 1, j = 0; i >= 0; --i, ++j) {
    tab_rev[j] = tab[i];
}
 
tab_rev[n] = 0;
printf("%s\n", tab_rev);

}

Wrocilem do scanf'a jednak. Za pomoca printfow chcialem zobaczyc co konkretnie jest wpisywane w poszczegolne elementy tablicy- bez ""cofniecia" wpisywania w przypadku \n na tab 0 wpisywany jest znak nowej linii, i kolejne znaki sa wpisywane dopiero na kolejne elementy. Wiec jezeli chce wpisac "domek" otrzymuje tylko "emod". Za kazdym razem scanf bierze pod uwage \n. Jak rozwiazac problem bledow nadal nie wiem.

komentarz 15 grudnia 2021 przez j23 Mędrzec (194,920 p.)

Sprawdź:

#include <stdio.h>
#include <stdlib.h>
 
int main()
{
    char tab[100];
    char tab_rev[100 + 1];
    int n, c, i = 0;
     
    scanf("%d\n", &n);

    while (i < 100 && (c = getchar()) != EOF && c != '\n') {
        tab[i++] = c; 
    }
     
    if (i != n) {
        printf("BŁĄD\n");
        return -1;
    }

    for(int i = n - 1, j = 0; i >= 0; --i, ++j) {
        tab_rev[j] = tab[i];
    }

    tab_rev[n] = 0;
    printf("%s\n", tab_rev);
}

 

komentarz 15 grudnia 2021 przez Raven2221 Nowicjusz (200 p.)

Dziala pieknie, ale niestety testy sprawdzajace nie beda zaliczone - pierwszy test podaje liczbe 4, a nastepnie slowo "ala" wiec o 1 znak mniej niz zadeklarowano, i zamiast odwrotnosci wychodzi BLAD.

 

komentarz 15 grudnia 2021 przez j23 Mędrzec (194,920 p.)
Nie wiem, czy to zgodne z założeniami zadania, ale liczba wczytanych znaków jest inna od zadeklarowanej, więc założyłem, że to błąd danych wejściowych, który powinien być zasygnalizowany przez program (vide ostatnie zdanie zadania).

Skoro to nie jest błąd, to zmień warunek w linii 16.
komentarz 15 grudnia 2021 przez Raven2221 Nowicjusz (200 p.)
Tylko na co mam go zmienic? Jak usune go calkowicie, to otrzymuje pusty wynik. Tak samo jak wpisze tam \n.
komentarz 15 grudnia 2021 przez j23 Mędrzec (194,920 p.)

Gdzie Ty chciałeś wpisać to \n?!

Zmień warunek na i > n. Autor zadania nie sprecyzował, kiedy program ma zwrócić BŁĄD, więc można sobie zgadywać, jak taki warunek powinien wyglądać.

komentarz 16 grudnia 2021 przez Raven2221 Nowicjusz (200 p.)

Dalej nie dziala.  Nie wyswietla sie nic. Problem jest z tym ze po wpisaniu liczby liter program domyslnie "wciska enter" i ten nieszczesny enter jest pierwszym odczytywanym znakiem zapisywanym w tablice. Czyli dla przykladu:

INPUT:
4  \n
ala

OUTPUT
\n
ala.

Jak chcialbym to rozpisac na poszczegolne elementy tablicy:

tab[0] = \n
tab[1] = a
tab[2]= l
tab[3]= a

Udalo mi sie to poprawic w poprzednim kodzie z uzyciem scanf'u cofajac po prostu indeks
poszczegolnych elementow tablicy w przypadku kiedy pierwszym elementem jest \n.
Wyszlo mniej wiecej tak

hipotetyczny tab[-1] = \n
tab[0] a
tab[1] l
tab[2] a

I ten sposob chociaz bardzo dziwaczny i pewnie grozacy bledem pamieci dziala - ale nie uwzglednia w ogole
bledow (cokolwiek ma byc bledem w tym zadaniu).

 

komentarz 16 grudnia 2021 przez j23 Mędrzec (194,920 p.)
#include <stdio.h>
#include <stdlib.h>
  
int main()
{
    char tab[100];
    char tab_rev[100 + 1];
    int n, c, i = 0;

    if(!fgets(tab, 100, stdin) || sscanf(tab, "%d", &n) != 1) {
        printf("BŁĄD\n");
        return -1;
    }

    while (i < 100 && (c = getchar()) != EOF && c != '\n') {
        tab[i++] = c; 
    }
      
    if (i > n) {
        printf("BŁĄD\n");
        return -1;
    }
    else n = i;
 
    for(int i = n - 1, j = 0; i >= 0; --i, ++j) {
        tab_rev[j] = tab[i];
    }
 
    tab_rev[n] = 0;
    printf("%s\n", tab_rev);
}

Powinno być ok.

Podobne pytania

0 głosów
3 odpowiedzi 667 wizyt
0 głosów
2 odpowiedzi 579 wizyt
pytanie zadane 19 stycznia 2018 w C i C++ przez nibyykto Nowicjusz (140 p.)
0 głosów
2 odpowiedzi 1,336 wizyt
pytanie zadane 6 października 2015 w C i C++ przez Pscoolka Nowicjusz (240 p.)

92,579 zapytań

141,432 odpowiedzi

319,663 komentarzy

61,964 pasjonatów

Motyw:

Akcja Pajacyk

Pajacyk od wielu lat dożywia dzieci. Pomóż klikając w zielony brzuszek na stronie. Dziękujemy! ♡

Oto polecana książka warta uwagi.
Pełną listę książek znajdziesz tutaj.

Akademia Sekuraka

Kolejna edycja największej imprezy hakerskiej w Polsce, czyli Mega Sekurak Hacking Party odbędzie się już 20 maja 2024r. Z tej okazji mamy dla Was kod: pasjamshp - jeżeli wpiszecie go w koszyku, to wówczas otrzymacie 40% zniżki na bilet w wersji standard!

Więcej informacji na temat imprezy znajdziecie tutaj. Dziękujemy ekipie Sekuraka za taką fajną zniżkę dla wszystkich Pasjonatów!

Akademia Sekuraka

Niedawno wystartował dodruk tej świetnej, rozchwytywanej książki (około 940 stron). Mamy dla Was kod: pasja (wpiszcie go w koszyku), dzięki któremu otrzymujemy 10% zniżki - dziękujemy zaprzyjaźnionej ekipie Sekuraka za taki bonus dla Pasjonatów! Książka to pierwszy tom z serii o ITsec, który łagodnie wprowadzi w świat bezpieczeństwa IT każdą osobę - warto, polecamy!

...