【问题标题】:Why won't this work ? Dynamic memory beginner program为什么这行不通?动态记忆初学者程序
【发布时间】:2016-04-18 23:43:53
【问题描述】:
int main()
{   
    //FILE *out = fopen("keimeno.txt", "w+");

    FILE *in = fopen("keimeno.txt", "r");
    int fullbufflen=0 , i;

    char buffer[100];
    fgets(buffer, 100, in);

    int bufflen = strlen(buffer);
    char *text;
    text =calloc(bufflen,sizeof(char));
    char *strcat(text, buffer); 
    //  printf("line of \"keimeno.txt\": %s", buffer);
    //  printf("size of line \"keimeno.txt\": %i\n\n", bufflen);

    fullbufflen = bufflen;  

    while(fgets(buffer, 100, in)!=NULL)
    {         
        //  printf("line of \"keimeno.txt\": %s", buffer);
        //  printf("size of line \"keimeno.txt\": %i\n\n", bufflen);
        text =realloc(text,bufflen*sizeof(char));
        char *strcat(text, buffer);

        fullbufflen = bufflen + fullbufflen ;
    }
    for (i = 0;i<fullbufflen;i++)
    {
        printf("%c\n",text[i]);
    }
}

我正在尝试将全文文件 (keimeno.txt) 复制到动态内存数组中,每次最多使用 100 个字符的缓冲区。最后为了测试它,我试图打印结果。我就是不能让它工作。不知道是不是最后的printf有问题,还是整个程序出错了。

此外,动态数组在开始时应该有 0 大小,所以如果有人也能告诉我该怎么做,那将是受欢迎的。

提前致谢。

【问题讨论】:

标签: c file dynamic malloc realloc


【解决方案1】:

有几个问题:

char *strcat(text, buffer);

这不是你调用函数的方式。这是一个函数声明,不正确,因为它没有定义参数的类型。

要拨打strcat,只需这样做:

strcat(text, buffer);

接下来,您没有为缓冲区分配足够的空间:

text =calloc(bufflen,sizeof(char));

您需要为终止字符串的空字节添加空间:

text =calloc(bufflen + 1,sizeof(char));

这里也一样:

text =realloc(text,bufflen*sizeof(char));

这只会重新分配总共bufflen 个字节。它不会将bufflen 字节添加到已分配的内容中,并且bufflen 与首次在while 循环之外设置时相比没有变化。改为这样做:

bufflen = strlen(buffer);
text =realloc(text,bufflen+fullbufflen+1);

这为当前长度、附加缓冲区和空字节提供了足够的空间。

最后,确保你最后fclose(in)free(text)清理你的资源,一定要检查fopen的返回值确保文件打开成功,realloc/@ 987654336@ 以确保您的分配有效。

经过上述修改后,您的代码应如下所示:

int main(void)
{
    //FILE *out = fopen("keimeno.txt", "w+");

    FILE *in = fopen("keimeno.txt", "r");
    if (in == NULL) {
        perror("open failed");
        exit(1);
    }
    int fullbufflen=0 , i;

    char buffer[100];
    fgets(buffer, 100, in);

    int bufflen = strlen(buffer);
    char *text;
    text =calloc(bufflen+1,sizeof(char));
    if (text == NULL) {
        perror("calloc failed");
        exit(1);
    }
    strcat(text, buffer);
//  printf("line of \"keimeno.txt\": %s", buffer);
//  printf("size of line \"keimeno.txt\": %i\n\n", bufflen);

    fullbufflen = bufflen;

    while(fgets(buffer, 100, in)!=NULL)
    {
    //  printf("line of \"keimeno.txt\": %s", buffer);
    //  printf("size of line \"keimeno.txt\": %i\n\n", bufflen);
        bufflen = strlen(buffer);
        text =realloc(text,bufflen+fullbufflen+1);
        if (text == NULL) {
            perror("realloc failed");
            exit(1);
        }
        strcat(text, buffer);

        fullbufflen = bufflen + fullbufflen ;
    }
    fclose(in);
    for (i = 0;i<fullbufflen;i++)
    {
        printf("%c\n",text[i]);
    }
    free(text);
}

【讨论】:

  • 非常感谢您付出的努力。这几乎是完美的,但据我所知,它只显示整个文本的一部分,在 txt 文件中我有一个大约 600 个字符的文本它只会显示 300 或其他东西。我发现这个奇怪的原因,因为它可以工作并且缓冲区是 100c ,为什么它会卡在这样的数字中?
  • @begginer3 我通过程序运行了这个源代码,它读写了整个程序。它的打印方式是每行输出一个字符,因此可能很难看到。尝试在最后取出printf 中的\n,看看输出是什么样的。
  • 此尝试存在许多问题。 (1) 没有错误检查。 (2) 长输入线是个问题。 (3) 主签名错误
  • @JohnHascall 长线不是问题。对fgets 的下一次呼叫将在中断处继续。我用超过 100 个字符的行进行了测试,它仍然有效。我确实更改了main 签名并将错误检查添加到fopencalloc/realloc
  • @JohnHascall 你能否详细说明一下,以便我修复它们?
【解决方案2】:

这是一种可能的解决方案:

#include <stdio.h>
#include <fcntl.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>


#define ERR     (-1) 
#define GROW    100


static void die ( const char * msg ) { perror(msg); exit(1); }


int main ( void ) {

        char *  filename        = "in.txt";
        size_t  buffSize        = 0;
        size_t  buffUsed        = 0;
        ssize_t bytesRead       = 0;
        char *  buffer          = NULL;
        char *  tmp;
        int     fd;

        fd = open(filename, O_RDONLY, 0);
        if (fd == ERR) die("open");

        do {
                buffUsed += (size_t)bytesRead;
                if (buffUsed == buffSize) {
                        tmp = realloc(buffer, buffSize += GROW);
                        if (tmp == NULL) die("realloc");
                        buffer = tmp;
                }
                bytesRead = read(fd, buffer + buffUsed, buffSize - buffUsed);
                if (bytesRead == ERR) die("read");
        } while (bytesRead > 0);

        if (write(STDOUT_FILENO, buffer, buffUsed) == ERR) die("write");
        free(buffer);
        if (close(fd) == ERR) die("close");

        return 0;
}

与原始文件一样,输入文件名是硬编码的,次优...

【讨论】:

  • 感谢您的努力,但我觉得这对我的教授来说似乎很重要,因为我们根本没有触及您一直在使用的一些东西。还是谢谢。
  • 是的,如果这是一项作业,您绝对应该上交自己的工作,但请随时为您将来的作业提供一些指导:(1) 检查错误,(2) 使用正确的变量类型,(3)不要在代码中粘贴“魔术”数字,使用#defines,(4)空格有助于提高可读性,(5)编译时打开警告
  • 感谢您的建议,但您对“神奇”数字的含义是什么,给我一个例子,以便我解决它。
  • 除了 0、1 和无穷大之外,几乎任何数字都是“神奇”数字。想象一下阅读别人的代码并看到ipy = 1512; 这是一个神奇的数字。这是什么意思?谁知道?但是,如果您看到 ipy = INNINGS_PER_YEAR;,那么您一看到它就开始有意义。
猜你喜欢
  • 2016-01-18
  • 2015-12-07
  • 1970-01-01
  • 1970-01-01
  • 2014-06-22
  • 2011-09-05
  • 1970-01-01
相关资源
最近更新 更多