CYFROWY BARON • PROGRAMOWANIE • Zobacz wątek - StrToInt dla kilku liczb

StrToInt dla kilku liczb

dział ogólny

StrToInt dla kilku liczb

Nowy postprzez manin » poniedziałek, 2 grudnia 2013, 15:26

Witam.
Dopiero co zacząłem pracę z C++ Builder i natknąłem się na problem, z którym nie umiem sobie poradzić.
Stworzony przeze mnie StringGrid w przechowuje w komórkach jednej z kolumn ciąg liczb rozdzielonych spacjami, np:
1 4 15 62 8
Dodatkowo ilość liczb w takim Stringu nie zawsze jest jednakowa.
W jaki sposób można (najprościej i najczytelniej dla laika) liczby z takiego ciągu zapisać w jednowymiarowej tablicy?
Dodatkowo, czy istnieje sposób, aby każdy znak, niebędący cyfrą, który przez nieuwagę użytkownika znalazłby się w komórce, zastąpić spacją?

Z góry dziękuję za wskazówki.
Avatar użytkownika
manin
Bladawiec
Bladawiec
 
Posty: 5
Dołączył(a): poniedziałek, 2 grudnia 2013, 14:59
Podziękował : 2
Otrzymał podziękowań: 0
System operacyjny: WinXP
Kompilator: C++ Builder 6
Gadu Gadu: 0
    Windows XPFirefox

Re: StrToInt dla kilku liczb

Nowy postprzez Mironas » poniedziałek, 2 grudnia 2013, 16:05

Przepisanie liczb ze stringa do tablicy, zakładając dla uproszczenia, że w stringu nie ma więcej niż 10 liczb można zrobić np tak:
KOD cpp:     UKRYJ  
  TStrings* lista = new TStringList();
  lista->LineBreak = " ";
  lista->Text =  "1 2 5 10 15 25";

  int tab[10];  // max 10 liczb
  for (int i=0 ; i<lista->Count ; i++)
    tab[i] = lista->Strings[i].ToInt();

  delete lista;
 

Jeśli nie wiesz ile maksymalnie może być liczb to musisz tworzyć tablicę dynamicznie.

Zamiana w tekście znaków innych niż cyfry na spacje:
KOD cpp:     UKRYJ  
  String tekst = "1a2 5 10 z15 25x";
  for (int i=1 ; i<=tekst.Length() ; i++)
    if ( tekst[i]<'0' || tekst[i]>'9' )
      tekst[i] = ' ';   // tutaj spacja


Przy takich operacjach pomocna może też być funkcja StringReplace(...).
Avatar użytkownika
Mironas
Programista I
Programista I
 
Posty: 427
Dołączył(a): poniedziałek, 2 stycznia 2012, 19:02
Podziękował : 17
Otrzymał podziękowań: 61
System operacyjny: Windows 10
Kompilator: C++Builder 10.3 Rio
TMS Components Pack
Gadu Gadu: 0
    Windows XPChrome

Re: StrToInt dla kilku liczb

Nowy postprzez manin » poniedziałek, 2 grudnia 2013, 16:40

Dzięki za szybką odpowiedź, jednak chyba robię coś nie tak, bo przy kompilacji wyskakuje błąd 'LineBreak' is not member of 'TStrings'.
Avatar użytkownika
manin
Bladawiec
Bladawiec
 
Posty: 5
Dołączył(a): poniedziałek, 2 grudnia 2013, 14:59
Podziękował : 2
Otrzymał podziękowań: 0
System operacyjny: WinXP
Kompilator: C++ Builder 6
Gadu Gadu: 0
    Windows XPFirefox

Re: StrToInt dla kilku liczb

Nowy postprzez Cyfrowy Baron » poniedziałek, 2 grudnia 2013, 17:07

Wszystko robisz dobrze, tylko w C++Builder 6 TStringList nie ma metody LineBreak. W podanych niżej przykładach użyto tej metody by łamać tekst po każdej spacji, czyli taki zapis:

KOD text:     UKRYJ  
"1, 2 5, 10 15"


po użyciu LineBreak będzie wyglądał tak:

KOD text:     UKRYJ  
1
2
5
10
15
Avatar użytkownika
Cyfrowy Baron
Administrator
Administrator
 
