scanf_s einlesen char-Variable



  • Hallo zusammen,

    ich möchte gerne ein Wort mittels scanf_s in eine char-Variable einlesen und diese anschließend über printf ausgeben.

    Dazu habe ich auch Beispiele im Internet gefunden, wenn ich diese jedoch in Visual Studio wie folgend eintrage, wird das debuggen nach der Eingabe bei der scanf_s-Zeile gestoppt, die Zeile mit einem rot umrandeten Kreuz markiert und ein Fenster mit "Ausnahmefehler bei 0xFEFEFEFE in Test.exe: 0xC00001A5: Eine ungültige Ausnahmebehandlungsroutine wurde gefunden (Parameter: 0x00000003)" angezeigt.

    Das scanf geht zudem auch nicht mehr, da zeigt er an, dass dies veraltet sei und man scanf_s nehmen soll/muss.

    Wäre super, wenn mir jemand sagen könnte, was ich verkehrt mache bzw. an was es liegt und wie man es zum laufen bekommt.

    Vielen Dank schon mal.

    Code:

    #include <iostream>
    #include <stdlib.h>
    #include "conio.h"
    #include <string.h>
    #include <stdio.h>
    
    using namespace std;
    
    int main()
    {
        char Name[50];
        printf("Geben Sie einen Namen ein: \n");
        scanf_s(" %s", Name);
        printf("Der Name lautet: %s", Name);
        
        system("pause");
        return 0;
    }


  • @NiV3K88 scanf_s ist kein direkter Ersatz für scanf.

    Das _s steht für secure. Und die braucht bei manchen Formatspecifiern noch zusätzliche Angaben. %s gehört dazu.

    Du speicherst auch nicht in einem char sondern in einem char-Array. Großer Unterschied!

    Du kannst die Warnung auch deaktivieren.



  • Ein halbwegs aktueller Visual Studio Compiler macht bei deinem Coee folgende Ausgabe:

    warning C4473: 'scanf_s' : not enough arguments passed for format string
    1>Test.cpp(13,13): message : placeholders and their parameters expect 2 variadic arguments, but 1 were provided
    1>Test.cpp(13,13): message : the missing variadic argument 2 is required by format string '%s'
    1>Test.cpp(13,13): message : this argument is used as a buffer size
    

    Das erklärt dein Problem in deinem Code meines erachtens sehr gut.

    Ansonsten rate ich eindringlich davon ab, C++ in diesem C-Stil zu lernen und dir stattdessen die std::cout/std::cin-Objekte und die std::string-Klasse anzusehen. Wo immer du das her hast - wirf es in die Tonne. So lernt man als Anfänger (system("pause")) nicht, wie man modernen, fehlerfreien und gut wartbaren C++-Code schreibt.



  • @NiV3K88 sagte in scanf_s einlesen char-Variable:

    int main()
    {
    char Name[50];
    printf("Geben Sie einen Namen ein: \n");
    scanf_s(" %s", Name);
    printf("Der Name lautet: %s", Name);
    system("pause");
    return 0;
    }

    Ich übersetze mal in C++

    #include <iostream>
    #include <string>
    
    int main()
    {
        std::string Name = "";
        std::cout << "Geben Sie einen Namen ein: \n";
        std::cin >> Name;
        std::cout << "Der Name lautet: " << Name << "\n";
        return 0;
    }
    

    Das system("pause") vergisst du schnell mal wieder. Jede Entwicklungsumgebung hat eine Möglichkeit zu verhindern, dass dein Konsolenfenster direkt wieder zu geht.

    Es gibt im Grunde für "printf"/"scanf" und ihre Verwandten keine Verwendung mehr. Man kann eigentlich alles mit Streams lösen. In Sachen Performance sind die Streams allerdings nicht der Knaller, aber sie sind flexibel und vielseitig einsetzbar.



  • @DirkB

    Hallo DirkB, vielen Dank für deine Hilfe.

    Ich dachte ein char ist immer ein Array für Zeichen.

    Die Deaktivierung habe ich leider trotz google noch nicht gefunden bzw. erfolgreich hinbekommen aber vielleicht klappts
    ja noch.

    Da mir aber die anderen Helfer äußerst dringlich davon abraten scanf/printf zu verwenden, werden
    ich mich nun umgewöhnen müssen.



  • @Finnegan

    Hallo Finnegan,

    vielen Dank für deine Hilfe.

    Ich versteh leider nicht, was mit dem 2ten Argument gemeint ist, werde mich nun aber an deinen empfohlenen C-Stil gewöhnen.



  • @It0101

    Hallo It0101,

    auch vielen Dank für deine Hilfe und Übersetzung.



  • @NiV3K88 sagte in scanf_s einlesen char-Variable:

    ... werde mich nun aber an deinen empfohlenen C-Stil gewöhnen.

    @Finnegan hat gerade NICHT C-Stil empfohlen, da du ja offenbar C++ lernen willst. C und C++ haben einiges gemein, aber sind auch unterschiedlich. Insbesondere ist der Stil, wie man programmiert, auch unterschiedlich. Entscheide dich für eine der beiden Sprachen. Wenn du C++ lernen möchtest, verwende keine Lehrmaterialien zu C (und umgekehrt). Leider gibt es häufig Lehrmaterialien (und Bücher), die vorgeben, C++ zu unterrichten, aber in Wirklichkeit einen Mischmasch lehren.

    Ich versteh leider nicht, was mit dem 2ten Argument gemeint ist

    Das scanf_s nimmt einen Formatstring und dann variabel viele Parameter. Wenn du hier in der Doku schaust: https://en.cppreference.com/w/c/io/fscanf, dann findest du die variabel vielen Paramter in den "..." wieder. Dort werden 2 Argumente erwartet, du hast aber nur eines (zusätzlich zum Formatstring) angegeben. Ich zitiere mal aus der Doku:

    Same as (1-3), except that %c, %s, and %[ conversion specifiers each expect two arguments (the usual pointer and a value of type rsize_t indicating the size of the receiving array, which may be 1 when reading with a %c into a single char)

    Das bedeutet, dass du bei %s im Formatstring als weiteren Parameter nicht nur das Ziel, sondern auch die Größe des Ziels angeben musst. Siehe auch das Beispiel in der verlinkten Doku:

        int n = sscanf_s(input, "%d%f%s", &i, &x, str1, (rsize_t)sizeof str1);
        // writes 25 to i, 5.432 to x, the 9 bytes "thompson\0" to str1, and 3 to n.
    

    Der Grund für diesen zusätzlichen Parameter ist die Frage, was passiert, wenn du 50 Zeichen oder mehr eingibst, wo du oben mit char Name[50] ja nur Platz für 49 Zeichen + das \0 hast. In C++ nimmst du einfach std::string und denkst nicht weiter über die maximale Länge eines Namens nach.



  • @NiV3K88 sagte in scanf_s einlesen char-Variable:

    Ich dachte ein char ist immer ein Array für Zeichen.

    Nein.
    Ein char ist nur ein int mit kleinerem Wertebereich, der aber genug Platz für ein Zeichencode bietet.
    Zumindest war es mal so gedacht. Leider ist es systemabhängig, ob char signed oder unsigned ist.

    In einem Array kannst du dann mehrere Zeichen ablegen.

    Aber da du ja jetzt C++ lernst, kannst du für Zeichenketten gleich std::string nehmen



  • @wob und DirkB

    Hallo zusammen,

    vielen Dank für eure ausführliche Hilfe.

    Hmm naja, ehrlich gesagt will ich mitthilfe eines Youtube Tutorials lernen wie man einen Microcontroller programmiert (https://www.youtube.com/watch?v=YHMj2Wom-Vw&list=PLd79x-uW4uyZUTnuAxnIBFj56JhK5io3g&index=13
    --> Minute 37:45).

    Der Tutor schreibt dies mit dem Programm Code::Blocks in C und ich habe
    bisher hierfür Visual Studio verwendet, da bis jetzt hierfür nur eine Konsolen-App von nöten war und bei der Eingabe von einer Zeichenkette beißt es sich nun wie oben beschrieben. Ich habe den Code genau so übernommen, wie er ihn geschrieben hat, bei ihm funktioniert es und bei mir mit Visual Studio eben nicht.

    Im Internet habe ich vor Beginn des Tutorials den Unterschied zwischen C und C++ nachgelesen und hierbei war "nur" die Rede davon, dass C++ die Erweiterung von C ist. Deswegen bin ich ehrlich gesagt davon ausgegangen, dass es nicht sooo schlimm ist, wenn sich dies etwas vermischt bzw. ganz normal ist.



  • @NiV3K88 sagte in scanf_s einlesen char-Variable:

    Im Internet habe ich vor Beginn des Tutorials den Unterschied zwischen C und C++ nachgelesen und hierbei war "nur" die Rede davon, dass C++ die Erweiterung von C ist. Deswegen bin ich ehrlich gesagt davon ausgegangen, dass es nicht sooo schlimm ist, wenn sich dies etwas vermischt bzw. ganz normal ist.

    Das ist auch nicht schlimm, bzw. es ist eine Frage der Sichtweise, der Philosophie wenn man so will, bei manchen vielleicht auch der Religion.



  • @Bashar

    Hey Bashar,

    das beruhigt mich schon mal.

    Ist es dann eine Sünde in diesem Forum eine C-Frage zu stellen? 🙂



  • @NiV3K88 sagte in scanf_s einlesen char-Variable:

    Ist es dann eine Sünde in diesem Forum eine C-Frage zu stellen?

    Nein, dafür gibt es sogar ein extra Unterforum.

    Aber

    #include <iostream>
    
    using namespace std;
    

    ist C++.

    scanf und printf sind z.B. nicht typsicher - also eine Fehlerquelle.
    Warum sollte man das in C++ nutzen, wenn es auch anders geht.



  • @DirkB

    Hey DirkB,

    ah perfekt, habe ich gefunden.

    Vielen Dank



  • Vielen Dank nochmal an alle.

    Top Community 🙂

    Ihr habt mir alle sehr weitergeholfen.



  • @NiV3K88 sagte in scanf_s einlesen char-Variable:

    Hmm naja, ehrlich gesagt will ich mitthilfe eines Youtube Tutorials lernen wie man einen Microcontroller programmiert

    Ohne mir jetzt das Video angesehen zu haben noch eine Bemerkung hierzu: Diese C-Funktionen sind nicht unbedingt in jedem Kontext verwerflich. Wenn man einen guten Grund hat, diese zu verwenden, dann ist das durchaus okay. Mikrocontroller können so ein Grund sein, da iostreams letztendlich recht schwergewichtig ist und ich mir kaum vorstellen kann, dass es viele Mikrocontroller gibt, die mit einem unmodifizierten Standard-iostreams klarkommen.

    C-Funktionen wie printfoder scanf sind da durchaus eine akzeptable Lösung. Eleganter wäre es noch, die Lowlevel-Funktionen, die der Mikrocontroller anbietet, in ein typsicheres Interface zu verpacken - vielleicht so etwas wie ein iostreams-light. Wenn es sowas aber nicht bereits schon gibt, dann ist das allerdings nichts für einen Anfänger, da solltest du besser bei printf bleiben.

    Ich bin übrigens ein Verfechter von C++ auch auf extrem magerer Hardware wie Mikrocontrollern. Mit C kann man nichts machen, dass nicht auch mit C++ ginge und C++ bietet eine Menge Features die einem das Leben im Vergleich zu purem C leichter machen können (Klassen, Destruktoren/RAII, Templates). Im Zweifelsfall kann man auch immer noch de facto ein C-Programm damit schreiben (auch wenn es Stirnrunzeln auslöst) . Der einzige Grund C zu verwenden, wäre für mich, wenn es keinen brauchbaren C++-Compiler für die Zielplattform gäbe.


Log in to reply