Vinicius
Vinicius

Reputation: 21

I have problem with reading input with blank spaces

I made this function to get input:

void entrada_dados(Time* time, int i){
    scanf("%s %d %d", time[i].nome, &time[i].gols_marcados, &time[i].gols_sofridos);
};

The input is in this form:

2
Campinense 
23
12
ABC
30
13

The main is:

int main(void) {

  int n = 0;
  scanf("%d", &n);
  
  for(int i = 0; i < n; i++){
    entrada_dados(time, i);
 }
....

My problem is when the team name have some space like to "São Paulo". I have tried some forms to solve, but no one solved my problem.

I tried:

void entrada_dados(Time* time, int i){
    fscanf(stdin, "%[^\n] %d %d", time[i].nome, &time[i].gols_marcados, &time[i].gols_sofridos);
};

and:

void entrada_dados(Time* time, int i){
    fgets(time[i].nome, 100, stdin);
    scanf("%d", &time[i].gols_marcados);
    scanf("%d", &time[i].gols_sofridos);
  }

but in the first case the output have nothing, and second case the output miss some cases. Someone can help me to understand this problem?

Edit 1: The definition of .name is:

typedef struct Time{
  char nome[100];
  int gols_marcados;
  int gols_sofridos;
} Time;

Edit 2:

Solution: One way to solve it:

Try two fscanfs fscanf(stdin, " %[^\n]", time[i].nome);
fscanf(stdin, "%d %d", &time[i].gols_marcados, &time[i].gols_sofridos);

Thank you guys.

Upvotes: 2

Views: 69

Answers (1)

Craig Estey
Craig Estey

Reputation: 33631

Because you have to handle strings with spaces, it's better to use fgets for those.

But mixing fgets and scanf doesn't work too well. We can replace scanf with fgets followed by sscanf.

To decode numbers, we can use strtol or sscanf

We take advantage of the fact that each element/member of Time appears on a separate line in the input file, so we can do fgets for every line. This simplifies the code and makes error checking easier.


Here is the refactored code. It is annotated.

I didn't do this, but, if these sequences are done a lot, we can combine some of these sequences in helper functions to reduce some code replication (e.g. a function that combines the fgets followed by the sscanf)

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

typedef struct Time {
    char nome[100];
    int gols_marcados;
    int gols_sofridos;
} Time;

// RETURNS: 1=valid, 0=syntax error
int
entrada_dados(Time *timelist, int i)
{
    char buf[100];
    char *cp;
    Time *tim = &timelist[i];
    int valid = 0;

    do {
        // get name
        if (fgets(tim->nome,sizeof(tim->nome),stdin) == NULL)
            break;

        // strip newline
        tim->nome[strcspn(tim->nome,"\n")] = 0;

        // get number using strtol
        if (fgets(buf,sizeof(buf),stdin) == NULL)
            break;
        tim->gols_marcados = strtol(buf,&cp,10);
        if (*cp != '\n')
            break;

        // get number using sscanf
        if (fgets(buf,sizeof(buf),stdin) == NULL)
            break;
        if (sscanf(buf,"%d",&tim->gols_sofridos) != 1)
            break;

        // all input is okay
        valid = 1;
    } while (0);

    return valid;
};

int
main(void)
{

    int n = 0;
#if 0
    scanf("%d", &n);
#else
    char buf[100];
    if (fgets(buf,sizeof(buf),stdin) == NULL)
        exit(1);
    sscanf(buf,"%d",&n);
#endif

    // allocate sufficient space
    Time *timelist = malloc(sizeof(*timelist) * n);

    // read in data
    int valid = 0;
    for (int i = 0; i < n; i++) {
        valid = entrada_dados(timelist, i);
        if (! valid)
            break;
    }

    // show the data
    if (valid) {
        for (int i = 0; i < n; i++) {
            Time *tim = &timelist[i];
            printf("nome='%s' gols_marcados=%d gols_sofridos=%d\n",
                tim->nome,tim->gols_marcados,tim->gols_sofridos);
        }
    }

    return 0;
}

Here is the program input:

3
Campinense
23
12
ABC
30
13
São Paulo
17
82

Here is the program output:

nome='Campinense' gols_marcados=23 gols_sofridos=12
nome='ABC' gols_marcados=30 gols_sofridos=13
nome='São Paulo' gols_marcados=17 gols_sofridos=82

Upvotes: 1

Related Questions