Posty: 4716
Dołączył(a): niedziela, 13 lipca 2008, 15:17
Podziękował : 12
Otrzymał podziękowań: 442
System operacyjny: Windows 7 x64 SP1
Kompilator: Embarcadero RAD Studio XE2
C++ Builder XE2 Update 4
SKYPE: cyfbar
Gadu Gadu: 0
    Windows 7Firefox

Re: StrToInt dla kilku liczb

Nowy postprzez manin » poniedziałek, 2 grudnia 2013, 18:22

W takim razie jakiej metody mógłbym użyć, ewentualnie w jaki sposób zmodyfikować tę, aby działała w "szóstce"?
Avatar użytkownika
manin
Bladawiec
Bladawiec
 
Posty: 5
Dołączył(a): poniedziałek, 2 grudnia 2013, 14:59
Podziękował : 2
Otrzymał podziękowań: 0
System operacyjny: WinXP
Kompilator: C++ Builder 6
Gadu Gadu: 0
    Windows XPFirefox

Re: StrToInt dla kilku liczb

Nowy postprzez Mironas » poniedziałek, 2 grudnia 2013, 19:01

Dla BCB6 można tak:
KOD cpp:     UKRYJ  
  TStrings* lista = new TStringList();
  String tekst = "1 2 5 10 15 25";
 
  // zamiana spacji na znaki końca wiersza
  lista->Text = StringReplace(tekst, " ", "\r\n", TReplaceFlags() << rfReplaceAll);

  int tab[10];
  for (int i=0 ; i<lista->Count ; i++)
    tab[i] = lista->Strings[i].ToInt();

  delete lista;
 
Avatar użytkownika
Mironas
Programista I
Programista I
 
Posty: 427
Dołączył(a): poniedziałek, 2 stycznia 2012, 19:02
Podziękował : 17
Otrzymał podziękowań: 61
System operacyjny: Windows 10
Kompilator: C++Builder 10.3 Rio
TMS Components Pack
Gadu Gadu: 0
    Windows XPChrome

Re: StrToInt dla kilku liczb

Nowy postprzez Cyfrowy Baron » poniedziałek, 2 grudnia 2013, 19:01

Trzeba parsować lub posłużyć się regex'em. Napiszę w wolnej chwili parsowanie, ale nie dziś.
Avatar użytkownika
Cyfrowy Baron
Administrator
Administrator
 
Posty: 4716
Dołączył(a): niedziela, 13 lipca 2008, 15:17
Podziękował : 12
Otrzymał podziękowań: 442
System operacyjny: Windows 7 x64 SP1
Kompilator: Embarcadero RAD Studio XE2
C++ Builder XE2 Update 4
SKYPE: cyfbar
Gadu Gadu: 0
    Windows 7Firefox

Re: StrToInt dla kilku liczb

Nowy postprzez polymorphism » poniedziałek, 2 grudnia 2013, 19:08

Regex do tego?! Niech użyje klasy istringstream.
C++ Reference - opis wszystkich klas STL-a i funkcji C.

Za ten post autor polymorphism otrzymał podziękowanie od:
manin
Avatar użytkownika
polymorphism
Doświadczony Programista ● Moderator
Doświadczony Programista ● Moderator
 
Posty: 2156
Dołączył(a): piątek, 19 grudnia 2008, 13:04
Podziękował : 0
Otrzymał podziękowań: 200
System operacyjny: Windows 8.1
Windows 10
Linux Mint 21.1
Kompilator: Visual Studio
Visual Studio Code
MSYS2 (MinGW, clang)
g++
clang
Gadu Gadu: 0
    Windows XPFirefox

Re: StrToInt dla kilku liczb

Nowy postprzez Cyfrowy Baron » poniedziałek, 2 grudnia 2013, 20:07

polymorphism napisał(a):Niech użyje klasy istringstream.


A to mi akurat nie przyszło do głowy. :oops:

KOD cpp:     UKRYJ  
#include <iostream>
#include <fstream>
#include <sstream>

using namespace std;

 AnsiString text = "1 14 19 20";

 istringstream iSS( text.c_str() ); /* lub iSS( StringGrid1->Cell[x][y].c_str() ) */
 int n;

 while(iSS >> n)
 {
  ListBox1->Items->Add(n); /* tutaj przepisujesz ze zmiennej n gdzie ci potrzeba */
 }


Tyle, że przeszukiwanie zostanie przerwane gdy napotka tekst zamiast liczby. Można więc posłużyć się metodą isdigit:

KOD cpp:     UKRYJ  
#include <vcl.h>
#pragma hdrstop

#include "Unit1.h"


#include <sstream>
//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma resource "*.dfm"

using namespace std;

TForm1 *Form1;
//---------------------------------------------------------------------------
__fastcall TForm1::TForm1(TComponent* Owner)
        : TForm(Owner)
{
}
//---------------------------------------------------------------------------
void __fastcall TForm1::Button1Click(TObject *Sender)
{
 AnsiString text = "1 14 text 19 20";

 istringstream iSS( text.c_str() );
 char *buf;

 while(iSS >> buf)
 {

  if( isdigit( (unsigned char)*buf ) )
         ListBox1->Items->Add(buf);
 }
}

Za ten post autor Cyfrowy Baron otrzymał podziękowanie od:
manin
Avatar użytkownika
Cyfrowy Baron
Administrator
Administrator
 
Posty: 4716
Dołączył(a): niedziela, 13 lipca 2008, 15:17
Podziękował : 12
Otrzymał podziękowań: 442
System operacyjny: Windows 7 x64 SP1
Kompilator: Embarcadero RAD Studio XE2
C++ Builder XE2 Update 4
SKYPE: cyfbar
Gadu Gadu: 0
    Windows 7Firefox

Re: StrToInt dla kilku liczb

Nowy postprzez manin » poniedziałek, 2 grudnia 2013, 20:47

Dziękuję bardzo wszystkim. Dzięki wam mogę ruszać dalej. Kluczem okazał się isdigit. Nie miałem pojęcia o istnieniu takiej funkcji. Z resztą sobie już poradziłem.
Ostatnio edytowano poniedziałek, 2 grudnia 2013, 21:00 przez manin, łącznie edytowano 1 raz
Avatar użytkownika
manin
Bladawiec
Bladawiec
 
Posty: 5
Dołączył(a): poniedziałek, 2 grudnia 2013, 14:59
Podziękował : 2
Otrzymał podziękowań: 0
System operacyjny: WinXP
Kompilator: C++ Builder 6
Gadu Gadu: 0
    Windows XPFirefox

Re: StrToInt dla kilku liczb

Nowy postprzez polymorphism » poniedziałek, 2 grudnia 2013, 20:49

KOD cpp:     UKRYJ  
 char *buf; //<--- na co wskazuje?

 while(iSS >> buf) { ... }

Zamiast kombinować z gołymi wskaźnikami, użyj po prostu std::stringa, i wtedy testuj pierwszy znak.
C++ Reference - opis wszystkich klas STL-a i funkcji C.
Avatar użytkownika
polymorphism
Doświadczony Programista ● Moderator
Doświadczony Programista ● Moderator
 
Posty: 2156
Dołączył(a): piątek, 19 grudnia 2008, 13:04
Podziękował : 0
Otrzymał podziękowań: 200
System operacyjny: Windows 8.1
Windows 10
Linux Mint 21.1
Kompilator: Visual Studio
Visual Studio Code
MSYS2 (MinGW, clang)
g++
clang
Gadu Gadu: 0
    Windows XPFirefox

Re: StrToInt dla kilku liczb

Nowy postprzez Cyfrowy Baron » poniedziałek, 2 grudnia 2013, 20:51

Ale on pracuje na tabeli StringGrid i typie AnsiString, więc jak da std::string to będzie musiał kombinować z konwersją.
Avatar użytkownika
Cyfrowy Baron
Administrator
Administrator
 
Posty: 4716
Dołączył(a): niedziela, 13 lipca 2008, 15:17
Podziękował : 12
Otrzymał podziękowań: 442
System operacyjny: Windows 7 x64 SP1
Kompilator: Embarcadero RAD Studio XE2
C++ Builder XE2 Update 4
SKYPE: cyfbar
Gadu Gadu: 0
    Windows 7Firefox

Re: StrToInt dla kilku liczb

Nowy postprzez polymorphism » poniedziałek, 2 grudnia 2013, 20:56

