简体   繁体   中英

compare string acquired with fgets and fscanf

i need to compare a string acquired from stdin by fgets, with onother one acquired from file by fscanf (and write on file with fprintf). I necessarily have to use the two functions for read from stdin and file. How i can do that? because i've see that fgets store also "\\0" byte, but fscanf no.

this is the code:

#include<stdio.h>
#include<stdlib.h>
#include<string.h>

typedef struct asd {
    char a[20];
    char b[20];
} struttura;


void stampa_file() {
struttura *tmp = NULL;
struttura *letto = NULL;
FILE *file;

tmp = (struttura *)malloc(sizeof(struttura));
letto = (struttura *)malloc(sizeof(struttura));
file = fopen("nuovoFile", "r");
printf("compare:\n");\
fgets(letto->a, sizeof(letto->a), stdin);
fgets(letto->b, sizeof(letto->b), stdin);
while(!feof(file)) {
    fscanf(file, "%s %s\n", tmp->a, tmp->b);
    printf("a: %s, b: %s\n", tmp->a, tmp->b);
    if(strcmp(letto->a, tmp->a) == 0 && strcmp(letto->b, tmp->b)) {
        printf("find matching\n");
    }
}
free(tmp);
free(letto);
}

int main() {
struttura *s = NULL;
FILE *file;

s = (struttura *)malloc(sizeof(struttura));

file = fopen("nuovoFile", "a+");
printf("");
fgets(s->a, sizeof(s->a), stdin);
printf("");
fgets(s->b, sizeof(s->b), stdin);
fprintf(file, "%s%s\n", s->a, s->b);
fclose(file);
stampa_file();

free(s);
return 0;
}

Lots of potential issues here depending on what you are trying to do

  • fgets reads a line (up to and including a newline) whereas fscanf(.."%s"..) reads a token delimited by whitespace. Not at all the same thing.

  • fscanf(.."%s"..) doesn't check the bounds on the buffer you give it to write to. You really want fscanf(.."%19s"..) to ensure that it doesn't write more than 20 bytes (including the NUL terminator) to your 20 byte buffer.

  • while(!feof(fp)) is almost always wrong. feof doesn't tell you if you're at the end of the file, it tells you if you've tried to read past the end of the file. So if you've just read to the end of the file and haven't yet read past it, feof will return false, but the next read will fail.

  • You really want to check the return value of fscanf to make sure it read what you wanted it to read (and actually wrote something to the output buffers.) Combined with the above, it means you probably want your loop to be something like:

     while (fscanf(fp, "%19s%19s", tmp->a, tmp->b) == 2) { : 

How i can do that? because i've see that fgets store also "\\0" byte, but fscanf no.

I just read the documentation for fscanf and tested it, and this worked fine:

#include <stdio.h>

int main()
{
    char str[100] = { 1 }; // intentionally initialized to nonzero junk
    fscanf(stdin, "%s", str);
    if (strcmp(str, "H2CO3") == 0)
        printf("This is me\n");
    else
        printf("This is not me\n");
    return 0;
}

scanf or fscanf when passed with %s terminates the string on newline OR space char. Where as fgets waits until the \\n.

Hence if you call

fscanf(stdin, "%s", str);

vs

fgets(str);

and the file contains "Hello there"

fscanf would only contain "Hello" where as fgets would return the entire string

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