Problem z pominięciem/wczytaniem pustych linii z pliku.

0

Cześć.
Ostatnio postanowiłem usprawnić swoje łączenie przez Windowsowskiego VPNa i napisałem program do takich połączeń.
Problem polega na tym, gdy pobiera dane z pliku (w tym wypadku z kolejnych linii w pliku) to omija puste linie, a chcę aby je odczytywał jako puste bądź null.
Tu kod z podawaniem danych, aby plik się utworzył:

else if(odpRDP == '3')
    {
        char pytanie;
        system("cls");
        cout <<"xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"<<endl;
        podgladWinVPN();
        cout <<"xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"<<endl;
        cin.clear();
        cout << "\nCzy polaczenie wymaga uzytkownika i hasla? (t/n)\n";
        cin >> pytanie;
        if(pytanie == 'n')
        {
            cout << "\nPodaj nazwe polaczenia:";
            cout << "\n(Nazwa musi byc zgodna z nazwa Windows VPN)\n";
            cin >> WVPN[nrWvpn].nazwawinvpn;
            WVPN[nrWvpn].userwinvpn = "";
            WVPN[nrWvpn].haslowinvpn = "";
            cout << "\nPodaj nazwe pliku polaczenia RDP:";
            cin >> WVPN[nrWvpn].rdpwin;

            cin.ignore();
            nrWvpn++;
            ifstream plik3;
            plik3.open("config\\winvpn.ini");
            system("cls");
            if ( nrWvpn != 0)                        //musi byc conajmniej 1 element do wypisania
            {                                                //j<i wyswietlanie prawidlowej wartosci   i = j-1
                cout << "\nDodano polaczenie z "<< WVPN[nrWvpn-1].nazwawinvpn << "." <<endl;
            }
            else
                cout << "\nBrak polaczen w bazie!\n";
            system("ping 1.1.1.1 -n 3 -w 3000 > nul");
        }
        else if(pytanie == 't')
        {
            cout << "\nPodaj nazwe polaczenia:";
            cout << "\n(Nazwa musi byc zgodna z nazwa Windows VPN)\n";
            cin >> WVPN[nrWvpn].nazwawinvpn;
            cout << "\n Podaj nazwe uzytkowanika:";
            cin >> WVPN[nrWvpn].userwinvpn;
            cout << "\nPodaj haslo:";
            cin >> WVPN[nrWvpn].haslowinvpn;
            cout << "\nPodaj nazwe pliku polaczenia RDP:";
            cin >> WVPN[nrWvpn].rdpwin;

            cin.ignore();
            nrWvpn++;
            ifstream plik3;
            plik3.open("config\\winvpn.ini");
            system("cls");
            if ( nrWvpn != 0)                        //musi byc conajmniej 1 element do wypisania
            {                                    //j<i wyswietlanie prawidlowej wartosci   i = j-1
                cout << "\nDodano polaczenie z "<< WVPN[nrWvpn-1].nazwawinvpn << "." <<endl;
            }
            else
                cout << "\nBrak polaczen w bazie!\n";
            system("ping 1.1.1.1 -n 3 -w 3000 > nul");
        }
        else
        {
            system("cls");
            cout << "\nPodales bledna odpowiedz!\n";
            system("ping 1.1.1.1 -n 2 -w 3000 > nul");
        }
    }

(Zapis plików tworzy się w oddzielnej funkcji, ale chyba w tym wypadku nie jest potrzebna.)

Podany kod powyżej tworzy taki plik:
------BEG------
1 <-Tu zlicza ilość połączeń / ster do wyboru połączenia
Test <-Nazwa połączenia
[i]pusta linia[/i] <-Użytkownik
[i]pusta linia[/i] <-Hasło
test <-Nazwa połączenia RDP
------EOF------

A tu poniżej podaję kod tworzenia pliku PowerShella, który jest uruchamiany przez plik bat.

