Pobieranie danych

Tykis

Użytkownik
Dołączył
Luty 27, 2007
Posty
32
Witam serdecznie.
Chciałbym się dowiedzieć jak pobrać dane z ciągu znaków (np. 123456) pisanych z klawiatury do programu, ale każdego znaku osobno do osobnej zmiennej. Powiedzmy, że zmienne będą deklarowane tak:
Kod:
 int a1, a2, a3...
Jak to zrobić żeby każdą z liczb zapamiętać do osobnej zmiennej, czyli '1' do 'a1', '2' do 'a2' itd.
Używam dev C++.
Z góry dziękuje za pomoc
 

tobix10

Użytkownik
Dołączył
Luty 25, 2009
Posty
65
Chyba najłatwiej jak wczytasz wszystko do stringu lub tablicy znakowej i będziesz przypisywał znak po znaku do zmiennych.
Wystarczy, że od wartości znaku odejmiesz 48, a otrzymasz cyfrę.

Lepiej będzie użyć tablic od luźnych zmiennych, bo możesz mieć ich dużo. I w takim przypadku możesz zwiększyć liczbę elementów w tablicy.
 

Tykis

Użytkownik
Dołączył
Luty 27, 2007
Posty
32
Jeśli można to ja poproszę o tą metodę luźnych zmiennych, bo będzie ich dokładnie 9, a że na zajęcia z C++ mało chodziłem to teraz z tablicami nie bardzo jestem obyty ;-P No więc jaka komendą będę mógł zapamiętać to do osobnych zmiennych? Z góry dzięki
 

0wn3r

Były Moderator
Dołączył
Marzec 10, 2007
Posty
1330
Kod:
#include <iostream>
using namespace std;
int main()
{
    char a[8]; // 1
    string ciag;
    
    cout << "ciag znakow: ";
    cin >> ciag;
    
    for(int i = 0; i < ciag.length(); i++) // 2
    {
            a[i] = ciag[i]; // 3          
    }
    cout << a; // 4
    getchar(); // 5
}
  1. Deklarowanie 8 elementowej tablicy typu char.
  2. length(); - długość wprowadzonego ciągu znaków.
  3. Jeden element z tablicy a[] odpowiada jednemu znakowi z łańcucha tekstowego ciag.
  4. Wypisanie całej zawartości tablicy a[].
  5. Czekamy aż użytkownik naciśnie przycisk i kończymy pracę z programem.
Specjalnie napisałem Ci kod z użyciem tablicy, gdyż tablice strasznie ułatwiają życie i na prawdę warto się z nimi zapoznać, jeśli masz zamiar brnąć do przodu w tym języku programowania.

Pozdrawiam, 0wn3r.
 

Tykis

Użytkownik
Dołączył
Luty 27, 2007
Posty
32
Dzięki wielkie:)
Widzę, że te tablice nie takie trudne... w sumie to bardzo podobnie jak w pascalu, więc myślę,ze nie bedzie problemu. Pozdawiam
 

tobix10

Użytkownik
Dołączył
Luty 25, 2009
Posty
65
Na początku pisałeś o zmiennych typu int. Jeżeli nadal chcesz int to zamieniasz char a[8] na int a[8] a w pętli a = ciag - 48; (w ASCII 48 odpowiada cyfrze 0, 49 jedynce itd)
 

RobertG

Użytkownik
Dołączył
Styczeń 3, 2007
Posty
391
Co tego kodu, co jest wyżej, nie można ufać, że user nie wpisze więcej znaków, a wtedy:

Kod:
rgawron@foo:~$ ./a.out 
ciag znakow: 123456789
*** stack smashing detected ***: ./a.out terminated
======= Backtrace: =========
/lib/tls/i686/cmov/libc.so.6(__fortify_fail+0x48)[0xb7dac138]
/lib/tls/i686/cmov/libc.so.6(__fortify_fail+0x0)[0xb7dac0f0]
./a.out(__gxx_personality_v0+0x325)[0x8048b59]
/lib/tls/i686/cmov/libc.so.6(__libc_start_main+0xe0)[0xb7cd5450]
./a.out(__gxx_personality_v0+0x4d)[0x8048881]
 

grzonu

Były Moderator
Dołączył
Grudzień 26, 2006
Posty
1390
dlatego wlasnie cin jest najgorsza metoda do pobierania stringow :)
 

tobix10

Użytkownik
Dołączył
Luty 25, 2009
Posty
65
Przecież problem nie leży w cin, bo on pobiera do stringa a tam może znaleźć się kuuuuuuuuuupa znaków. Wystarczy tworzyć sobie dynamicznie tablicę w zależności od wielkości bufora wejściowego i tyle.

A tak poza tym kolega napisał, że cyfr będzie dokładnie 9, więc reszty nie będzie przetwarzać i tyle. W pętli for trzeba zmienić i < ciag.length() na i < 9, a w deklaracji tablicy powinno być char a[9]
 

grzonu

Były Moderator
Dołączył
Grudzień 26, 2006
Posty
1390
ale zlosliwy haxor moze wpisac wiecej cyfr a wtedy co? pozatym bezpieczne programowanie jest dobrym obyczajem nawet w sofcie nie wymagajacym tego
 

tobix10

Użytkownik
Dołączył
Luty 25, 2009
Posty
65
Rozumiem, ale napisałem że program będzie przystosowany do działania na 9 cyfrach.

