Du bist nicht angemeldet.

Stilllegung des Forums
Das Forum wurde am 05.06.2023 nach über 20 Jahren stillgelegt (weitere Informationen und ein kleiner Rückblick).
Registrierungen, Anmeldungen und Postings sind nicht mehr möglich. Öffentliche Inhalte sind weiterhin zugänglich.
Das Team von spieleprogrammierer.de bedankt sich bei der Community für die vielen schönen Jahre.
Wenn du eine deutschsprachige Spieleentwickler-Community suchst, schau doch mal im Discord und auf ZFX vorbei!

Werbeanzeige

DasBlub

Alter Hase

  • »DasBlub« ist der Autor dieses Themas

Beiträge: 802

Wohnort: Schweiz

Beruf: Programmierer

  • Private Nachricht senden

1

22.03.2008, 14:42

toupper für char*

hallo

ich wollte gerade eine konsoleneingabe prüfen. damit der benutzer nicht an gross-/kleinschreibung gebunden ist, wollte ich den ganzen text (char*) mit toupper prüfen. dabei viel mir auf, dass toupper nur für ein char funktioniert

Zitat von »"C/C++ GE-PACKT"«

int toupper(int ch);


um dass nun zu umgehen (ohne strings zu gebrauchen) habe ich nun folgende funktion geschrieben:

C-/C++-Quelltext

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
/**
 * convert a char* to uppercase
 *
 */
char* toupper(const char* pcString) {
    char*  pcRet   = (char*)malloc(sizeof(char)*strlen(pcString)); // the returnstring

    int    i       = 0; // cursor


    if( !pcRet ) // check if the malloc failed

        return pcString; // give the original string back, so the program doesn't crash


    sprintf(pcRet, "%s", pcString); // write the given string in the returnstring


    // step trougth each char

    while(pcRet[i]) {
        pcRet[i] = toupper(pcRet[i]); // convert to uppercase

        i++; // increment the cursor

    }

    return pcRet; // give it back

}


dies kann man nun z.B. so aufrufen:

C-/C++-Quelltext

1
cout << "toupper(\"tEsT\") = " << toupper("tEsT") << endl;

ausgabe:

Zitat

toupper("tEsT") = TEST


ich hoffe, dass dies allen hilft, welche das gleiche problem haben ;)

David Scherfgen

Administrator

Beiträge: 10 382

Wohnort: Hildesheim

Beruf: Wissenschaftlicher Mitarbeiter

  • Private Nachricht senden

2

22.03.2008, 15:04

Komische Funktion.
Der Rückgabewert im Falle eines Fehlers ist schlecht gewählt. Wenn ein Fehler passiert, sollte man das auch merken.
Außerdem sorgt deine Funktion mit großer Sicherheit für Speicherlecks, da der Benutzer immer den String nachher freigeben muss.
Der Speicherbereich, der mit malloc angefordert wird, ist genau 1 Byte zu klein. Das letzte Nullbyte passt nicht rein.
Was soll das mit sprintf? Das ist mit Kanonen auf Spatzen geschossen. Zuerst schreibst du den alten String mit der dafür völlig überdimensionierten Funktion sprintf rein, um dann nachher sowieso jedes einzelne Zeichen wieder zu ersetzen. Sinn?

Kurz: warum benutzt du nicht std::string? Da hast du solche Probleme nicht und brauchst auch nicht solche Verrenkungen zu programmieren.

David Scherfgen

Administrator

Beiträge: 10 382

Wohnort: Hildesheim

Beruf: Wissenschaftlicher Mitarbeiter

  • Private Nachricht senden

3

22.03.2008, 15:17

So sähe das mit std::string aus:

C-/C++-Quelltext

1
2
3
4
5
6
7
const std::string str_to_upper(const std::string& in)
{
    std::string out;
    out.reserve(in.length());
    for(size_t i = 0; i < in.length(); ++i) out.append(toupper(in[i]));
    return out;
}


Kürzer, schneller, schöner, sicherer, ...

4

22.03.2008, 15:31

