Für jedes Zeichen in einer Zeichenfolge

228

Wie würde ich eine for-Schleife für jedes Zeichen in einer Zeichenfolge in C ++ durchführen?

Jack Wilsdon
quelle
9
Was für eine Saite? C-String oder std::string?
Mysticial
Es ist in einer aus einer Textdatei gelesen, also gehe ich von std ::
Jack Wilsdon
4
Was für ein Charakter? char, Unicode-Codepunkt, erweiterter Graphemcluster?
Philipp
Mögliches Duplikat von Wie kann ich eine Zeichenfolge durchlaufen und auch den Index (aktuelle Position) kennen? . Mach dir keine Sorgen über den indexTeil in den Antworten.
JWW

Antworten:

416
  1. Durchlaufen der Zeichen von a std::stringmithilfe einer bereichsbasierten for-Schleife (stammt aus C ++ 11 und wird bereits in neueren Versionen von GCC, clang und der VC11-Beta unterstützt):

    std::string str = ???;
    for(char& c : str) {
        do_things_with(c);
    }
  2. Durchlaufen der Zeichen eines std::stringmit Iteratoren:

    std::string str = ???;
    for(std::string::iterator it = str.begin(); it != str.end(); ++it) {
        do_things_with(*it);
    }
  3. Durchlaufen der Zeichen eines std::stringmit einer altmodischen for-Schleife:

    std::string str = ???;
    for(std::string::size_type i = 0; i < str.size(); ++i) {
        do_things_with(str[i]);
    }
  4. Durchlaufen der Zeichen eines nullterminierten Zeichenarrays:

    char* str = ???;
    for(char* it = str; *it; ++it) {
        do_things_with(*it);
    }
R. Martinho Fernandes
quelle
4
@ Robinson: Das ist eine fehlerhafte Annahme. Eine sehr fehlerhafte Annahme. Außerdem hat "Charakter" so viele verschiedene Bedeutungen, dass es am besten ist, den Begriff strikt zu vermeiden.
Welpe
6
@Robinson: "std :: string ist UTF8 (angenommen) " Seit wann?!
Leichtigkeitsrennen im Orbit
2
Nun, OK, es hat keine Codierung, jedoch angesichts der Allgegenwart von utf8 (insbesondere im Web) und der Tatsache, dass man möglicherweise eine einzige konsistente Codierung in einer Pipeline oder Anwendung als Grundlage für diese Diskussion meiner std :: strings wünscht sind alle utf8: p.
Robinson
4
@Robinson: Und alle von mir werden als codierungslos behandelt, weil ich nicht in einer benutzerbezogenen Domäne programmiere (das heißt, es gibt keine Zeichenfolgen, die für Menschen gerendert werden sollen). Wenn Sie sich über Zeichenkodierungen sprechen wollen, müssen Sie über eine höhere Abstraktionsebene sprechen auf der Oberseite std::string , die nur eine Reihe von Bytes.
Leichtigkeitsrennen im Orbit
1
Auch die Fälle 2 und 3 sind ein gutes Beispiel dafür, wo Sie "auto" verwenden können / sollten
galois
29

Eine for-Schleife kann folgendermaßen implementiert werden:

string str("HELLO");
for (int i = 0; i < str.size(); i++){
    cout << str[i];
}

Dadurch wird die Zeichenfolge zeichenweise gedruckt. str[i]Gibt das Zeichen am Index zurück i.

Wenn es sich um ein Zeichenarray handelt:

char str[6] = "hello";
for (int i = 0; str[i] != '\0'; i++){
    cout << str[i];
}

Grundsätzlich gibt es über zwei Arten von Zeichenfolgen, die von c ++ unterstützt werden. Die zweite heißt c string und die erste heißt std string oder (c ++ string). Ich würde vorschlagen, c ++ string zu verwenden, sehr einfach zu handhaben.


quelle
24

In modernem C ++:

std::string s("Hello world");

for (char & c : s)
{
    std::cout << "One character: " << c << "\n";
    c = '*';
}

In C ++ 98/03:

for (std::string::iterator it = s.begin(), end = s.end(); it != end; ++it)
{
    std::cout << "One character: " << *it << "\n";
    *it = '*';
}

Für schreibgeschützte Iterationen können Sie std::string::const_iteratorin C ++ 98 und for (char const & c : s)oder nur for (char c : s)in C ++ 11 verwenden.