Program w którym można przepełnić bufor.
Kod:
...
char a[9];
string ciag;
cin >> ciag;
for(int i = 0; i < ciag.length(); ++i)
a[i] = ciag[i];

a tu już jesteś zabezpieczony przed nadmierną ilością cyfr, string pomieści ich baaardzo dużo, a do tablicy i tak trafi tylko pierwszych dziewięć
Kod:
...
char a[9];
string ciag;
cin >> ciag;
for(int i = 0; i < 9 ++i)
a[i] = ciag[i];
 

RobertG

Użytkownik
Dołączył
Styczeń 3, 2007
Posty
391
Dalej macie to źle:

Kod:
rgawron@foo:~$ cat foo.c &&  g++ foo.c && ./a.out
#include <iostream>
using namespace std;
int main()
{
    char a[8]; // 1
    string ciag;
 
    cout << "ciag znakow: ";
    cin >> ciag;
 
    for(int i = 0; i < 9; i++) // 2
    {
            a[i] = ciag[i]; // 3
    }
    cout << a; // 4
    getchar(); // 5
}
ciag znakow: 1
*** stack smashing detected ***: ./a.out terminated
======= Backtrace: =========
/lib/tls/i686/cmov/libc.so.6(__fortify_fail+0x48)[0xb7de1138]
/lib/tls/i686/cmov/libc.so.6(__fortify_fail+0x0)[0xb7de10f0]
./a.out(__gxx_personality_v0+0x30c)[0x8048b04]
/lib/tls/i686/cmov/libc.so.6(__libc_start_main+0xe0)[0xb7d0a450]
 

Dark Smark

Były Moderator
Dołączył
Kwiecień 29, 2006
Posty
1953
Jeżeli chodzi wam o nadużycia dotyczące przepełnień zaalakowanej pamięci dla aplikacji to zawsze można użyć strncpy();
Pozdrawiam.
 

grzonu

Były Moderator
Dołączył
Grudzień 26, 2006
Posty
1390
dzieci ... czy nikt nie pamieta ze tablice indexuje sie od 0 ?
wiec ten for nie powinien miec i<9 tylko i<8
 

0wn3r

Były Moderator
Dołączył
Marzec 10, 2007
Posty
1330
Kod:
#include <iostream>
using namespace std;
int main()
{
    char a[8]; // 1
    string ciag;
    
    cout << "ciag znakow: ";
    cin >> ciag;
    
    for(int i = 0; i < ciag.length(); i++) // 2
    {
            a[i] = ciag[i];       
    }
    cout << a;
    getchar();
}
  1. 0, 1, 2, 3, 4, 5, 6, 7, 8 - 9 cyfr.
  2. Przyjmijmy ciag = 123456789, to length() odpowiada i < 9.
Pozdrawiam.
 
Ostatnia edycja:

grzonu

Były Moderator
Dołączył
Grudzień 26, 2006
Posty
1390
0wn3r ale przeciez to tez nie rozwiaze problemu :)
poniewaz jesli wpisze powiedzmy 15 cyfr to do a i tak zapisze sie 15 cyfr i nastapi segmentation fault
#include <iostream>
using namespace std;
int main()
{
char a[8]; // 1
string ciag;

cout << "ciag znakow: ";
cin >> ciag;

for(int i = 0; i < 8; i++) //dzieki temu warunkowi zapobiegniemy sytuacji ze zapisalismy za duzo
{
a = ciag;
if(i==ciag.length())//dzieki temu zapobiegniemy sytuacji ze wpisalismy mniej niz trzeba
{
break;
}
}
cout << a;
getchar();
}
 

tobix10

Użytkownik
Dołączył
Luty 25, 2009
Posty
65
Heh Ty chyba połączyłeś dwie różne wypowiedzi w jeden kod. Pisałem, że ma być char a[9] a nie 8 bo w kolega mówił, że będzie dziewięć cyfr.


Taka pętla for(int i = 0; i < 9; ++i) i po problemie.
 
Ostatnia edycja:

RobertG

Użytkownik
Dołączył
Styczeń 3, 2007
Posty
391
W pierwszym poście nie było ograniczenia, jaka jest maksymalna ilość liczb, problem ten można rozwiązać przy użyciu STL'a, np w ten sposób:

Kod:
#include <iostream>
#include <cstring>
#include <string>
#include <vector>

using namespace std;


int main() {
    vector<char> digits;
    string input;

    cin >> input;
    
    string::const_iterator iterator_input = input.begin();
    while(iterator_input != input.end()){
        digits.push_back(*iterator_input);
        iterator_input++;
    }

    vector<char>::const_iterator iterator_digits = digits.begin();
    while(iterator_digits != digits.end()){
        cout << (*iterator_digits) << endl;
        iterator_digits++;
    }

}
w ten sposób można podawać dowolnie długie liczby, jeśli potrzebne było by ograniczenie ich długości to można je upchnąć w pierwszym iteratorze. Taka implementacja rozwiązuje również problemy z błędnym odczytem pamięci jakie pojawiły się w kodach prezentowanych wyżej.
 
Ostatnia edycja:

loganek

Były Moderator
Dołączył
Listopad 11, 2006
Posty
563
RobertG, twój sposób dobry, ale nie idealny. Jakby się uprzeć, to i vector można przekroczyć. max_size() rozwiąże problem w 100%. Ale to ekstremalne przypadki.
 
Do góry Bottom