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

Dynamiczne tablice char/c/c++

VPS Starter Arubacloud
0 głosów
1,608 wizyt
pytanie zadane 12 marca 2020 w C i C++ przez Szymczak_7 Obywatel (1,860 p.)
Czy da się zrobić coś takiego, że długość tablicy char zostanie dostosowana po wpisaniu tekstu?
komentarz 12 marca 2020 przez tkz Nałogowiec (42,000 p.)
Skoro używasz c++, to masz klasę string, w dodatku dostępną out of the box z każdym kompilatorem(z tych bardziej popularnych).
komentarz 12 marca 2020 przez Szymczak_7 Obywatel (1,860 p.)
Ale robię zadanie z polskiego SPOJ'a i muszę użyć chara;
komentarz 12 marca 2020 przez tkz Nałogowiec (42,000 p.)
W poleceniu jest jasno napisane, że char? Pokaż treść.
komentarz 12 marca 2020 przez Szymczak_7 Obywatel (1,860 p.)
komentarz 12 marca 2020 przez tkz Nałogowiec (42,000 p.)
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int main(void)
{
    char *s = malloc(1);
    printf("Enter a string: \t");
    int c;
    int i = 0;
    while((c = getchar()) != '\n' && c != EOF)
    {
        s[i++] = c;
        s = realloc(s, i+1); 
    }
    s[i] = '\0';
    printf("Entered string: \t%s\n", s);  
    free(s);
    return 0;
}  

 

komentarz 12 marca 2020 przez Szymczak_7 Obywatel (1,860 p.)
Ten program nie działa wyskakuje mi błąd:

invalid conversion from 'void*' to 'char*' [-fpermissive]
komentarz 12 marca 2020 przez tkz Nałogowiec (42,000 p.)

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
 
int main(void)
{
    char *s = (char*)malloc(1);
    printf("Enter a string: \t");
    int c;
    int i = 0;
    while((c = getchar()) != '\n' && c != EOF)
    {
        s[i++] = c;
        s = realloc(s, i+1); 
    }
    s[i] = '\0';
    printf("Entered string: \t%s\n", s);  
    free(s);
    return 0;
}

 

komentarz 12 marca 2020 przez Szymczak_7 Obywatel (1,860 p.)
Wyskakuje ten sam błąd tylko tym razem w linii 14
komentarz 12 marca 2020 przez tkz Nałogowiec (42,000 p.)

Wiesz, że możesz ten komunikat wpisać w googla? 


#include <stdio.h>
#include <stdlib.h>
#include <string.h>
  
int main(void)
{
    char *s = (char*)malloc(1);
    printf("Enter a string: \t");
    int c;
    int i = 0;
    while((c = getchar()) != '\n' && c != EOF)
    {
        s[i++] = c;
        s = (char*)realloc(s, i+1); 
    }
    s[i] = '\0';
    printf("Entered string: \t%s\n", s);  
    free(s);
    return 0;
}

 

2 odpowiedzi

–1 głos
odpowiedź 12 marca 2020 przez dawid2002 Mądrala (5,190 p.)
edycja 15 marca 2020 przez dawid2002
 
Najlepsza
char tab[] = "";
std::cin >> tab;

EDIT:

Przyznam szczerze, że na co dzień nie używam łańcuchów znaków w stylu C, dlatego też podałem nieświadomie ten błędny przykład powyżej. Jedyne co było można by zrobić to wczytać tekst do string'a a następnie przekonwertować do tablicy char. Nic chyba lepszego nie da się zrobić.

std::string line;
std::cin >> line;
char* text = const_cast<char*>(line.c_str());   // lub w C++ 11: &*line.begin()
size_t size = line.length();

 

komentarz 12 marca 2020 przez dawid2002 Mądrala (5,190 p.)

mokrowski  Okay, dziękuje. Choć prościej byłoby tak:

std::string line;
std::cin >> line;
char* text = &line[0];
int size = line.length();

 

komentarz 12 marca 2020 przez mokrowski Mędrzec (155,460 p.)

1. Sprawdź co zwraca (jaki typ) operator[] tak w przypadku l-value jak i r-value.

2. Sprawdź jaki typ danych zwraca length() i co dzieje się przy przekroczeniu zakresu typu signed w C i C++.

ex.cpp:8:21: warning: implicit conversion loses integer precision: 'std::__1::basic_string<char, std::__1::char_traits<char>,
      std::__1::allocator<char> >::size_type' (aka 'unsigned long') to 'int' [-Wshorten-64-to-32]
    int size = line.length();

3. Przeczytaj jeszcze raz co napisałem o c_str() i konieczności (lub braku) terminowania zerem. W sygnaturze funkcji pytaniu były wymagane wskaźniki na c-string bo nie ma możliwości przekazania length do funkcji (nie biorę pod uwagę zmiennej globalnej bo.. no bez przesady, trzeba się szanować :) ) a Ty w 3 linii wcale go nie robisz.

Pozwól że zademonstruję o co chodzi. Uprzedzam jednak że w kodzie będzie się roiło od UB i nie jest to kod który powinno się tworzyć standardowo:

#include <string>
#include <iostream>

int main() {
    std::string word{"abrakadabra"};
    std::cout << "Normalny napis: " << word << '\n';
    // Pobiorę wskaźnik na dane przetrzymywane w std::string
    // i zmienię go w gotowy do zapisu. Oczywiście to jest UB.
    char * ptr = const_cast<char *>(word.data());
    // Obliczę pierwszy bajt za danymi i zapiszę do niego wartość 'X'
    // Znów UB.
    char * last_ptr = ptr + word.length();
    *(last_ptr) = 'X';
    // Dla dowodu, pokażę że rzeczywiście to jest koniec danych
    std::cout << "Ostatnie litery danych: ... ";
    for (char * p = last_ptr - 5; p <= last_ptr; ++p) {
        std::cout << *p << ' ';
    }
    std::cout << '\n';
    // Teraz test czy to się dobrze wyświetla jeśli dane to std::string
    std::cout << "Wyświetlenie std::string = " << word << '\n'; // I zaskoczenie ... bo dobrze. Tylko nie jest terminowane '\0' a 'X'
}

I inny przykład. std::string ma standardowo "w poważaniu" że wewnątrz występuje '\0'.

#include <string>
#include <iostream>

int main() {
    std::string msg{"abcXcba"};
    std::cout << msg.length() << '\n';
    msg[3] = '\0'; // A tu "srruu zero" :)
    for(auto c: msg) {
        std::cout << static_cast<int>(c) << '\n';
    }
    std::cout << "std::string = " << msg << '\n'; // Gdzie jest zero? WTF???
    std::cout << "c-string = " << msg.c_str() << '\n';
}

Mam nadzieję że teraz jest jasne dlaczego to powinien być c_str() i jasne dlaczego popełniłem (w mojej ocenie) barbarzyństwo rzutowania :) Można jeszcze bazować na pewnej subtelności standardu >= C++11, ale to ryzykowna droga...

Ok... wystarczy... 

 

komentarz 13 marca 2020 przez dawid2002 Mądrala (5,190 p.)

1. Sprawdziłem

2. Może i faktycznie zamiast int powinien być typ size_t

3. A tutaj to szczerze mówiąc nie wiem o co ci chodzi. Po co mi pokazujesz przykłady, które pokazują jak ważny jest '\0' , skoro mój przykład nie narusza tej ważnej zasady jaką jest umieszczanie na końcu tego znaku. Przecież gdy string przechowuje tekst to na końcu jest zawsze '\0'. Zobacz na wynik tego poniższego kodu:

std::string line;
std::cin >> line;
char* text = &line[0];
size_t size = line.length();

std::cout << text << "\n";

bool x = text[size] == '\0';           // wynik to true, więc....
std::cout << x;

 

komentarz 13 marca 2020 przez mokrowski Mędrzec (155,460 p.)

Przecież gdy string przechowuje tekst to na końcu jest zawsze '\0'.

No właśnie... pokaż mi miejsce w standardzie gdzje jest to jawnie.stwierdzone. To że tak może mieć dany kompilator, to zbyt mało. Warto zerknąć co zmieniono w C++11 w tej materii.

komentarz 13 marca 2020 przez dawid2002 Mądrala (5,190 p.)

Faktycznie w standardzie nie ma o tym mowy. Zatem wystarczy mój kod zmodyfikować i mamy coś takiego:

std::string line;
std::cin >> line;
char* text = const_cast<char*>(line.c_str());   // lub w C++ 11: &*line.begin()
size_t size = line.length();

 

+1 głos
odpowiedź 12 marca 2020 przez Michałełe Nałogowiec (25,600 p.)
	char tab[] = "foobar";

Czy o takie coś chodziło?

komentarz 12 marca 2020 przez Szymczak_7 Obywatel (1,860 p.)
Chodzi mi o to że na wejściu programu zostanie podany ciąg znaków i program ma dostosować długość tablicy char do tego ciągu.

Podobne pytania

0 głosów
2 odpowiedzi 316 wizyt
pytanie zadane 26 stycznia 2021 w C i C++ przez szylvvia Początkujący (300 p.)
0 głosów
1 odpowiedź 123 wizyt
pytanie zadane 29 marca 2020 w C i C++ przez wjacoszek2000 Początkujący (290 p.)
0 głosów
0 odpowiedzi 286 wizyt
pytanie zadane 10 grudnia 2016 w C i C++ przez jeżuś Nowicjusz (200 p.)

92,453 zapytań

141,262 odpowiedzi

319,087 komentarzy

61,854 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

Akademia Sekuraka 2024 zapewnia dostęp do minimum 15 szkoleń online z bezpieczeństwa IT oraz dostęp także do materiałów z edycji Sekurak Academy z roku 2023!

Przy zakupie możecie skorzystać z kodu: pasja-akademia - użyjcie go w koszyku, a uzyskacie rabat -30% na bilety w wersji "Standard"! Więcej informacji na temat akademii 2024 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!

...