Kerrek SB
quelle
Hier sind einige Optionen für Compiler mit teilweiser C ++ 11-Unterstützung: pastebin.com/LBULsn76
Benjamin Lindley
@ BenjaminLindley: Danke! autoist immer eine gute Idee. Bei der Verwendung wird die Unterscheidung zwischen begin()und cbegin()relevant.
Kerrek SB
2
Welche Rolle spielt die Referenz in char here ( char & c)? Ist es nur so, dass der Zeichenwert für den Fall geändert werden kann, dass er benötigt wird?
LunaticSoul
11

Hier ist eine andere Möglichkeit, den Standardalgorithmus zu verwenden.

#include <iostream>
#include <string>
#include <algorithm>

int main()
{
   std::string name = "some string";
   std::for_each(name.begin(), name.end(), [] (char c) {
      std::cout << c;
   });
}
0xBADF00
quelle
Wir haben das Jahr 2018, also sollte dies die richtige Antwort sein.
Erstes
7
const char* str = "abcde";
int len = strlen(str);
for (int i = 0; i < len; i++)
{
    char chr = str[i];
    //do something....
}
Dämoncodemonkey
quelle
4
(Veralteter Kommentar, der wahrscheinlich immer noch für das OP relevant ist :) Die Verwendung strlenin der Schleifenbedingung wird nicht als gute Form angesehen , da für jede Iteration eine O (n) -Operation für die Zeichenfolge erforderlich ist, wodurch die gesamte Schleife zu O (n) wird ^ 2) in der Größe der Zeichenfolge. strlenin der Schleife Bedingung kann aufgerufen werden, wenn sich die Zeichenfolge während der Schleife ändert, sollte jedoch für die Fälle reserviert werden, in denen sie tatsächlich erforderlich ist .
Magnus Hoff
@MagnusHoff: Ja, Schlemiel der Maler reckt wieder seinen hässlichen Kopf.
Fred Larson
Ich habe meine Antwort bearbeitet. Magnus, du hast recht, oops benutzt foreach in c # seit ein paar Jahren;)
Demoncodemonkey
Sie sollten jedoch weiterhin strlen () außerhalb der Schleife verwenden, anstatt in jeder Iteration auf Null zu testen.
McKenzm
4

Ich sehe keine Beispiele für die Verwendung eines Bereichs, der auf einer Schleife mit einer "c-Zeichenfolge" basiert.

char cs[] = "This is a c string\u0031 \x32 3";

// range based for loop does not print '\n'
for (char& c : cs) {
    printf("%c", c);
}

nicht verwandt, aber int Array Beispiel

int ia[] = {1,2,3,4,5,6};

for (int& i : ia) {
    printf("%d", i);
}
10SecTom
quelle
1

Für C-string ( char []) sollten Sie ungefähr Folgendes tun:

char mystring[] = "My String";
int size = strlen(mystring);
int i;
for(i = 0; i < size; i++) {
    char c = mystring[i];
}

Für std::stringkönnen Sie mit str.size()seiner Größe und Iterierte wie das Beispiel bekommen, oder könnte einen Iterator verwenden , um:

std::string mystring = "My String";
std::string::iterator it;
for(it = mystring.begin(); it != mystring.end(); it++) {
    char c = *it;
}
Tiago Pasqualini
quelle
1
for (int x = 0; x < yourString.size();x++){
        if (yourString[x] == 'a'){
            //Do Something
        }
        if (yourString[x] == 'b'){
            //Do Something
        }
        if (yourString[x] == 'c'){
            //Do Something
        }
        //...........
    }

Ein String ist im Grunde ein Array von Zeichen. Daher können Sie den Index angeben, um das Zeichen abzurufen. Wenn Sie den Index nicht kennen, können Sie ihn wie den obigen Code durchlaufen. Wenn Sie jedoch einen Vergleich durchführen, stellen Sie sicher, dass Sie einfache Anführungszeichen verwenden (die ein Zeichen angeben).

Davon abgesehen ist der obige Code selbsterklärend.

fast ein Anfänger
quelle
-1

Sie können jedes Zeichen in einem String erhalten, indem Sie die at-Funktion der String-Bibliothek verwenden, so wie ich es gemacht habe

string words;
    for (unsigned int i = 0; i < words.length(); i++)
        {
            if (words.at(i) == ' ')
            {
                spacecounter++;    // to count all the spaces in a string
                if (words.at(i + 1) == ' ')
                {
                    i += 1;
                }

Dies ist nur ein Teil meines Codes, aber der Punkt ist, dass Sie auf Zeichen zugreifen können, indem Sie stringname.at(index)

Shuja Ul Hasan
quelle