Wie kann ich eine Ganzzahl aus einer Zeichenfolge extrahieren?

8

Ich arbeite an einer Aufgabe und als Teil davon muss ich die Ganzzahl aus einer Zeichenfolge extrahieren.

Ich habe versucht, die atoi()Funktion zu verwenden, aber sie gibt immer a zurück 0, also habe ich auf umgeschaltet strtol(), aber es wird immer noch a zurückgegeben 0.

Ziel ist es, die Ganzzahlen aus der Zeichenfolge zu extrahieren und als Argumente an eine andere Funktion zu übergeben. Ich verwende eine Funktion, die diese Werte verwendet, um einige Daten zu aktualisieren ( update_stats).

Bitte denken Sie daran, dass ich ziemlich neu in der Programmierung in der C-Sprache bin, aber dies war mein Versuch:

void get_number (char str[]) {
    char *end;
    int num;
    num = strtol(str, &end, 10);
    update_stats(num);
    num = strtol(end, &end, 10);
    update_stats(num);
}

Der Zweck ist , in einem String "e5 d8"(zum Beispiel) Ich würde das extrahieren 5und die 8aus dieser Zeichenfolge.

Das Format der Zeichenfolge ist immer gleich.

Wie kann ich das machen?

Ramux05
quelle
1
In diesem Teil des Codes gibt es keinen offensichtlichen Fehler, sodass das Problem nicht reproduziert werden kann.
Lundin
1
Sie können Schleifen verwenden, um alle nicht-stelligen Zeichen zu überspringen, isdigitbevor Sie verwendenstrtol
Bodo
1
Beides atoiund strtolerwarten, den Zeiger auf das erste Zeichen einer Ziffer zu erhalten - Ihr Zeiger muss bereits auf eine Ziffer zeigen. Weder "e" noch "d" ist eine Ziffer, wenn die Basis 10 ist. Um die Ziffern in der Zeichenfolge zu finden, sollten Sie Code schreiben, um jedes Zeichen zu untersuchen, um festzustellen, ob es eine Ziffer ist oder nicht. Sobald Sie eine Ziffer gefunden haben, können Sie sie entweder (nur eine Ziffer) oder die Ziffernfolge (mehrere Ziffern) in eine Zahl umwandeln, je nachdem, was Sie benötigen.
Eric Postpischil
@Lundin: Es gibt einen völlig offensichtlichen Fehler; Das Übergeben eines Zeigers auf das erste Zeichen von "e5 d8"to strtolist kein korrekter Weg, um die „5“ zu finden und in eine Zahl umzuwandeln.
Eric Postpischil
@EricPostpischil In der Tat, wenn das die tatsächliche Eingabe ist. Ohne den aufrufenden Code schwer zu sagen.
Lundin

Antworten:

7

strtolnicht findet eine Zahl in einem String. Es konvertiert die Zahl am Anfang der Zeichenfolge . (Es werden keine Leerzeichen übersprungen, aber sonst nichts.)

Wenn Sie herausfinden möchten, wo eine Nummer beginnt, können Sie Folgendes verwenden:

const char* nump = strpbrk(str, "0123456789");
if (nump == NULL) /* No number, handle error*/

( man strpbrk)

Wenn Ihre Nummern signiert sein könnten, benötigen Sie etwas Anspruchsvolleres. Eine Möglichkeit besteht darin, die oben genannten Schritte auszuführen und dann ein Zeichen zu sichern, wenn das vorherige Zeichen vorhanden ist -. Aber achten Sie auf den Anfang der Zeichenfolge:

if ( nump != str && nump[-1] == '-') --nump;

Nur -in das strpbrkArgument zu setzen, würde falsche Übereinstimmungen bei der Eingabe wie erzeugen non-numeric7.

Rici
quelle
2

Wenn das Format immer so ist, könnte dies auch funktionieren

#include <stdio.h>

int main()
{
    char *str[] = {"a5 d8", "fe55 eec2", "a5 abc111"};
    int num1, num2;

    for (int i = 0; i < 3; i++) {
      sscanf(str[i], "%*[^0-9]%d%*[^0-9]%d", &num1, &num2);
      printf("num1: %d, num2: %d\n", num1, num2);
    }
    return 0;
}

Ausgabe

num1: 5, num2: 8                                                                                                                                                                   
num1: 55, num2: 2                                                                                                                                                                  
num1: 5, num2: 111

%[^0-9]stimmt mit jedem nichtstelligen Zeichen überein. Wenn Sie Folgendes hinzufügen, bedeutet *dies %*[^0-9], dass die Daten aus der Zeichenfolge gelesen, aber ignoriert werden sollen.

Eraklon
quelle
Gute Verwendung von sscanf. Ich schätze die Mühe sehr. Es wird jedoch nirgends angegeben, dass das Format so ist, wie Sie es für selbstverständlich gehalten haben. Versuchen Sie, etwas mehr Großzügigkeit hinzuzufügen, wenn Sie können. Wenn der Benutzer in der Konvertierung von E / A und Zeichenfolge in Ganzzahl steckt, besteht eine hohe Wahrscheinlichkeit, dass er neu ist. Es wäre also sehr hilfreich, einen Link zur Dokumentation hinzuzufügen oder zumindest bereitzustellen, z. B. in diesem Fall sscanf. Schöne Antwort aber :)
d4rk4ng31
1
Gut, danke. Beachten Sie aber auch, dass die Frage "Das Format der Zeichenfolge ist immer das gleiche" lautet, was impliziert, dass dies das gleiche sein könnte. Großzügigkeit ist eine gute Sache, aber das Fehlen davon lässt die Lösung so funktionieren. Der allererste Treffer bei Google sscanfist die Dokumentation. Ich denke, was hier wirklich verbessert werden kann, ist eine kleine Erklärung des Formats, das ich hier hinzufügen darf.
Eraklon
Ja wahr. Es tut uns leid. Ich glaube, ich habe die letzte Aussage verpasst. Schöne Antwort aber :)
d4rk4ng31
2

Ich schlage vor, Sie schreiben die Logik selbst. Ich weiß, es ist, als würde man das Rad neu erfinden , aber in diesem Fall haben Sie einen Einblick in die Funktionsweise der Bibliothek.

Hier ist eine Funktion, die ich vorschlage:

bool getNumber(str,num_ptr)
char* str;
long* num_ptr;
{
    bool flag = false;
    int i = 0;
    *num_ptr = 0;
    char ch = ' ';
    while (ch != '\0') {
        ch = *(str + i);
        if (ch >= '0' && ch <= '9') {
            *num_ptr = (*num_ptr) * 10 + (long)(ch - 48);
             flag = true;
        }
        i++;
    }
    return flag;
}

Vergiss nicht, einen String mit einem \0am Ende zu übergeben :)

d4rk4ng31
quelle
Diese Funktion scannt den gesamten String und gibt eine Zahl zurück, die aus den Ziffern der Reihe nach besteht.
d4rk4ng31
bedenkt c, Sie Bool int und konvertieren können trueund falsezu 1und 0jeweils
d4rk4ng31