来自 malloc() 的流中的随机感叹号但如果删除该行就会消失?我破坏了堆吗?

发布于 2024-11-19 11:52:38 字数 2581 浏览 2 评论 0原文

我不经常使用 C,所以请原谅我在编码风格方面可能犯的任何错误:P 我目前遇到一个错误,我有点困惑:当我包含行 tokenCopy = 时malloc(sizeof(fileSize));,我在文件输出到 std 的过程中大约 1/4 处收到随机感叹号,但如果删除/注释该行,数据将按预期显示:

MAY      +1.32      D1      1002
JUNE     -1.57      D3      201
JULY      -2.37      D4      478
AUGUST      +5.03      D2      930
SEPTEMBER      -3.00      D1      370
OCTOBER      +7.69      D1      112

和实际的当线路就位时我得到的输出:

MAY      +1.32      D1      1002
JUNE      -1.57      D3      2!

以及相关代码:

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


    /**
     * Machine struct - three column
     **/

    /**
     * Parses the input file, size is the size of name
     **/

    char parseInputFile(char *name, int size) {
            FILE *fp;

          if ((fp = fopen(name,"r")) == NULL) {
                printf("Cannot open file %s\n", name);
                return 1;
            }
            else {
                int fileSize;
                fileSize = 0;
                char *fileContent;
                char *processedFileContent;

                //get file size
                fseek(fp, 0, SEEK_END);
                fileSize = ftell(fp);
                fseek(fp, 0, SEEK_SET);

                //allocate
                fileContent = malloc(sizeof(fileSize));
                processedFileContent = malloc(sizeof(fileSize));

                //read
                char c;
                int g;
                g=0;

                while((c = getc(fp)) != EOF) {
                    fileContent[g] = c;
                    g++;
                }

                //process
                char delim[6] = "      ";
                char *tokenCopy;
                tokenCopy = malloc(sizeof(fileSize));

                strcpy(tokenCopy, fileContent);
                char *tokens = strtok(tokenCopy, delim);

                while (tokens) {
                    tokens = strtok(NULL, delim);
                }

                puts(fileContent);
                //printf("File Size: %i \n",fileSize);
                //puts(tokenCopy);
                return *processedFileContent;
            }
    }

    int main(int argc, char *argv[])
    {
            //char *input;
            if (argc == 1)
                puts("You must enter a filename");
            else {
                int size = sizeof(argv[1]);
                parseInputFile(argv[1],size);
            }
            return 0;
    }

任何人都可以提供有关我做错了什么的任何见解(或者我的代码本身是否导致问题)?

I don't work with C often so please excuse any mistakes I might be making in terms of coding style :P I'm currently getting an error that I'm a bit stumped on: when I include the line tokenCopy = malloc(sizeof(fileSize));, I get random a random exclamation about 1/4th of the way through the output of a file to std but if the line is removed/commented, the data displays as expected:

MAY      +1.32      D1      1002
JUNE     -1.57      D3      201
JULY      -2.37      D4      478
AUGUST      +5.03      D2      930
SEPTEMBER      -3.00      D1      370
OCTOBER      +7.69      D1      112

and the actual output I get when the line is in place:

MAY      +1.32      D1      1002
JUNE      -1.57      D3      2!

and the relevant code:

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


    /**
     * Machine struct - three column
     **/

    /**
     * Parses the input file, size is the size of name
     **/

    char parseInputFile(char *name, int size) {
            FILE *fp;

          if ((fp = fopen(name,"r")) == NULL) {
                printf("Cannot open file %s\n", name);
                return 1;
            }
            else {
                int fileSize;
                fileSize = 0;
                char *fileContent;
                char *processedFileContent;

                //get file size
                fseek(fp, 0, SEEK_END);
                fileSize = ftell(fp);
                fseek(fp, 0, SEEK_SET);

                //allocate
                fileContent = malloc(sizeof(fileSize));
                processedFileContent = malloc(sizeof(fileSize));

                //read
                char c;
                int g;
                g=0;

                while((c = getc(fp)) != EOF) {
                    fileContent[g] = c;
                    g++;
                }

                //process
                char delim[6] = "      ";
                char *tokenCopy;
                tokenCopy = malloc(sizeof(fileSize));

                strcpy(tokenCopy, fileContent);
                char *tokens = strtok(tokenCopy, delim);

                while (tokens) {
                    tokens = strtok(NULL, delim);
                }

                puts(fileContent);
                //printf("File Size: %i \n",fileSize);
                //puts(tokenCopy);
                return *processedFileContent;
            }
    }

    int main(int argc, char *argv[])
    {
            //char *input;
            if (argc == 1)
                puts("You must enter a filename");
            else {
                int size = sizeof(argv[1]);
                parseInputFile(argv[1],size);
            }
            return 0;
    }

