Das spezifische Problem ist, die Sie haben, dass ein scanf
Format-String von %f
Leerraum überspringen wird (einschließlich Zeilenumbrüche), bis sie einen tatsächlichen Charakter findet auf Scan. Vom C99-Standard:
Eine Umwandlungsspezifikation in den folgenden Schritten ausgeführt wird:
- Eingangsleerraumzeichen (wie durch die isspace
Funktion angegeben) werden übersprungen, es sei denn die Beschreibung umfasst ein '['
, 'c'
oder 'n'
Spezifizierer.
und anderswo, beschreibt isspace()
:
Die Standard-Leerraumzeichen die folgenden sind: '\t'
Raum ' '
, Formularvorschub '\f'
, new-line '\n'
, Wagenrücklauf '\r'
, horizontal tab, und vertikale Registerkarte .
Ihre beste Wette ist fgets
zu verwenden, um die Linie zu bekommen (und das kann von Pufferüberlauf sehr leicht geschützt werden), dann sscanf
auf der resultierenden Linie verwenden.
Die scanf
Funktion ist eine jener, die Sie sehr vorsichtig betrachten sollten. Das folgende Stück Code ist, den ich verwende, um oft Line-Eingang handhaben:
#include <stdio.h>
#include <string.h>
#define OK 0
#define NO_INPUT 1
#define TOO_LONG 2
static int getLine (char *prmpt, char *buff, size_t sz) {
int ch, extra;
// Get line with buffer overrun protection.
if (prmpt != NULL) {
printf ("%s", prmpt);
fflush (stdout);
}
if (fgets (buff, sz, stdin) == NULL)
return NO_INPUT;
// If it was too long, there'll be no newline. In that case, we flush
// to end of line so that excess doesn't affect the next call.
if (buff[strlen(buff)-1] != '\n') {
extra = 0;
while (((ch = getchar()) != '\n') && (ch != EOF))
extra = 1;
return (extra == 1) ? TOO_LONG : OK;
}
// Otherwise remove newline and give string back to caller.
buff[strlen(buff)-1] = '\0';
return OK;
}
// Test program for getLine().
int main (void) {
int rc;
char buff[10];
rc = getLine ("Enter string> ", buff, sizeof(buff));
if (rc == NO_INPUT) {
// Extra NL since my system doesn't output that on EOF.
printf ("\nNo input\n");
return 1;
}
if (rc == TOO_LONG) {
printf ("Input too long [%s]\n", buff);
return 1;
}
printf ("OK [%s]\n", buff);
return 0;
}
Testen Sie es mit verschiedenen Kombinationen:
pax> ./prog
Enter string>[CTRL-D]
No input
pax> ./prog
Enter string> a
OK [a]
pax> ./prog
Enter string> hello
OK [hello]
pax> ./prog
Enter string> hello there
Input too long [hello the]
pax> ./prog
Enter string> i am pax
OK [i am pax]
Was ich tun würde, ist zu verwenden, Diese Funktion, um eine Linie sicher zu bekommen, dann einfach verwenden:
sscanf (buffer, "%f %f", &real, &img)
, um die tatsächlichen Werte zu erhalten (und die Anzahl zu überprüfen).
In der Tat, hier ist ein komplettes Programm, das näher ist, was Sie wollen:
#include <stdio.h>
#include <string.h>
#define OK 0
#define NO_INPUT 1
#define TOO_LONG 2
static int getLine (char *prmpt, char *buff, size_t sz) {
int ch, extra;
// Get line with buffer overrun protection.
if (prmpt != NULL) {
printf ("%s", prmpt);
fflush (stdout);
}
if (fgets (buff, sz, stdin) == NULL)
return NO_INPUT;
// If it was too long, there'll be no newline. In that case, we flush
// to end of line so that excess doesn't affect the next call.
if (buff[strlen(buff)-1] != '\n') {
extra = 0;
while (((ch = getchar()) != '\n') && (ch != EOF))
extra = 1;
return (extra == 1) ? TOO_LONG : OK;
}
// Otherwise remove newline and give string back to caller.
buff[strlen(buff)-1] = '\0';
return OK;
}
int main (void) {
int i = 1, rc;
char prompt[50], buff[50];
float real, imag;
while (1) {
sprintf (prompt, "\nEnter real and imaginary for #%3d: ", i);
rc = getLine (prompt, buff, sizeof(buff));
if (rc == NO_INPUT) break;
if (*buff == '\0') break;
if (rc == TOO_LONG) {
printf ("** Input too long [%s]...\n", buff);
}
if (sscanf (buff, "%f %f", &real, &imag) == 2) {
printf ("Values were %f and %f\n", real, imag);
i++;
} else {
printf ("** Invalid input [%s]\n", buff);
}
}
return 0;
}
zusammen mit einem Testlauf:
pax> ./testprog
Enter real and imaginary for # 1: hello
** Invalid input [hello]
Enter real and imaginary for # 1: hello there
** Invalid input [hello there]
Enter real and imaginary for # 1: 1
** Invalid input [1]
Enter real and imaginary for # 1: 1.23 4.56
Values were 1.230000 and 4.560000
Enter real and imaginary for # 2:
pax> _
Falls Sie mehr Gründe brauchten, '' scanf' zu vermeiden: http://c-faq.com/stdio/scanfprobs.html – jamesdlin