【问题标题】:more character when reading from file从文件中读取更多字符
【发布时间】:2021-08-24 10:06:32
【问题描述】:

我没有找到与我的问题相关的任何其他内容..所以我们到了。 直截了当,我使用的是 Manjaro x64,并创建了一个纯文本文件,该文件是文件 .c 的输入,代码如下:

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

#define MAX_STRING 50

struct lista
{
    char data;
    struct lista *next;
};
typedef struct lista Nodo;

void read_file(FILE *fp, char *stringa);
Nodo * create_list(char *s);
void print_list(Nodo *lis);

int main(int argc, char *argv[])
{
    if(argc <= 1)
    {
        printf("Error: Not enough parameters\n");
        return 1;
    }
    FILE *fp;
    fp = fopen(argv[1], "r");
    Nodo *lis = NULL;

    if(fp == NULL)
    {
        printf("Error, failed when opening file, does it exist?\n");
        return 1;
    }
    char str[MAX_STRING];
    read_file(fp, str);
    fclose(fp);
    lis = create_list(str);
    print_list(lis);
    printf("\n\n");

    free(lis);
}

void read_file(FILE *fp, char *stringa)
{
    unsigned int i=0;
    char ch;
    while ((ch = fgetc(fp)) != EOF)
    {
        if(ch != '\0')
        {
            *(stringa + i) = ch;
            i++;
        }
    }
}

Nodo * create_list(char *s)
{
    Nodo *headPtr;

    if (*s=='\0')
    {
        return NULL;
    }
    else
    {
        headPtr = (Nodo *) malloc(sizeof(Nodo));
        if (headPtr==NULL)
            return NULL;

        headPtr->data = *s;
        headPtr->next = create_list(s+1);
        return headPtr;
    }
}

void print_list(Nodo *lis)
{
    if(lis == NULL)
        return;
    else
    {
        printf("%c", lis->data);
        print_list(lis->next);
    }
}

.txt 文件:

Hello World!
How are you?

现在,使用 gcc 它说我没有错误,一切都很好,但是 .txt 文件有问题,它添加了更多字符...如下面的输出所示:

[pasquale@pasquale-Manjaro Desktop]$ ./a.out file.txt 
Hello World!
How are you?
11V

[pasquale@pasquale-Manjaro Desktop]$ 

为什么会添加“11V”(每次执行时都会更改)?我认为这是 .txt 文件错误,并尝试使用“nano”或“vi”(读取)从命令提示符进行编辑,但没有任何改变,尝试编辑代码更改但没有任何改变... 然后我还注意到:如果我的文件较长,程序中止执行并结束打印列表

Hello World!
How are you?
Hello World!
How are you?
Hello World!
How are you?
Hello World!
How are you?

如何修复所有这些奇怪的输出?

【问题讨论】:

  • 您的read_file 函数应在字符串末尾添加终止符NUL
  • 它不会改变任何东西,它会在从文件读取时继续在字符串末尾添加一些随机字符
  • "Error, failed when opening file, does it exist?\n" 是一个无用的错误消息。不要问用户问题,告诉用户为什么fopen失败:perror(argv[1]);
  • fgetc 返回一个整数。当c 的类型为char 时,while( (c = fgetc(fp)) != EOF ) 不正确。

标签: c string list file output


【解决方案1】:

您遇到的主要问题是未能将空终止符附加到字符串,并溢出缓冲区。 create_list 依赖于空终止符的存在,但您没有将空终止符写入字符串,因此您的列表构造不正确。 (事实上​​,当程序试图从数组的未初始化成员中读取时,或者当它超出数组边界写入时,程序会表现出未定义的行为。)通过在读取数据时构建列表来避免这两个问题,而不是试图将文件读入固定大小的缓冲区:

#include<stdio.h>                                                                  
#include<stdlib.h>                                                                 
                                                                                   
struct lista {                                                                     
        char data;                                                                 
        struct lista *next;                                                        
};                                                                                 
                                                                                   
struct lista * read_file(FILE *);                                                  
struct lista * create_list(char);                                                  
void print_list(struct lista *);                                                   
void free_list(struct lista *);                                                    
                                                                                   
int                                                                                
main(int argc, char *argv[])                                                       
{                                                                                  
        FILE *fp = argc > 1 ? fopen(argv[1], "r") : stdin;                         
        struct lista *lis;                                                         
        if( fp == NULL ){                                                          
                perror(argv[1]);                                                   
                return 1;                                                          
        }                                                                          
        lis = read_file(fp);                                                       
        fclose(fp);                                                                
        print_list(lis);                                                           
        free_list(lis);
        return 0;                                                           
}                                                                                  
                                                                                   
struct lista *                                                                     
read_file(FILE *fp)                                                                
{                                                                                  
        int ch;   /* Not a char! fgetc returns int */                                                                 
        struct lista *head = NULL;                                                 
        struct lista **tail = &head;                                               
        while( (ch = fgetc(fp)) != EOF ){                                          
                *tail = create_list(ch);                                           
                tail = &((*tail)->next);                                           
        }                                                                          
        return head;                                                               
}
                                                                              
struct lista *                                                                     
create_list(char s)                                                                
{                                                                                  
        struct lista *headPtr = malloc(sizeof *headPtr);                           
        if( headPtr == NULL ){                                                     
                perror("malloc");                                                  
                exit(1);                                                           
        }                                                                          
        headPtr->data = s;                                                         
        headPtr->next = NULL;                                                      
        return headPtr;                                                            
}                                                                                  
                                                                                   
void                                                                               
print_list(struct lista *lis)                                                      
{                                                                                  
        if( lis != NULL ){                                                         
                putchar(lis->data);                                                
                print_list(lis->next);                                             
        }                                                                          
}                                                                                  
                                                                                   
void                                                                               
free_list(struct lista *lis)                                                       
{                                                                                  
        if( lis != NULL ){                                                         
                struct lista *n = lis->next;                                       
                free(lis);                                                         
                free_list(n);                                                      
        }                                                                          
}   

【讨论】:

    【解决方案2】:

    str 没有空终止符,所以,你应该在后面加上*(stringa + i) = '\0';

    while ((ch = fgetc(fp)) != EOF)
    {
        if(ch != '\0')
        {
            *(stringa + i) = ch;
            i++;
        }
    }
    

    您还说您的程序在文件较长的情况下中止执行,这是因为MAX_STRINGstr的长度)为50,如果文件较大,请增加MAX_STRING的值或动态分配str

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-05-23
      相关资源
      最近更新 更多