9
votes

Les fgets de C peuvent-ils être coaxés pour travailler avec une chaîne * non * à partir d'un fichier?

Plus précisément, l'échantillon de code Ici fonctionne bien, mais uniquement lorsque la chaîne est stockée dans un fichier.

Parfois, j'en ai besoin pour traiter une chaîne générée (stockée dans une variable de chaîne), mais j'ai du mal à convaincre le troisième paramètre de Fgets de fonctionner avec des variables de chaîne, car il est Un pointeur à une structure de fichiers .

ou peut-être qu'il y a un équivalent fonctionnel aux fgets pouvant être utilisés sur des chaînes?

Toute suggestion? Merci!


2 commentaires

Êtes-vous bien avec votre chaîne modifiée?


Je suppose. J'ai juste besoin d'un moyen de faire le premier échantillon de code que j'ai lié à accepter l'entrée à partir d'un fichier ou d'une chaîne.


7 Réponses :



3
votes

SSCANF devrait le faire. Bien sûr que la sémantique est différente.


1 commentaires

SSCANF n'arrêtera-t-il pas sur des espaces blanche au lieu de quelques lignes neuves?



2
votes

Si la chaîne est déjà en mémoire, vous pourriez vous rendre sur les nouvelles lignes (avec strtok si vous allez bien avec la chaîne et si vous n'avez pas besoin de vous inquiéter de la réintensif, ni En utilisant manuellement strchr et copie sur un tampon séparé vous-même).

Vous n'obtiendrez pas la conversion nouvelle de la plate-forme dépendante de la plate-forme que les fonctions STDIO vous donneraient normalement vous, cependant, de sorte que des soins supplémentaires seraient nécessaires si vos chaînes en mémoire utilisent, disent, des terminateurs de ligne CRLF.


0 commentaires

1
votes

Tout ce que vous avez à faire est d'effectuer une recherche linéaire de terminaisons de ligne dans la chaîne. Voici un petit programme pour que vous ayez commencé à écrire votre propre classe de diffusion de chaînes.

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

typedef struct StringStream StringStream;

struct StringStream {
    const char *data;
    const char *position;
};

StringStream *
stringstream_new(const char *data)
{
    StringStream *self = malloc(sizeof (StringStream));

    self->data = self->position = data;

    return self;
}

void
stringstream_delete(StringStream *self)
{
    free(self);
}

char *
stringstream_gets(char *s, int n, StringStream *self)
{
    const char * eol;
    int i, len;

    if (NULL == self->position || '\0' == *self->position)
        return NULL;

    eol = strchr(self->position, '\n');

    if (eol) {
        len = eol - self->position + 1;
        len = len <= n ? len : n - 1;

        for (i = 0; i < len; ++i)
            s[i] = *self->position++;

    } else {
        for (i = 0; *self->position && i < n; ++i)
            s[i] = *self->position++;
            if ('\0' == *self->position)
                self->position = NULL;
            else
                ++self->position;
    }

    s[i] = '\0';

    return s;
}

int
main(int argc, char * argv[])
{
    static const int LEN = 100;
    static const char TEST_STRING[] =
        "line 0\n"
        "line 1\n"
        "line 2\n"
        "line 3\n"
        "line 4\n"
        "line 5\n"
        "line 6\n"
        "line 7\n"
        "line 8\n"
        "line 9\n";

    StringStream *stream;
    char buf[LEN];

    stream = stringstream_new(TEST_STRING);

    while (stringstream_gets(buf, LEN, stream))
        printf("gets: %s\n", buf);

    stringstream_delete(stream);

    return 0;
}


0 commentaires

10
votes

Dans l'esprit de piratage ensemble des réponses rapides, voici "Sgets" que je viens d'écrire. Il tente d'émuler des fgets mais avec une entrée de chaîne.

modifier strong> Correction d'un bug que Monte a signalé (merci). En frappant follement une utilité tout en croyant qu'au moins 15 autres personnes avec exactement la même idée font frénétiquement la même chose ne conduit pas à un code bien testé. Mauvais moi. La version originale comprenait le personnage de la nouvelle ligne sur l'appel suivant. P>

char *sgets( char * str, int num, char **input )
{
    char *next = *input;
    int  numread = 0;

    while ( numread + 1 < num && *next ) {
        int isnewline = ( *next == '\n' );
        *str++ = *next++;
        numread++;
        // newline terminates the line but is included
        if ( isnewline )
            break;
    }

    if ( numread == 0 )
        return NULL;  // "eof"

    // must have hit the null terminator or end of line
    *str = '\0';  // null terminate this tring
    // set up input for next call
    *input = next;
    return str;
}


int main( int argc, char* argv[] )
{
    // quick and dirty test
    char *str = "abc\ndefghitjklksd\na\n12345\n12345\n123456\nabc\n\n";
    char buf[5];

    while ( sgets( buf, sizeof( buf ), &str ))
        printf( "'%s'\n", buf );
}


9 commentaires

Obtenir un avertissement de compilateur étrange sur la chaîne littéral de la chaîne de votre exemple: "Avertissement: Conversion obsolète de la chaîne constante sur" Char * "". Google est mon ami, mais je ne l'ai pas encore résolu. Edit: Il semblerait que j'ai compilé cela comme C ++, d'où l'avertissement. Mais toujours, pour la curiosité, je suis intéressé par la manière dont cela serait abordé.


OK, pour le bonheur de la compilation C ++ J'ai fait le suivant "Const": "Char * Sgets", "Char ** Entrée", "Char * Suivant", "Char * Str".


Cela semble correct. Et vous avez raison; Je l'ai compilée comme une application de test C ainsi que ces avertissements ne remarquaient pas ces avertissements.


Je suggère d'utiliser un deuxième pointeur sur la chaîne d'origine. Sinon, vous perdez la référence depuis que STR est modifié par Sgets.


J'ai trouvé un petit problème de compatibilité que je n'ai pas été capable de résoudre jusqu'à présent aujourd'hui - selon la documentation Fgets "Un personnage de nouvelle ligne permet de mettre fin à la lecture, mais il est considéré comme un caractère valide et il est donc inclus dans la chaîne copiée à STR . " Le problème est que ce code comprend le leader NEWLINE, alors que les Fgets incluent le traction Newline Char. Mes efforts de peau de peau ont été en vain - aucune idée?


Le problème que j'ai mentionné ci-dessus est plus facile à voir si vous modifiez "Char BUF [5];" à "Char Buf [32];".


Haha ressemble à quelqu'un qui a déjà eu votre idée: bugs.debian.org/cgi -bin / bugrepor.cgi? bug = 358701 Ils ont aussi une fonction "Sgets"! Je devais aussi faire son retour et son paramètre "Char ** Source", c'est aussi mais il semble fonctionner et traiter le problème de la nouvelle ligne. Merci encore pour toute l'aide !!! Edit: Voici ma version nettoyée: Pastie.org/779971


Merci Monte. Désolé pour ça. Je crois que j'ai réparé cette version.


@Montehurd Que voulez-vous dire par "j'ai fait ce qui suit ... char * str "? La signature de la méthode ne devrait-elle pas être Char * SGETS (Char * STR, INT NUM, CONSTRIS PART ** INPUT) POUR C ++?



2
votes

Utilisez un tuyau, puis ouvrez le tuyau avec fdopen pour obtenir un fichier * , puis lus à partir de celui-ci. XXX


4 commentaires

Pas de vérification des erreurs et d'utilisation de noms de variables ambigu, mauvais, mauvais, très mauvais! (-1)


Que se passe-t-il lorsque mon \ Long \ String \ Nexeeds \ Nthe \ Npipe \ tampon?


@jhfrontz: Votre \ programme \ sera probablement \ nblock \ nwhen \ nCalling \ n fputts .


Donnant "trouvé une ligne: le son d'un coup de main."



0
votes

J'ai modifié le code source de la fonction Fgets de Fgets: xxx pré>

et fonction principale: p> xxx pré>

et sortie: p>

outBuf:this 


0 commentaires