Z tego co pamiętam, to nie - są zdefiniowane operatory << >> dla AnsiStringa.
C++ Reference - opis wszystkich klas STL-a i funkcji C.
Avatar użytkownika
polymorphism
Doświadczony Programista ● Moderator
Doświadczony Programista ● Moderator
 
Posty: 2156
Dołączył(a): piątek, 19 grudnia 2008, 13:04
Podziękował : 0
Otrzymał podziękowań: 200
System operacyjny: Windows 8.1
Windows 10
Linux Mint 21.1
Kompilator: Visual Studio
Visual Studio Code
MSYS2 (MinGW, clang)
g++
clang
Gadu Gadu: 0
    Windows XPFirefox

Re: StrToInt dla kilku liczb

Nowy postprzez Cyfrowy Baron » poniedziałek, 2 grudnia 2013, 21:01

Nie wiem o co Tobie chodziło w ostatniej wypowiedzi, ale można też ze string. W ten sposób pozbędę się pustego wskaźnika:

KOD cpp:     UKRYJ  
 AnsiString text = "1 14 text 19 20";

 istringstream iSS( text.c_str() );
 string buf;

 while(iSS >> buf)
 {
  if( isdigit( *buf.c_str() ) )
         ListBox1->Items->Add( buf.c_str() );
 }


Można by też od razu na AnsiString:

KOD cpp:     UKRYJ  
 AnsiString text = "1 14 text 19 20";

 istringstream iSS( text.c_str() );
 AnsiString buf;

 while(iSS >> buf.c_str())
 {
  if( isdigit( *buf.c_str() ) )
         ListBox1->Items->Add( buf );
 }
Ostatnio edytowano poniedziałek, 2 grudnia 2013, 21:18 przez Cyfrowy Baron, łącznie edytowano 2 razy
Powód: Poprawiłem kod, bo się trochę za daleko zapędziłem.
Avatar użytkownika
Cyfrowy Baron
Administrator
Administrator
 
Posty: 4716
Dołączył(a): niedziela, 13 lipca 2008, 15:17
Podziękował : 12
Otrzymał podziękowań: 442
System operacyjny: Windows 7 x64 SP1
Kompilator: Embarcadero RAD Studio XE2
C++ Builder XE2 Update 4
SKYPE: cyfbar
Gadu Gadu: 0
    Windows 7Firefox

Re: StrToInt dla kilku liczb

Nowy postprzez polymorphism » poniedziałek, 2 grudnia 2013, 21:27

KOD cpp:     UKRYJ  
while(iSS >> buf.c_str())

To jest zła konstrukcja. Zawartość zwrócona przez c_str jest tylko do odczytu.

Nie wiem o co Tobie chodziło w ostatniej wypowiedzi (...)

O to mi chodziło, że AnsiString ma zdefiniowane operatory << >> dla strumieni standardowych, dzięki czemu nic nie musisz konwertować.

Z dokumentacji:
To utilize the C++ streaming operators (<< and >>) with AnsiString, you must use #include <iostream> or #define VCL_IOSTREAM before #include <dstring.h>. This occurs automatically if you include vcl.h or system.h and defines the operators as follows:

KOD cpp:     UKRYJ  
ostream& operator << (ostream& os, const AnsiString& arg);
istream& operator >> (istream& is, AnsiString& arg);
C++ Reference - opis wszystkich klas STL-a i funkcji C.
Avatar użytkownika
polymorphism
Doświadczony Programista ● Moderator
Doświadczony Programista ● Moderator
 
Posty: 2156
Dołączył(a): piątek, 19 grudnia 2008, 13:04
Podziękował : 0
Otrzymał podziękowań: 200
System operacyjny: Windows 8.1
Windows 10
Linux Mint 21.1
Kompilator: Visual Studio
Visual Studio Code
MSYS2 (MinGW, clang)
g++
clang
Gadu Gadu: 0
    Windows XPFirefox

Następna strona

  • Podobne tematy
    Odpowiedzi
    Wyświetlone
    Ostatni post

Powrót do Ogólne problemy z programowaniem

Kto przegląda forum

Użytkownicy przeglądający ten dział: Brak zalogowanych użytkowników i 39 gości

cron