简体   繁体   中英

Read multiple strings and float with multiple cases in C

My main problem here is that I have two strings and a float to read. The strings' size is 10 bytes, but I should be able to read no matter what input it is and store it inside the strings. For example: if my input is Hello world! then the string should be string = "Hello wor"

if my input is Hello then the string should be string = "Hello"

Now you might think this is obvious, just use fgets right? But that presents buffer problems when reading a second string. The thing is, I did find a fix, but that involves using the fflush function, but it appears that it doesn't work in a few compilers.

I searched for an alternative and found while ( getchar() != '\n') but it actually doesn't work like fflush.

So what I'm asking here is there's a better alternative to read a string no matter the length of the input? This is what I came up with:

#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;
}

If you expect each string to be on its own line you can use this solution:

#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] = '\0';
}


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;
}

In this case, it's actually useful that fgets includes '\n' when reading input. If \n is there at the end of the string, it means that fgets was able to read the whole line till the end. If it's some other character, it means that fgets stopped before reaching the end of the line and the whole line was not read. We can use this to use the getchar() loop to clear stdin only if the whole line has not been read.

#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")] = '\0';
    str2[strcspn(str2, "\n")] = '\0';
    printf("%s\n%s\n", str1, str2);
}

You can even make a simple wrapper around fgets that does this whenever you read a line:

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")] = '\0';
    
    return buf;
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM