简体   繁体   English

从 txt 文件读取时指针出现问题

[英]Troubles with pointers when reading from a txt file

Im trying to print out the strings from a txt file in order.我试图按顺序打印出 txt 文件中的字符串。

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

int main(int argc, char *argv[])
{
    // Check for command line args
    if (argc != 2)
    {
        printf("Usage: ./read infile\n");
        return 1;
    }

    // Create buffer to read into
    char buffer[7];
    // Create array to store plate numbers
    char *plates[8];

    FILE *infile = fopen(argv[1], "r");
    int idx = 0;


    while (fread(buffer, 1, 7, infile) == 7)
    {
        char buffer2[7];
        // Replace '\n' with '\0'
        buffer[6] = '\0';
        strcpy(buffer2, buffer);

        // Save plate number in array

        plates[idx] = buffer2;
        idx++;
    }

    for (int i = 0; i < 8; i++)
    {
        printf("%s\n", plates[i]);
    }


}

The pasted code just writes one and the same string over and over again, and I cant for the life of me figure out what Im doing wrong.粘贴的代码只是一遍又一遍地写同一个字符串,我终究无法弄清楚我做错了什么。 When I debug the "while" method, I see that the buffer updates keep overwriting every entry to the plates array.当我调试“while”方法时,我看到缓冲区更新不断覆盖 plates 数组的每个条目。

In this for loop在这个for循环中

while (fread(buffer, 1, 7, infile) == 7)
{
    char buffer2[7];
    // Replace '\n' with '\0'
    buffer[6] = '\0';
    strcpy(buffer2, buffer);

    // Save plate number in array

    plates[idx] = buffer2;
    idx++;
}

you declared a local array with automatic storage duration您声明了一个具有自动存储持续时间的本地数组

    char buffer2[7];

that will not be alive after exiting the loop.退出循环后将不存在。 And all elements of the array plates are set by the address of the first element of the array buffer2 .数组plates的所有元素都由数组buffer2的第一个元素的地址设置。 That is within the for loop they all point to the same extent of memory.也就是说,在 for 循环中,它们都指向相同的范围 memory。

After exiting the loop the pointers will be invalid.退出循环后指针将失效。

You need to allocate character arrays dynamically and their addresses to assign to the elements of the array plates .您需要动态分配字符 arrays 及其地址以分配给数组plates的元素。

Also pay attention to that the function fread does not read a string.另请注意,function fread不会读取字符串。 So this statement所以这个说法

buffer[6] = '\0';

overwrites the last character stored in the array.覆盖存储在数组中的最后一个字符。

Using dynamic allocation should fix your problem.使用动态分配应该可以解决您的问题。 You could try something like this:你可以尝试这样的事情:

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

int main(int argc, char *argv[])
{
    // Check for command line args
    if (argc != 2)
    {
        printf("Usage: ./read infile\n");
        return 1;
    }

    // Create buffer to read into
    char buffer[7];
    // Create array to store plate numbers
    char *plates[8];

    FILE *infile = fopen(argv[1], "r");
    int idx = 0;


    while (fread(buffer, 1, 7, infile) == 7)
    {
        // Replace '\n' with '\0'
        buffer[6] = '\0';

        // Save plate number in array
        plates[idx] = malloc(sizeof(buffer));
        strcpy(plates[idx++], buffer);
    }

    for (int i = 0; i < 8; i++)
    {
        printf("%s\n", plates[i]);
        free(plates[i];
    }
}

The pasted code just writes one and the same string over and over again, and I cant for the life of me figure out what Im doing wrong.粘贴的代码只是一遍又一遍地写同一个字符串,我终究无法弄清楚我做错了什么。 When I debug the "while" method, I see that the buffer updates keep overwriting every entry to the plates array.当我调试“while”方法时,我看到缓冲区更新不断覆盖 plates 数组的每个条目。

@Vlad from Moscow gave you an explanation for this:来自莫斯科的@Vlad给了你一个解释:

that will not be alive after exiting the loop.退出循环后将不存在。 And all elements of the array plates are set by the address of the first element of the array buffer2.数组 plates 的所有元素都由数组 buffer2 的第一个元素的地址设置。 That is within the for loop they all point to the same extent of memory.也就是说,在 for 循环中,它们都指向相同的范围 memory。

"Im trying to print out the strings from a txt file in order." “我试图按顺序打印出 txt 文件中的字符串。”

As noted in comments fread() as used in your implementation is not the best way to read lines in a text file.如评论中所述,您的实现中使用的fread()并不是读取文本文件中行的最佳方式。

Answering these 2 questions (at minimum the first one) will provide important values to help in declaring and initializing the right sized (and shaped) buffers for reading lines from a file...回答这 2 个问题(至少第一个)将提供重要的值,以帮助声明和初始化正确大小(和形状)的缓冲区以从文件中读取行...

  • What is the longest line in the file?文件中最长的一行是什么?
  • How many lines are in the file?文件中有多少行? (may be optional if not storing all lines) (如果不存储所有行,则可能是可选的)

The following example(s) can be accomplished knowing only the answer to the first question, but knowing the answer to the second would be useful if it was necessary for example to store all of the lines into an array of strings.仅知道第一个问题的答案就可以完成以下示例,但如果有必要将所有行存储到字符串数组中,则知道第二个问题的答案将很有用。 (This is out of scope here as you did not list that as a requirement for your code) (这是在 scope 之外,因为您没有将其列为代码的要求)

Unless you are comfortable with making an assumption on the maximum line length, ie hard-coded...除非您对最大行长度做出假设感到满意,即硬编码......

char line[guessed_max_line_length] = {0};  

...a run-time assessment to determine the length of the longest line in the file is necessary to size the buffer such that it can safely contain lines that will later be read from file. ...确定文件中最长行长度的运行时评估对于确定缓冲区大小是必要的,以便它可以安全地包含稍后将从文件中读取的行。 Once this assessment is done, use the length of the longest line to create a line buffer during run-time.完成此评估后,使用最长行的长度在运行时创建行缓冲区。 (dynamically allocate memory): (动态分配内存):

char *line = malloc(max_length + 1);
memset(line, 0, max_length + 1);

Using these methods, (and providing the implementation linked above) your code can be simplified to the following adaptation....使用这些方法,(并提供上面链接的实现)您的代码可以简化为以下改编......

//prototype to get max line length in file
size_t longestLine(FILE *fi);

int main(int argc, char *argv[])
{
    // Check for command line args
    if (argc != 2)
    {
        printf("Usage: ./read infile\n");
        return 1;
    }

    FILE *infile = fopen(argv[1], "r");
    if(infile)
    {
        size_t max_length = longestLine(infile); //see linked implemenation from above
        rewind(infile);//suggest adding this line to longestLine() implementation.
        char *line = malloc(max_length + 1);
        if(line)
        {
            memset(line, 0, max_length + 1);
            while(fgets(line, max_length, infile))
            {
                fputs(line, stdout);
                //or alternatively
                //printf("%s", line);
            }
            free(line);
        }
        fclose(infile);
    }
    return 0;
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM