【问题标题】:wrap ungetc() without puts() gets() and streams in general包装 ungetc() 不带 puts() gets() 和一般流
【发布时间】:2017-03-30 21:22:06
【问题描述】:

我正在将 net-snmp 移植到一个只能有限访问文件系统的嵌入式平台,我偶然发现了一个大问题。有一部分核心代码使用了 ungetc() 函数,而我没有。当然有两种解决方案:

A) 使用我拥有的东西编写我自己的 ungetc()

B) 修改 net-snmp 代码以在不使用 ungetc() 的情况下达到相同的结果

解决方案(B)最终将在 net-snmp 编码器邮件列表中讨论,因为需要深入了解库的内部结构,所以让我们关注(A)的可行性

我的嵌入式系统有:

fopen()
fclose()
fcreate()
fwrite()
fread()
fdelete()
fclear()
fcopy()
ffindfirst()
ffindnext()
frename()
fgetsize()
ftell()
fseek()
fgetc()
fgets()

主要区别在于我的文件函数使用 INT32* 文件句柄而不是 FILE* 类型。我没有 FILE* 类型。

ungetc() 函数所做的基本上是“将 char 放回流中”,无论是它刚刚读取的 char 还是另一个。

在第一种情况下,解决方案很简单,我用 fseek() 将指针倒回一个位置。

但在第二种情况下,我遇到了问题。我将修改流而不是文件,除非我没有流!我正在直接读取文件。

使用 ungetc() 你可以做类似的事情

FILE *fp = fopen("file.txt", "r");
int c = getc (fp);
if( c == 'a' ) ungetc ('b', fp);

如果“file.txt”包含“abcdefghi”,随后使用gets() 读取将读取“bbcdefghi”而不是“abcdefghi”,因为流中的内容已更改,而不是文件!

如果我没有“流”,我该如何复制这种行为?我的 getc() 和 gets() 从 INT32* 文件句柄中读取,我没有 puts() 或 putc() 等价物。

我只能使用 fwrite() 写入,但这会改变 NV 内存上的内容。

感谢您的见解

【问题讨论】:

    标签: c ungetc


    【解决方案1】:

    这是我解决它的方法。我为文件句柄创建了一个更复杂的结构,它不仅包含句柄本身,还包含文件名、文件大小和保存文件全部内容的缓冲区。它应该只加载我需要的文件部分,但我的是一个嵌入式应用程序,我知道我不会打开大文件,所以我没有打扰。

    然后,一旦你有了“流”,将字符弹出和弹出是微不足道的。

    typedef struct _myfile {
          _FS_HANDLE        handle; /* file descriptor */
          CHAR*             fname;  /* file name */
          UINT32            fsize;  /* file size */
          CHAR*             buffer; /* file buffer */
      } *my_FILE;
    
    int my_ungetc(int c, my_FILE stream)
    {
        if (stream)
        {
            UINT32 pointer = _fs_tell(stream->handle);
            if (pointer > 0)
            {
                _fs_seek(stream->handle,pointer - 1);
                stream->buffer[pointer - 1] = c;
                return c;
            }
        }
        else
        {
            printf("ERROR! stream is NULL!\r\n");
        }
        return EOF;
    }
    
    void *my_fopen(const char *filename, const char *mode)
    {
        my_FILE fp = _mem_alloc(sizeof(struct _myfile));
        fp->fname = strdup(filename);
        if (mode == "r")
        {
            fp->handle = _fs_open((CHAR*)filename, OPEN_READ);
            if (fp->handle) fp->fsize = _get_size_with_handle(fp->handle);
            if (fp->fsize)
            {
                fp->buffer = _mem_alloc(fp->fsize);
                if (fp->buffer)
                {
                    if (_fs_read(fp->handle,fp->buffer,fp->fsize))
                    {
                        _fs_seek(fp->handle,0);
                    }
                    else
                    {
                        printf("ERROR: unable to read %d bytes from %s\r\n",fp->fsize,filename);
                    }
                }
                else
                {
                    printf("ERROR in my_fopen(\"%s\",\"r\"): could not alloc %d bytes for buffer\r\n",filename,fp->fsize);
                }
            }
            else
            {
                fp->buffer = NULL;
                printf("File \"%s\" is empty\r\n");
            }
            return fp;
        }
        else if (mode == "w")
        {
            fp->handle = _fs_open((CHAR*)filename, OPEN_WRITE);
            if (fp->handle) fp->fsize = _get_size_with_handle(fp->handle);
            fp->buffer = NULL;
            return fp;
        }
        else
        {
            printf("File open mode %s not supported\r\n",mode);
            return NULL;
        }
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2010-12-19
      • 1970-01-01
      • 2021-05-25
      • 2021-07-17
      • 2013-10-24
      • 2021-01-03
      相关资源
      最近更新 更多