简体   繁体   中英

Reading a string with blank spaces

I'm trying to read a file using a structure, seems all fine until I face a string with spaces, let me give you an example.

In my file I've got text like this:

Luca 21 Università di Palermo 22.3

I can read all the row, but when I arrive at the third element which is the university, it reads only the "Università" and not the rest. I've tried using [^\t\n] but then it reads the next information also and I don't want this. This is the code:

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

typedef struct{
    char nome[30];
    int eta;
    char universita[30];
    double media;
}Studente;

int main(int argc, char** argv){

    FILE* fp;
    Studente s;
    if((fp=fopen("studenti.txt", "r ")) == NULL){
        perror("fopen");
        exit(1);
    }

    char buffer[200];   //tipicamente 200 caratteri stanno su una riga
   // fgets(buffer, 200, fp);  //facciamo una prima lettura
    
    /*while(!feof(fp)){
        sscanf(buffer, " %s %d %s %f", &s.nome, &s.eta, &s.universita, &s.media); //assegnamo il valore della stringa contenuta nel buffer ai tre indirizzi di memoria
        printf("Lo studente si chiama: %s\n", s.nome);
        printf("Ha %d anni\n", s.eta);
        printf("Frequenta %s\n", s.universita);
        printf("Ha una media del %6f\n", s.media);
        fgets(buffer, 200, fp); //continuiamo a leggere
    }*/

    while(fgets(buffer, sizeof(buffer), fp)){
        sscanf(buffer, " %s %d %s %f", s.nome, &s.eta, s.universita, &s.media); //assegnamo il valore della stringa contenuta nel buffer ai tre indirizzi di memoria
        printf("Lo studente chiama: %s\n", s.nome);
        printf("Ha %d anni\n", s.eta);
        printf("Frequenta %s\n", s.universita);
        printf("Ha una media del %lf\n", s.media);
        printf("\n");
    }

    fclose(fp);

    return 0;
}

The output that I want is: The name is X He is y He goes at z His score is k

Thanks in advance.

Assuming:

  • Student name does not include spaces.
  • University name may contain spaces but does not include digits.
  • Average (media) does not start with a dot, such as .12 .

Then would you please try:

#include <stdio.h>
//#include <stdlib.h>
//#include <string.h>
//#include <ctype.h>
#define FILENAME "studenti.txt"

typedef struct {
    char nome[30];
    int eta;
    char universita[30];
    double media;
} Studente;

/*
 * removes trailing spaces of str by modifying the array str
 */
char *trimright(char *str)
{
    char *p;
    for (p = str; *p != '\0'; p++);
    for (--p; p - str >= 0 && (*p == ' ' || *p == '\t') ; p--) {
        *p = '\0';
    }
    return str;
}

int main(int argc, char **argv)
{
    FILE *fp;
    Studente s;
    char buffer[200];   // tipicamente 200 caratteri stanno su una riga
    int n;              // count the number of elements

    if ((fp = fopen(FILENAME, "r")) == NULL) {
        perror(FILENAME);
        exit(1);
    }

    while (fgets(buffer, sizeof(buffer), fp)) {
        n = sscanf(buffer, "%s %d %[^0-9] %lf", s.nome, &s.eta, s.universita, &s.media);
        if (n == 4) {
            printf("Lo studente chiama: %s\n", s.nome);
            printf("Ha %d anni\n", s.eta);
            printf("Frequenta %s\n", trimright(s.universita));
            printf("Ha una media del %f\n", s.media);
        } else {
            printf("Possible format error with: %s", buffer);
        }
        printf("\n");
    }

    fclose(fp);
    return 0;
}

The identifier %[^0-9] makes sscanf read characters other than digits. then the parsed string s.universita may contain trailing space character(s). The function trimright is applied to trim them. If you don't mind including trailing space characters, you don't need to use the function.

If you want to allow digits in the university name, please let me know.

Use strrchr to find the last space in the record.
From that pointer, try to scan a double.
Try to scan a string and an integer from the record. The %u specifier will store the number of characters processed by the scan.
Subtract the pointers to get the number of characters to the last space.
Subtract the number of characters processed to get the the number of characters in the remaining sub-string.
strncpy the sub-string, making sure to set the zero terminator.

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

typedef struct{
    char nome[30];
    int eta;
    char universita[30];
    double media;
}Studente;

int main ( void) {
    char buffer[200] = "Luca 21 Università di Palermo 22.3";
    char *space = NULL;
    int count = 0;
    Studente s = { "", 0, "", 0.0};

    if ( ( space = strrchr ( buffer, ' '))) { // pointer to last space
        if ( 1 == sscanf ( space, "%lf", &s.media)) {
            if ( 2 == sscanf ( buffer, "%29s%d %n", s.nome, &s.eta, &count)) {
                int length = (int)(space - buffer) - count;
                if ( length > 0 && length < sizeof s.universita) {
                    strncpy ( s.universita, buffer + count, length);
                    s.universita[length] = 0;

                    printf ( "%s\n", s.nome);
                    printf ( "%d\n", s.eta);
                    printf ( "%s\n", s.universita);
                    printf ( "%f\n", s.media);
                }
                else {
                    fprintf ( stderr, "Sub-string is too long\n");
                }
            }
            else {
                fprintf ( stderr, "Could not scan string and integer\n");
            }
        }
        else {
            fprintf ( stderr, "Could not scan double\n");
        }
    }
    else {
        fprintf ( stderr, "Could not find a space\n");
    }
    return 0;
}

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