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ürscanf
.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 diestd::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.
-
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.
-
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.
-
-
@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 einfachstd::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.
Einchar
ist nur einint
mit kleinerem Wertebereich, der aber genug Platz für ein Zeichencode bietet.
Zumindest war es mal so gedacht. Leider ist es systemabhängig, obchar
signed
oderunsigned
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.
-
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
undprintf
sind z.B. nicht typsicher - also eine Fehlerquelle.
Warum sollte man das in C++ nutzen, wenn es auch anders geht.
-
-
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
printf
oderscanf
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 einiostreams-light
. Wenn es sowas aber nicht bereits schon gibt, dann ist das allerdings nichts für einen Anfänger, da solltest du besser beiprintf
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.