读取多个字符串并在 C 中使用多个 case 进行浮动
Read multiple strings and float with multiple cases in C
我这里的主要问题是我有两个字符串和一个浮点数要读取。字符串的大小是 10 个字节,但无论输入是什么我都应该能够读取并将其存储在字符串中。
例如:
如果我的输入是 Hello world!
那么字符串应该是 string = "Hello wor"
如果我的输入是 Hello
那么字符串应该是 string = "Hello"
现在您可能认为这是显而易见的,只需使用 fgets 就可以了吗?但这在读取第二个字符串时会出现缓冲区问题。问题是,我确实找到了一个修复程序,但这涉及到使用 fflush 函数,但它似乎在一些编译器中不起作用。
我搜索了一个替代方案并找到了 while ( getchar() != '\n')
但它实际上不像 fflush 那样工作。
所以我想问的是,无论输入的长度如何,是否有更好的方法来读取字符串?这是我想出的:
#include <stdio.h>
#include <string.h>
int main(int argc, char** argv) {
char nom[10] , prenom[10];
double salaire;
fgets( nom , sizeof( nom ) , stdin );
nom[ strcspn( nom , "\n") ] = 0;
fflush(stdin);
fgets( prenom , sizeof( prenom ) ,stdin );
prenom[ strcspn( prenom , "\n") ] = 0;
fflush(stdin);
scanf("%lf",&salaire);
printf("%s\n",nom);
printf("%s\n",prenom);
printf("%lf\n",salaire);
return 0;
}
如果您希望每个字符串都在自己的行上,您可以使用此解决方案:
#include <assert.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
void ReadLine(char result[], int resultLen)
{
int ch, i;
assert(resultLen > 0);
i = 0;
ch = getchar();
while ((ch != '\n') && (ch != EOF)) {
if (i < resultLen - 1) {
result[i] = ch;
i++;
}
ch = getchar();
}
result[i] = '[=10=]';
}
int main(int argc, char *argv[])
{
char nom[10], prenom[10];
double salaire;
int n;
ReadLine(nom, sizeof(nom));
ReadLine(prenom, sizeof(prenom));
n = scanf("%lf", &salaire);
if (n == 1) {
printf("%s\n", nom);
printf("%s\n", prenom);
printf("%f\n", salaire);
} else {
fprintf(stderr, "Reading salaire failed, number expected\n");
exit(EXIT_FAILURE);
}
return 0;
}
在这种情况下,fgets
在读取输入时包含 '\n'
实际上很有用。如果 \n
出现在字符串的末尾,这意味着 fgets
能够读取整行直到最后。如果是其他字符,则表示 fgets
在到达行尾之前停止并且整行未被读取。我们可以使用它来使用 getchar()
循环来清除 stdin
只有当整行还没有被读取时。
#include <stdio.h>
#include <string.h>
int main(void)
{
char str1[10], str2[10];
fgets(str1, sizeof str1, stdin);
if (str1[strlen(str1) - 1] != '\n')
for (int c; (c = getchar()) != '\n' && c != EOF;);
fgets(str2, sizeof str2, stdin);
if (str1[strlen(str1) - 1] != '\n')
for (int c; (c = getchar()) != '\n' && c != EOF;);
// Now it's safe to remove the \n
str1[strcspn(str1, "\n")] = '[=10=]';
str2[strcspn(str2, "\n")] = '[=10=]';
printf("%s\n%s\n", str1, str2);
}
你甚至可以围绕 fgets
做一个简单的包装器,每当你读到一行时它就会这样做:
char *readln_and_clear(char *buf, size_t bufsz, FILE *stream)
{
if (fgets(buf, bufsz, stream) == NULL)
return NULL;
if (buf[strlen(buf) - 1] != '\n')
for (int c; (c = fgetc(stream)) != '\n' && c != EOF;);
// If you want
buf[strcspn(buf, "\n")] = '[=11=]';
return buf;
}
我这里的主要问题是我有两个字符串和一个浮点数要读取。字符串的大小是 10 个字节,但无论输入是什么我都应该能够读取并将其存储在字符串中。
例如:
如果我的输入是 Hello world!
那么字符串应该是 string = "Hello wor"
如果我的输入是 Hello
那么字符串应该是 string = "Hello"
现在您可能认为这是显而易见的,只需使用 fgets 就可以了吗?但这在读取第二个字符串时会出现缓冲区问题。问题是,我确实找到了一个修复程序,但这涉及到使用 fflush 函数,但它似乎在一些编译器中不起作用。
我搜索了一个替代方案并找到了 while ( getchar() != '\n')
但它实际上不像 fflush 那样工作。
所以我想问的是,无论输入的长度如何,是否有更好的方法来读取字符串?这是我想出的:
#include <stdio.h>
#include <string.h>
int main(int argc, char** argv) {
char nom[10] , prenom[10];
double salaire;
fgets( nom , sizeof( nom ) , stdin );
nom[ strcspn( nom , "\n") ] = 0;
fflush(stdin);
fgets( prenom , sizeof( prenom ) ,stdin );
prenom[ strcspn( prenom , "\n") ] = 0;
fflush(stdin);
scanf("%lf",&salaire);
printf("%s\n",nom);
printf("%s\n",prenom);
printf("%lf\n",salaire);
return 0;
}
如果您希望每个字符串都在自己的行上,您可以使用此解决方案:
#include <assert.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
void ReadLine(char result[], int resultLen)
{
int ch, i;
assert(resultLen > 0);
i = 0;
ch = getchar();
while ((ch != '\n') && (ch != EOF)) {
if (i < resultLen - 1) {
result[i] = ch;
i++;
}
ch = getchar();
}
result[i] = '[=10=]';
}
int main(int argc, char *argv[])
{
char nom[10], prenom[10];
double salaire;
int n;
ReadLine(nom, sizeof(nom));
ReadLine(prenom, sizeof(prenom));
n = scanf("%lf", &salaire);
if (n == 1) {
printf("%s\n", nom);
printf("%s\n", prenom);
printf("%f\n", salaire);
} else {
fprintf(stderr, "Reading salaire failed, number expected\n");
exit(EXIT_FAILURE);
}
return 0;
}
在这种情况下,fgets
在读取输入时包含 '\n'
实际上很有用。如果 \n
出现在字符串的末尾,这意味着 fgets
能够读取整行直到最后。如果是其他字符,则表示 fgets
在到达行尾之前停止并且整行未被读取。我们可以使用它来使用 getchar()
循环来清除 stdin
只有当整行还没有被读取时。
#include <stdio.h>
#include <string.h>
int main(void)
{
char str1[10], str2[10];
fgets(str1, sizeof str1, stdin);
if (str1[strlen(str1) - 1] != '\n')
for (int c; (c = getchar()) != '\n' && c != EOF;);
fgets(str2, sizeof str2, stdin);
if (str1[strlen(str1) - 1] != '\n')
for (int c; (c = getchar()) != '\n' && c != EOF;);
// Now it's safe to remove the \n
str1[strcspn(str1, "\n")] = '[=10=]';
str2[strcspn(str2, "\n")] = '[=10=]';
printf("%s\n%s\n", str1, str2);
}
你甚至可以围绕 fgets
做一个简单的包装器,每当你读到一行时它就会这样做:
char *readln_and_clear(char *buf, size_t bufsz, FILE *stream)
{
if (fgets(buf, bufsz, stream) == NULL)
return NULL;
if (buf[strlen(buf) - 1] != '\n')
for (int c; (c = fgetc(stream)) != '\n' && c != EOF;);
// If you want
buf[strcspn(buf, "\n")] = '[=11=]';
return buf;
}