读取多个字符串并在 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;
}