هل يمكن إقناع FGETs C للعمل مع سلسلة * ليس * من ملف؟

StackOverflow https://stackoverflow.com/questions/2068975

  •  20-09-2019
  •  | 
  •  

سؤال

على وجه التحديد ، عينة الكود هنا يعمل بشكل رائع ، ولكن فقط عندما يتم تخزين السلسلة في ملف.

في بعض الأحيان ، أحتاج إلى معالجة سلسلة تم إنشاؤها (مخزنة في متغير سلسلة) ، لكنني أواجه مشكلة في إقناع المعلمة الثالثة لـ FGTS للعمل مع متغيرات السلسلة لأنها مؤشر إلى بنية الملف.

أو ربما يكون هناك ما يعادل وظيفي لـ FGETs التي يمكن استخدامها على الأوتار؟

أي اقتراحات؟ شكرًا!

هل كانت مفيدة؟

المحلول

بروح الاختراق معا إجابات سريعة ، إليك "sgets" التي كتبتها للتو. يحاول محاكاة FGTS ولكن مع إدخال السلسلة.

تعديل تم إصلاح الخلل الذي أشار إليه مونتي (شكرًا). إن الكتابة بجنون من الأداة المساعدة مع الاعتقاد بأن ما لا يقل عن 15 شخصًا آخر لديهم نفس الفكرة بالضبط يفعلون نفس الشيء لا يؤدي إلى رمز تم اختباره جيدًا. لي سيئة. كان الإصدار الأصلي يشمل حرف NewLine على المكالمة التالية.

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

نصائح أخرى

لا توفر مكتبة C القياسية هذه الوظيفة.

لكن AT & T's مكتبة I/O آمنة/سريعة لا يمكّن تدفقات الذاكرة ويوفر أيضًا رمز التفاف لاستخدام واجهة برمجة تطبيقات الملف مع امتداداتها. التحديث الأخير هو من فبراير 2005 ، لذا إما أن قاموا أخيرًا بتوضيح جميع الأخطاء أو لم يعد بإمكانهم تحمل تكاليف الحفاظ عليها الآن لوك ويلسون على كشوف المرتبات :-(

يمكن أن تكون الحزمة تم تنزيله هنا.

SSCANF يجب القيام به. من طبعها دلالات مختلفة.

إذا كانت السلسلة موجودة بالفعل في الذاكرة ، فيمكنك التمييز على الخطوط الجديدة (إما مع strtok إذا كنت بخير مع تحوير السلسلة وإذا لم تكن بحاجة للقلق بشأن إعادة الإدخال ، أو عن طريق الاستخدام يدويًا strchr والنسخ إلى عازلة منفصلة نفسك).

لن تحصل على تحويل خط جديد يعتمد على النظام الأساسي والتي عادة ما تمنحك وظائف stdio ، لذلك ستكون هناك حاجة إلى بعض العناية الإضافية إذا كانت أوتارك في استخدام الذاكرة ، على سبيل المثال ، مقترات خط CRLF.

استخدم أنبوبًا ، ثم افتح الأنبوب fdopen للحصول على FILE *, ، ثم اقرأ من ذلك.


#include <stdio.h>

int main (int argc, char *argv[])
{
    int pipes[2];
    FILE *write;
    FILE *read;
    char buffer[1000];

    pipe (pipes);

    read = fdopen (pipes[0], "r");
    write = fdopen (pipes[1], "w");
    fputs ("My\nlong\nstring\nin\nmany\nlines\n", write);
    fclose (write);

    while (fgets (buffer, sizeof(buffer), read) != NULL)
    {
        printf ("Found a line: %s", buffer);
    }

    fclose (read);

    return 0;
}

كل ما عليك فعله هو إجراء بحث خطي عن نهايات الخط في السلسلة. فيما يلي برنامج صغير لتبدأ في كتابة فئة دفق السلسلة الخاصة بك.

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

لقد قمت بتعديل الكود المصدر لوظيفة FGTS:

size_t  my_fgets( inBuf , n , outBuf )
unsigned char *inBuf;
size_t n;
unsigned char *outBuf;
{
    size_t len = 0;
    unsigned char *s;
    unsigned char *p, *t;

    if (n <= 0)             /* sanity check */
            return (-1);

    p =  inBuf;
    s = outBuf;

    n--;                    /* leave space for NUL */

    while (n != 0) {

        len = n;
        t = memchr((void *)p, '\n', strlen(p));

        //printf ("'p' found at position %d.\n", t -p + 1);

        if (t != NULL) {
            len = ++t -p;
            (void)memcpy((void *)s, (void *)p, len);
            s[len] = 0;
            return len;
        }

        (void)memcpy((void *)s, (void *)p, len);
        s += len;
        n -= len;

    }

    *s = 0;

    return len;

}

والوظيفة الرئيسية:

int main(void)
{
    char *inBuf = "this \n"
                  "is \n"
                  "test \n";

    char outBuf[1024];

    my_fgets(inBuf,strlen(inBuf),outBuf);
    printf("outBuf:%s \n",outBuf);

    return 0;
}

والإخراج:

outBuf:this 
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top