int numerWVPN()
{
    char odp;
    do
    {
        int ok=0;
        do
        {
            system("cls");
            cout << "\nPolaczenie WinVPN\n";
            cout << "\nWybierz polaczenie:\n\n";
            cout <<"xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"<<endl;
            podgladWinVPN();
            cout <<"xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"<<endl;
            cout << "\n0. Powrot do menu\n\n";
            cin.clear();
            cin.sync();
            cin >> znak;
            if (cin.fail())
            {
                system("cls");
                cout << "\nNie podano liczby. Sprobuj wpisac ponownie...\n";
                system("ping 1.1.1.1 -n 2 -w 3000 > nul");
                cin.clear();
                cin.sync();
            }
            else
            {
                ok=1;
            }
        }while(ok==0);
        if (nrWvpn != 0)
        {
            system("cls");
            cin.ignore();

            if (znak > nrWvpn)
            {
                system("cls");
                cout <<"\nBrak polaczenia o takim numerze.";
                system("ping 1.1.1.1 -n 3 -w 3000 > nul");
            }
            else if(znak == 0)
            {

            }
            else
            {
                wczytajWinVPN();

                ofstream plik5("config\\winvpn.ps1", ios::out);
                plik5 <<"$vpnname = " + char2String(znaczek) + WVPN[znak-1].nazwawinvpn + char2String(znaczek)<<endl;
                plik5 <<"$vpnusername = " + char2String(znaczek) + WVPN[znak-1].userwinvpn + char2String(znaczek)<<endl;
                plik5 <<"$vpnpassword = " + char2String(znaczek) + WVPN[znak-1].haslowinvpn + char2String(znaczek)<<endl;
                plik5 <<"$cmd = $env:WINDIR + " + char2String(znaczek) + "\\System32\\rasdial.exe" + char2String(znaczek)<<endl;
                plik5 <<"$expression = " + char2String(znaczek) + "$cmd " + char2String(znaczek) + char2String(znaczek) + "$vpnname" + char2String(znaczek) + char2String(znaczek) + " $vpnusername $vpnpassword" + char2String(znaczek)<<endl;
                plik5 <<"$con = " + char2String(znaczek) + "$cmd $vpnname /DISCONNECT" + char2String(znaczek)<<endl;
                plik5 <<"$vpn = Get-VpnConnection | where {$_.Name -eq $vpnname}"<<endl;
                plik5 <<"if ($vpn.ConnectionStatus -eq " + char2String(znaczek) + "Disconnected" + char2String(znaczek) + ")"<<endl;
                plik5 <<"{"<<endl;
                plik5 <<"   Invoke-Expression -Command $expression"<<endl;
                plik5 <<"}"<<endl;
                plik5 <<"if($vpn.ConnectionStatus -eq "+ char2String(znaczek) + "Connected" + char2String(znaczek) + ")"<<endl;
                plik5 <<"{"<<endl;
                plik5 <<"   Invoke-Expression -Command $con"<<endl;
                plik5 <<"}"<<endl;

                do
                {
                    cout << "\nPolaczenie z " + WVPN[znak-1].nazwawinvpn + ".\n";
                    system("start WVPN.bat");
                    system("pause");
                    system("cls");
                    cout << "\nUruchamianie RDPa.\n";
                    ifstream plik1("config\\sciezka.ini", ios::in);
                    plik1 >> pathRDP;
                    system(("start " + char2String(znaczek) + pathRDP + "\\" + WVPN[znak-1].rdpwin + ".RDP" + char2String(znaczek) + " " + char2String(znaczek) + pathRDP + "\\" + WVPN[znak-1].rdpwin + ".RDP" + char2String(znaczek)).c_str());
                    cout << "\nChcesz ponowic polaczenie? (t/n)\n";
                    cin >> odp;
                }while(odp != 'n');

                system("cls");
                cout <<"\nZakonczono polaczenie z "<< WVPN[znak-1].nazwawinvpn <<"!";
                system("ping 1.1.1.1 -n 2 -w 3000 > nul");
            }
        }
        else
        {
            if(znak == 0)
            {

            }
            else
            {
                system("cls");
                cout << "\nPodales bledny numer!\n";
                system("ping 1.1.1.1 -n 2 -w 3000 > nul");
            }
        }
    }while(znak != 0);
    return 0;
}

