Wortzusammensetzung über Pointer und getline() statt mit gets()



  • error C2664: 'gets': Konvertierung des Parameters 1 von 'char (*)[80]' in 'char *' nicht möglich
    error C2664: 'gets': Konvertierung des Parameters 1 von 'char (*)[80]' in 'char *' nicht möglich
     error C2664: 'strcpy': Konvertierung des Parameters 1 von 'char (*)[160]' in 'char *' nicht möglich
    error C2664: 'strcat': Konvertierung des Parameters 1 von 'char (*)[160]' in 'char *' nicht möglich
    


  • silent_max schrieb:

    error C2664: 'gets': Konvertierung des Parameters 1 von 'char (*)[80]' in 'char *' nicht möglich
    error C2664: 'gets': Konvertierung des Parameters 1 von 'char (*)[80]' in 'char *' nicht möglich
     error C2664: 'strcpy': Konvertierung des Parameters 1 von 'char (*)[160]' in 'char *' nicht möglich
    error C2664: 'strcat': Konvertierung des Parameters 1 von 'char (*)[160]' in 'char *' nicht möglich
    

    Wieso nimmst du denn auch die Adressen der Arrays?
    Übergib' einfach direkt die Arrays, das array-to-pointer decay macht den Rest.



  • silent_max schrieb:

    error C2664: 'gets': Konvertierung des Parameters 1 von 'char (*)[80]' in 'char *' nicht möglich
    error C2664: 'gets': Konvertierung des Parameters 1 von 'char (*)[80]' in 'char *' nicht möglich
     error C2664: 'strcpy': Konvertierung des Parameters 1 von 'char (*)[160]' in 'char *' nicht möglich
    error C2664: 'strcat': Konvertierung des Parameters 1 von 'char (*)[160]' in 'char *' nicht möglich
    

    Verstehst du diese Fehlermeldungen? Weißt du, was char(*)[80] ist?



  • Sone schrieb:

    Und was soll in diesem Fall an string besser sein?

    namespace
    {
      const std::array<char const*, 2> emlist = {{
        "foo", "bar"
      }};
    }
     
    char const* &errormsg(std::array<char const*, 2>::size_type errorcode) {
      assert(errorcode < emlist.size());
      return emlist[errorcode];
    }
    

    [...]

    Immer diese Vorurteile gegenüber Zeigern...

    In Zeile 8 sehe ich ein falsches & . Beim Umgang mit Zeigern hast du also schon in so einem simplen Beispiel einen Flüchtigkeitsfehler gemacht. Mit string wäre das nicht passiert.

    Ich sehe ja ein, dass die Speicheranforderung durch string verschwenderisch ist. Aber const char * ist eindeutig die falsche Alternative. Die Idee von C++ ist nicht, dass man bei jedem kleinen Hindernis in prähistorisches Verhalten zurückfällt.

    Die Vorteile von string ohne die Nachteile:

    #include <utility>
    #include <iostream>
    #include <array>
    #include <cassert>
    #include <cstring>
    
    template <class C>
    class basic_string_ref
    {
    public:
    
    	typedef C value_type;
    	typedef C &reference;
    	typedef C *iterator;
    	typedef iterator const_iterator;
    	typedef std::size_t size_type;
    
    	basic_string_ref();
    	basic_string_ref(iterator begin, iterator end);
    
    	template <std::size_t N>
    	basic_string_ref(value_type (&data)[N]);
    
    	basic_string_ref(iterator c_string)
    		: m_begin(c_string)
    		, m_end(c_string + std::strlen(c_string))
    	{
    	}
    
    	size_type size() const
    	{
    		return std::distance(m_begin, m_end);
    	}
    
    	iterator data() const
    	{
    		return m_begin;
    	}
    
    	bool empty() const;
    	iterator begin() const
    	{
    		return m_begin;
    	}
    
    	iterator end() const
    	{
    		return m_end;
    	}
    	//...
    
    private:
    
    	iterator m_begin;
    	iterator m_end;
    };
    
    template <class C>
    std::basic_ostream<typename std::remove_const<C>::type> &operator << (
    std::basic_ostream<typename std::remove_const<C>::type> &os, basic_string_ref<C> const &str)
    {
    	std::copy(str.begin(), str.end(),
    		std::ostreambuf_iterator<typename std::remove_const<C>::type>(os));
    	return os;
    }
    
    typedef basic_string_ref<char> string_ref;
    typedef basic_string_ref<const char> cstring_ref;
    
    namespace
    {
    	const std::array<cstring_ref, 2> emlist =
    	{{
    		"foo",
    		"bar"
    	}};
    }
    
    cstring_ref const &errormsg(unsigned errorcode)
    {
    	assert(errorcode < emlist.size());
    	return emlist[errorcode];
    }
    
    int main()
    {
    	for (auto i = emlist.begin(); i != emlist.end(); ++i)
    	{
    		std::cout << *i << '\n';
    	}
    }
    

    EDIT: const -Verhalten korrigiert (danke an krümelkacker).



  • TyRoXx schrieb:

    Ich sehe ja ein, dass die Speicheranforderung durch string verschwenderisch ist. Aber const char * ist eindeutig die falsche Alternative.

    Das ist deine Meinung, die ich nicht mit dir teile.

    TyRoXx schrieb:

    Die Idee von C++ ist nicht, dass man bei jedem kleinen Hindernis in prähistorisches Verhalten zurückfällt.

    Hast du ein anderes Argument als "ich finde, das gehört nur in die Prähistorie" parat? Denn es ist keins.

    TyRoXx schrieb:

    Die Vorteile von string ohne die Nachteile:
    [...]

    Das finde ich nicht überzeugend genug, als dass ich behaupten wollen würde, alles andere sei "eindeutig falsch".

    Ich denke auch, dass du dein basic_string_ref nicht ganz zu Ende gedacht hast. Die const/nonconst Überladungen für begin/end finde ich komisch. Das passt einfach nicht zur restlichen Referenz/Zeiger-Semantik, die dieser Typ hat. Ist Dir schon mal aufgefallen, dass ein shared_ptr<T> folgenden Dereferenzierungsoperator bietet?

    T& operator*() const
      ^^             ^^^^^
    

    Das const überträgt sich da nicht auf den Rückgabetyp bei so einem Zeiger-artigem Objekt. Und das ist auch sinnvoll so; denn ein "deep const" bringt nichts, wenn man das Objekt kopieren kann und über die non-const Kopie auf dieselben Daten zugreifen kann. Ich hätte bei dir folgendes erwartet:

    T* begin() const {...} 
     T* end() const {...}
    

    und dann am besten noch einen Konvertierungskonstruktor für string_ref -> cstring_ref eingebaut.

    Aber wie unterscheidet sich jetzt cstring_ref von const char*? So, wie du es aktuell gebaut hast, beschränken sich die Unterschiede auf ein "STL Interface". Ein STL Interface ist nett, brauche ich aber bei Stringkonstanten so gut wie nie.

    Das praktische an so einem benutzerdefinierten Typ ist nicht die Rückgabe von strings, sondern das Empfangen von Strings als Funktionsparameter. Man kann den Typ so bauen, dass dem Benutzer das ".c_str()" erspart bleibt, wenn er einen std::string zur Hand hat. Wenn ich mich richtig erinnere, ist das auch die Motivation des string_ref-Proposals.

    Ich gehöre zu den ersten, die sich über Zeiger-Frickelei aufregen. Habe auch schon in ähnlicher Form ein array_ref-Klassentemplate gebastelt, was sich mit allerlei Dingen hat initialisieren lassen ( std::vector , std::array , rohes Array) sogar mit so lustigen Konvertierungen wie std::vector<Dings*> --> array_ref<const Dings* const>, die C++ mit rohen Zeigern erlaubt, ohne dass das ein Problem wär.

    Aber const char* oder const char[] für Zeichenkettenkonstanten kann ich bei bestem Gewissen nicht verteufeln.



  • Sone schrieb:

    Wieso nimmst du denn auch die Adressen der Arrays?
    Übergib' einfach direkt die Arrays, das array-to-pointer decay macht den Rest.

    Wie meinst Du das??

    Kannst Du nicht einen Beispielcode schreiben? Weil ich verstehe bei "array-to-pointer decay" nicht, was Du meinst...



  • Wenn du den Adressoperator auf einen Ausdruck des Typs T anwendest, bekommst du einen Zeigerwert des Typs T*. Logisch, oder?

    Text_1 hat bei dir den Typ char[160]. Also ist &Text_1 ein Zeigerwert des Typs char(*)[160]. Logisch, oder?

    Die gets-Funktion will aber einen Zeiger vom Typ char* haben.

    Siehe
    http://c-faq.com/~scs/cgi-bin/faqcat.cgi?sec=aryptr
    (u.a. Frage 6.12)



  • silent_max schrieb:

    Sone schrieb:

    Wieso nimmst du denn auch die Adressen der Arrays?
    Übergib' einfach direkt die Arrays, das array-to-pointer decay macht den Rest.

    Wie meinst Du das??

    Kannst Du nicht einen Beispielcode schreiben? Weil ich verstehe bei "array-to-pointer decay" nicht, was Du meinst...

    Nimm std::string oder such Dir ein anderes Hobby, oder wenigstens ein anderes Forum, bitte.



  • Belli schrieb:

    Nimm std::string oder such Dir ein anderes Hobby, oder wenigstens ein anderes Forum, bitte.

    Ja ok, dann vergesse ich die Idee mit Pointer auf Char...

    Sorry, dass ich überhaupt gefragt habe...



  • Du kannst ruhig fragen, so ist das nicht gemeint! Aber wenn Dich dann mehrere Leute nach dem Sinn fragen und Dir empfehlen, std::string zu nehmen, dann solltest Du vielleicht mal Rat annehmen, sonst macht es keinen Spaß mehr ...


Anmelden zum Antworten