2013-12-10 40 views
0

平台:Windows Vista家庭高级版SP2的x86动态获取字符串函数

编译:MinGW的(GCC 4.7.1 TDM-1)(IDE:代码::块)

我写一个函数使用(getc(stdin)!='\ n')相当常见的垃圾收集器循环来编写动态获取字符串函数,该函数将读取标准输入中由fgets()调用留下的任何数据。我正在Windows上编写函数,因为我目前无法访问我的计算机,只是为了让大家知道。但我的问题是我想我的函数dgets()malloc()一个缓冲区,如果指针给它的指针是NULL,但同时我希望函数返回一个整数。所以我对这个问题的解决方案是一个指向字符指针的指针。这个函数会被调用。

char *s = NULL; 
int n = 0; 

if(dgets(&s, &n) != 0) //ERROR 

我不使用指针的指针经常让我有点困惑时,我的功能坠毁。我通过使用下面的循环将问题缩小到了如何解除引用的问题。

char* *s; 
int i = 0; 

*s = malloc(32); 

for(; i < 32; i++) printf("*s[%i] == %c\n", i, *s[i]); 

当上面的代码被编译并运行它崩溃。我的问题是为什么?这里是上下文的功能。附:它尚未测试,但任何意见将不胜感激。

#include <windows.h> 
#include <stdio.h> 
#include <errno.h> 

int dgets(char* *s, size_t *n) 
{ 
    if(n == NULL) return 1; 
    if(*n < 0) return 1; 
    if(*n == 0) *n = 32; 

    if(s == NULL) return 1; 
    if(*s == NULL && (*s = malloc(*n)) == NULL) return 1; 

    int i = 0; 

    for(; i <= *n; i++) *s[i] = 0; 

    if(fgets(*s, *n, stdin) == NULL) return 1; 

    //Since fgets() will put newlines in the buffer, input is line buffered, 
    //and the buffer was initilized to zero if the last element 
    //is a nonzero value and not a newline then there must be a newline left 
    //in stdin. 
    if(*s[*n - 1] != 0 && *s[*n - 1] != '\n') 
    { 
     i = *n; 
     int byte = 0; 

     char *tmp = NULL; 

     for(; (byte = getc(stdin)) != '\n'; i++) 
     { 
      if(byte == EOF) return 1; 

      if(i == *n) 
      { 
       //eventually an arbitrary limit will be put here to limit the 
       //size of the buffer 
       *n *= 2; 

       if((tmp = realloc(*s, *n)) == NULL) return 1; 

       *s = tmp; 
      } 

      *s[i] = (char)byte; 
     } 

     //reallocates the buffer so that it is exact size 
     if(*n != i + 2 && (tmp = realloc(*s, i + 2)) == NULL) return 1; 

     *s = tmp; 
     *n = i + 2; 

     *s[i] = (char)byte; 
     *s[i + 1] = 0; 
    } 

    return 0; 
} 

回答

1

我注意到了两个问题。

  1. 类型不匹配

    int n; 
    if(dgets(&s, &n) != 0) 
    

    dgets原型是INT dgets(字符** S,为size_t * N)

    & N:INT *,但需要size_t *

  2. 外的范围数组访问&解除引用错误

    for(; i <= *n; i++) *s[i] = 0; 
    

    它具有访问该被保留的外部存储器。

    它应该是i < * n and (* s)[i] = 0;

    *s[i]意味着*(s[i])

也有必要改变程序的其余部分按照上述变化。

+0

'0'表示C语言中的错误(失败)。 所以, '返回0'作为发生错误时的值,它可能是合适的。 如果你'返回1', 最好是替换,比如'return DGETS_FAILUER'。 – BLUEPIXY

+0

为了避免混淆 它写成'char * p = * s;'...'p [i]'而不是'(* s)[i]'。 – BLUEPIXY

+0

非常感谢您的回复 –