A tak wygląda plik PowerShella:

$vpnname = "TEST"
$vpnusername = "test"
$vpnpassword = ""
$cmd = $env:WINDIR + "\System32\rasdial.exe"
$expression = "$cmd ""$vpnname"" $vpnusername $vpnpassword"
$con = "$cmd $vpnname /DISCONNECT"
$vpn = Get-VpnConnection | where {$_.Name -eq $vpnname}
if ($vpn.ConnectionStatus -eq "Disconnected")
{
   Invoke-Expression -Command $expression
}
if($vpn.ConnectionStatus -eq "Connected")
{
   Invoke-Expression -Command $con
}

Nie mam pojęcia jak odczytać puste linie żeby zamiast nazwy połączenia RDP pobierał 2 puste linie tj użytkownik i hasło. Może ktoś coś podpowie?

1

Jak chcesz czytać puste linie, użyj funkcji std::getline.

0
0x666 napisał(a):

Jak chcesz czytać puste linie, użyj funkcji std::getline.

Ok, ale w którym miejscu? Przy tworzeniu pliku powershella czy przy pobieraniu danych do pliku ze zmiennymi?

1

Przy pobieraniu danych z pliku (operator >> pomija białe znaki).

0
0x666 napisał(a):

Przy pobieraniu danych z pliku (operator >> pomija białe znaki).

No dobrze, czyli mam rozumieć, że muszę zmienić funkcję wczytania?

void wczytajWinVPN()
{
    ifstream plik3("config\\winvpn.ini", ios::in);
    plik3 >> nrWvpn;
    short j = 0;

    do
    {
        plik3 >>WVPN[j].nazwawinvpn;
        plik3 >>WVPN[j].userwinvpn;
        plik3 >>WVPN[j].haslowinvpn;
        plik3 >>WVPN[j].rdpwin;
        j++;
    }while( !plik3.eof() );
}
0
while(std::getline(plik3, WVPN[j].nazwawinvpn) &&
		std::getline(plik3, WVPN[j].userwinvpn) &&
		std::getline(plik3, WVPN[j].haslowinvpn) &&
		std::getline(plik3, WVPN[j].rdpwin))
{
	++j;
}
0

Stała się dziwna rzecz po takiej edycji wczytywania:

void wczytajWinVPN()
{
    ifstream plik3("config\\winvpn.ini", ios::in);
    plik3 >> nrWvpn;
    short j = 0;

    do
    {
        getline(plik3, WVPN[j].nazwawinvpn);
        getline(plik3, WVPN[j].userwinvpn);
        getline(plik3, WVPN[j].haslowinvpn);
        getline(plik3, WVPN[j].rdpwin);
        j++;
    }while( !plik3.eof() );
}

Plik tworzy się już lepiej, ale uzupełnia w złym miejscu:

$vpnname = ""
$vpnusername = "TEST"
$vpnpassword = ""
$cmd = $env:WINDIR + "\System32\rasdial.exe"
$expression = "$cmd ""$vpnname"" $vpnusername $vpnpassword"
$con = "$cmd $vpnname /DISCONNECT"
$vpn = Get-VpnConnection | where {$_.Name -eq $vpnname}
if ($vpn.ConnectionStatus -eq "Disconnected")
{
   Invoke-Expression -Command $expression
}
if($vpn.ConnectionStatus -eq "Connected")
{
   Invoke-Expression -Command $con
}

Jakieś wskazówki? Czemu nie podmienia do pierwszej zmiennej?

0
ifstream plik3("config\\winvpn.ini", ios::in);
plik3 >> nrWvpn;
plik3.ignore(std::numeric_limits<size_t>::max(), '\n'); // <---
...
0