Geht sowas nicht ?

C-/C++-Quelltext

1
_strupr((char *) String.c_str());

David_pb

Community-Fossil

Beiträge: 3 886

Beruf: 3D Graphics Programmer

  • Private Nachricht senden

5

22.03.2008, 15:42

Zitat von »"TrikkieMikkie"«

Geht sowas nicht ?

C-/C++-Quelltext

1
_strupr((char *) String.c_str());


Nein, das ist nicht Standardkonform.
@D13_Dreinig

6

22.03.2008, 15:53

Mmh. Schade, so schön kurz...
Muß ich wohl noch ein wenig nachsitzen und Standards studieren. :(

David_pb

Community-Fossil

Beiträge: 3 886

Beruf: 3D Graphics Programmer

  • Private Nachricht senden

7

22.03.2008, 16:00

Zitat von »"TrikkieMikkie"«

Mmh. Schade, so schön kurz...
Muß ich wohl noch ein wenig nachsitzen und Standards studieren. :(


Das Problem ist das der Rückgabewert von c_str() nicht zwangsläufig auf die tatsächlichen Daten des string-Objekts referenzieren müssen. D.h. du könntest theoretisch irgendeinen Speicher manipulieren aber nicht die tatsächlichen Stringdaten.
Aber const wegcasten ist ohnehin meißt eine schlechte Idee! :)

Noch eine Lösung (mit lokalisierungs Support):

C-/C++-Quelltext

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
template< typename T >
std::basic_string< T > ToUpper( const std::basic_string< T >& str, std::locale loc = std::locale( "" ) )
{
    struct helper
    {
        typedef std::basic_string< T >::value_type ValueType;

        helper( const std::locale& loc ) : m_loc( loc )
        {
        }

        ValueType operator()( ValueType ch )
        {
            return std::toupper( ch, m_loc );
        }

    private:
        const std::locale& m_loc;
    } ToUpperFun( loc );

    std::string result( str );
    std::transform( result.begin(), result.end(), result.begin(), ToUpperFun );
    return result;
}


Oder für C-Strings halt sowas:

C-/C++-Quelltext

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
void ToUpper( char* str )
{
    char* p = str;

    while ( *p )
    {
        *p = ::toupper( *p );
        ++p;
    }
}

int main()
{
    char buffer[ 256 ];
    strcpy( buffer, "Hallo Welt" );
    ToUpper( buffer );
    printf( "%s\n", buffer );

    std::cin.get();
}


Dabei ist aber zu beachten das ein const char* natürlich nicht übergeben werden darf. Zum Beispiel funktioniert folgendes nicht:

C-/C++-Quelltext

1
2
char* foo = "Hallo Welt"; // Ist eigentlich const char* foo = ...

ToUpper( foo );
@D13_Dreinig

8

22.03.2008, 16:21

Danke für die Info!
Deinen Code werde ich mir die Tage mal zur Brust nehmen. :)

dot

Supermoderator

Beiträge: 9 757

Wohnort: Graz

  • Private Nachricht senden

9

23.03.2008, 12:10

für nullterminierte dinge wie z.b. C strings würd ich sowas in der art machen:

C-/C++-Quelltext

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
#include <iostream>
#include <cctype>


inline char funky_conversion(char c) { return c ^ 42; }

template<typename T, typename Function>
inline T transform(T str, Function op)
{
  for (T s = str; *s; *s = op(*s), ++s);
  return str;
}


int main()
{
  char blub[] = "test";
  std::cout << transform(blub, toupper) << std::endl;
  std::cout << transform(blub, funky_conversion);
  return 0;
}


funktioniert für beliebige operationen (also toupper, tolower oder auch was selbstgemachtes).

David_pb

Community-Fossil

Beiträge: 3 886

Beruf: 3D Graphics Programmer

  • Private Nachricht senden

10

23.03.2008, 12:46

Sowas Ähnliches gibts ja bereits:

C-/C++-Quelltext

1
std::transform( buffer, buffer+10, buffer, ::toupper );
@D13_Dreinig

Werbeanzeige