Could anyone offer any insight into what I'm doing wrong (or if my code is causing problems in itself)?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

不顾 2024-11-26 11:52:39

您将文件的大小放入 fileSize 中,然后仅分配存储 int 的空间,这就是 sizeof(FileSize) 将为您提供的空间。

这两行

            fileContent = malloc(sizeof(fileSize));
            processedFileContent = malloc(sizeof(fileSize));

应该是(假设您将读取的文本视为字符串):

            fileContent = malloc(fileSize+1);
            processedFileContent = malloc(fileSize+1)

并且在读取文件内容后,您应该在末尾添加“\0”。

也就是说,我真的不明白您想通过使用 strtok() 来实现什么目的。如果您只需要分离每一行的三个组成部分,则在读取文件时可以轻松完成,因为您一次读取一个字符。

如果您详细说明您想要实现的目标,我们可能会提供其他建议。

在下面的评论后更新

您应该退一步并重新考虑您的问题,因为我怀疑您根本不需要存储任何字符串。第一个值是月份名称,可以存储为整数,第二个值是双精度(或浮点数),第三个值似乎为“Dx”,其中 x 不同于1 到 4,这也可以是整数。它似乎是一个传感器的名称,所以我怀疑它无论如何都可以用整数编码,因为它们的数量肯定是有限的。第四个显然是另一个整数。

通过对这些字段的含义进行疯狂猜测,您的结构将如下所示:

struct val {
   int month;
   double value;
   int sensor;
   int var;
}

现在,您可以一次读取一个字符来获取值,或者读取一整行并从那里获取值。

每次使用一个字符不需要任何额外的空间,但会导致程序更长(充满“if”和“while”)。阅读该行会稍微容易一些,但需要您处理行的最大尺寸。

正确的函数结构将对您有很大帮助:

 do {
   if ((c = get_month(fp, &month)) != EOF) 
     if ((c = get_value(fp, &value)) != EOF)
       if ((c = get_sensor(fp, &sensor)) != EOF)
         if ((c = get_var(fp, &var)) != EOF)
           measures = add_data(measures, month, value, sensor, var);
 } while (c != EOF);
 return measures

其中 measures 可以是一个链接列表或一个可调整大小的结构数组,并假设您一次只处理一个字符。

在完成之前还有很多其他细节需要设置,我希望这能帮助您找到正确的方向。

You put the size of the file in fileSize but then allocate only the space to store an int that is what sizeof(FileSize) will give you.

These two lines

            fileContent = malloc(sizeof(fileSize));
            processedFileContent = malloc(sizeof(fileSize));

should be (assuming you will treat the text you'll read as a string):

            fileContent = malloc(fileSize+1);
            processedFileContent = malloc(fileSize+1)

and, after having read the file content, you should put a '\0' at the end.

That said, I really don't get what you are trying to achieve by using strtok(). If you only need to separate the three components of each line, you can do it much easily while you read the file since you read it one character at the time.

If you elaborate a little bit more on what you're trying to achieve, we might have other advice.

UPDATE AFTER COMMENT BELOW

You should step back a second and reconsider your problem as I suspect you don't need to store any string at all. The first value is a month name, which can be stored as an integer, the second is a double (or float), the third seems 'Dx' with x varying from 1 to 4, again this could be an integer. It seems the name of a sensor, so I suspect it could be coded in an integer anyway as there will surely be a finite number of them. And the fourth is clearly another integer.

With a wild guess on what those fields mean, your struct would look like something like this:

struct val {
   int month;
   double value;
   int sensor;
   int var;
}

Now, you can get the values as you go one char at the time, or read an entire line and get the values from there.

Going one char at the time will not require any additional space but will result in a longer program (full of 'if' and 'while'). Reading the line will be slightly easier but will require you to handle the maximum size of a line.

A proper structuring of functions will help you a lot:

 do {
   if ((c = get_month(fp, &month)) != EOF) 
     if ((c = get_value(fp, &value)) != EOF)
       if ((c = get_sensor(fp, &sensor)) != EOF)
         if ((c = get_var(fp, &var)) != EOF)
           measures = add_data(measures, month, value, sensor, var);
 } while (c != EOF);
 return measures

Where measures can be a linked list or a resizable array of your structs and assuming you'll go one char at the time.

There are quite many other details you should set before you're done, I hope this will help you find the right direction.

段念尘 2024-11-26 11:52:39

您的 delims 字符串不是以 null 结尾的。

此外,分隔符是逐个字符匹配的,因此重复空格六次是没有用的,对 strtok 的调用也不会匹配连续六个空格。也许您需要类似 strpbrk 的东西。

Your delims string is not null-terminated.

Also, the delimiters are matched character-by-character, so there is no use repeating the space six times, nor will your call to strtok match a run of six spaces. Perhaps you need something like strpbrk.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文