Wielkie dzięki! Działa jak natura chciała :) Przy okazji, spoko opcja z maksymalnym limitem. Nawet nie wiedziałem, że coś takiego istnieje. Serdecznie pozdrawiam!

0

Teraz się pogubiłem.

Po dodaniu kolejnego połączenia robi się takie coś w pliku:

2
//pusta <- tu nie powinno być przesunięcia w dół
TEST
//pusta
//pusta
TEST2 <- podmieniło test na TEST2, prawdopodobnie przez przesunięcie
//pusta
//pusta
test2

Nie ważne! Dałem twój warunek sprawdzający czy nrWvpn == j i wsio w paradkie :D Dzięki jeszcze raz :)

0

Mam jeszcze 1 kwestię. Wszystko niby cacy, ale po zamknięciu programiku i uruchomieniu ponownie, nie odczytuje mojej zmiennej w podglądzie a wcześniej odczytywał:

void podgladWinVPN()
{
    if ( nrWvpn != 0)
    {
        for (short j = 0; j < nrWvpn; j++)
        {
            cout <<"x     Polaczenie nr "<<j+1<<": "<< WVPN[j].nazwawinvpn <<endl;
        }
    }
    else
    cout << "Brak polaczen w bazie!\n";
}
0

Kod wygląda ok, błędu szukałbym w innym miejscu.

Ilu elementowa jest tablica WVPN? I dlaczego nie std::vector?

0

Tablica WVPN ma 100 elementów w zupełności starczy. Jestem świeżakiem w C++, więc jeszcze dużo kombinuję z różną metodyką, jak również wiele nie znam.
A tablicę tworzę na bazie struktury:

struct winvpn
{
    string nazwawinvpn;
    string userwinvpn;
    string haslowinvpn;
    string rdpwin;
};
0

W funkcji czytającej z pliku do tej tablicy powinieneś sprawdzać, czy nie przekraczasz stu rekordów. Niejeden się przejechał na takim "w zupełności starczy".

0

Oj, nawet nie wiedziałem. Podpowiesz mi jak to mogę zrobić?

0

Tyle napisałeś, a warunku do pętli nie potrafisz dodać?

while(j < 100 && 
        std::getline(plik3, WVPN[j].nazwawinvpn) &&
        std::getline(plik3, WVPN[j].userwinvpn) &&
        std::getline(plik3, WVPN[j].haslowinvpn) &&
        std::getline(plik3, WVPN[j].rdpwin))
{
    ++j;
}

nrWvpn = j;
0
0x666 napisał(a):

Tyle napisałeś, a warunku do pętli nie potrafisz dodać?

while(j < 100 && 
        std::getline(plik3, WVPN[j].nazwawinvpn) &&
        std::getline(plik3, WVPN[j].userwinvpn) &&
        std::getline(plik3, WVPN[j].haslowinvpn) &&
        std::getline(plik3, WVPN[j].rdpwin))
{
    ++j;
}

Aaa to o to chodzi. Nie zrozumiałem cię, wybacz. Sprawdzę czy to może to.

2

Lepiej by było zrezygnować z tablicy w stylu C i używać std::vector.

0
ukaszek93 napisał(a):
0x666 napisał(a):

Tyle napisałeś, a warunku do pętli nie potrafisz dodać?

while(j < 100 && 
        std::getline(plik3, WVPN[j].nazwawinvpn) &&
        std::getline(plik3, WVPN[j].userwinvpn) &&
        std::getline(plik3, WVPN[j].haslowinvpn) &&
        std::getline(plik3, WVPN[j].rdpwin))
{
    ++j;
}

Aaa to o to chodzi. Nie zrozumiałem cię, wybacz. Sprawdzę czy to może to.
Niestety problem leży gdzie indziej. Coś źle odczytuje bo wyświetla mi numer połączenia ale nazwy nie widzi.

1 użytkowników online, w tym zalogowanych: 0, gości: 1