【问题标题】:After writing to file from array of characters it says "There was a problem with opening a file"从字符数组写入文件后,它说“打开文件时出现问题”
【发布时间】:2019-02-15 17:02:39
【问题描述】:

我正在编写一个必须反转文件的一半的程序。

例如:

输入:abcdefgh

输出:abcdhgfe

所以,这里我的程序从用户输入中获取并存储在一个文件中。使用fseek,我得到输入的长度并创建一个该长度加1的字符数组。在另一个数组中,我以相反的顺序存储输入的后半部分。问题是,程序将一些奇怪的字符写入文件。打开文件后出现错误提示:There was a problem opening the file “filename”. The file you opened has some invalid characters.。我怎么解决这个问题?

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

int main() {
    int fsize; 
    char fname[15];
    char data[fsize+1];

    printf("Enter the name of file you want to create: ");
    scanf("%s", fname);

    FILE *fp;
    fp = fopen(fname, "w+");

    printf("Enter data for that file: ");
    scanf("%s", data);
    fprintf(fp, "%s", data);

    fseek(fp, 0L, SEEK_END); // get length of file
    fsize = ftell(fp);
    fseek(fp, 0L, SEEK_SET); // go back to the beginning of file

    int j = 0, m = (fsize / 2) + 1;
    char data2[m];

    for (int k = fsize - 1; j < k; j++, k--) {
        data2[j] = data[k];
    }
    for (int i = 0; i < fsize / 2; i++) {
        printf("%c", data2[i]);
    }
    printf("\n");
    fprintf(fp, "%s", data2);
    fclose(fp);
    return 0;
}

【问题讨论】:

    标签: c


    【解决方案1】:

    第一个错误是char data[fsize+1] 行,因为fsize 尚未初始化。此外,数组的大小在编译时是未知的,因此您应该使用malloc/calloc,如in this post 所述。 char data2[m] 行也是如此。

    此外,您通常应尽量避免使用scanf,因为输入超过 14 个字符的文件名会溢出缓冲区fname 并导致错误行为,请参阅this post

    【讨论】:

    • 你开始回答第一个,还有其他几个错误,指出它们;-)
    • 看来你不想要,所以我得到了接力;-)
    【解决方案2】:

    正如 Lukas Koestler 在他的回答中所说的:

    char data[fsize+1];
    

    fsize 是未知的,因此行为是未定义的,请像 fname 一样使用固定大小。

    始终保护您的 (f)scanf,限制读取的长度以留在缓冲区中

    还有:

    检查fopen结果。

    避免使用可变数组维度,实际上你不需要data2

    说实话我不明白你为什么要在文件中写知道输入数据的大小,它是一个字符串,用strlen

    您错过了在文件中写入数据的前半部分,并且 data2 不是以 null 结尾的,因此 fprintf(fp,"%s",data2); 具有未定义的行为

    您没有正确管理只有 1 个字符的空数据。

    你的程序可以是:

    #include <stdio.h>
    #include <string.h>
    
    int main()
    {
      char fname[15];
      char data[100];
    
      printf("Enter the name of file you want to create: ");
      scanf("%14s", fname);
    
      printf("Enter data for that file: ");
      scanf("%99s", data);
    
      size_t sz = strlen(data);
    
      if (sz < 2) {
        puts("data too small");
        return -1;
      }
    
      FILE *fp = fopen(fname, "w+");
    
      if (fp == NULL) {
        printf("cannot open %s\n", fname);
        return -1;
      }
    
      size_t m = sz/2;
      size_t i;
    
      for (i = 0; i != m; ++i) {
        putchar(data[i]);
        fputc(data[i], fp);
      }
    
      for (i = sz - 1; i >= m; --i) {
        putchar(data[i]);
        fputc(data[i], fp);
      }
      putchar('\n');
      fputc('\n', fp);
    
      fclose(fp);
      return 0;
    }
    

    编译和执行:

    pi@raspberrypi:~ $ gcc -g -pedantic -Wextra f.c
    pi@raspberrypi:~ $ ./a.out
    Enter the name of file you want to create: aze
    Enter data for that file: a
    data too small
    pi@raspberrypi:~ $ ./a.out
    Enter the name of file you want to create: aze
    Enter data for that file: az
    az
    pi@raspberrypi:~ $ cat aze
    az
    pi@raspberrypi:~ $ ./a.out
    Enter the name of file you want to create: aze
    Enter data for that file: aze
    aez
    pi@raspberrypi:~ $ cat aze
    aez
    pi@raspberrypi:~ $ ./a.out
    Enter the name of file you want to create: aze
    Enter data for that file: azerty
    azeytr
    pi@raspberrypi:~ $ cat aze
    azeytr
    pi@raspberrypi:~ $ ./a.out
    Enter the name of file you want to create: aze
    Enter data for that file: abcdefgh
    abcdhgfe
    pi@raspberrypi:~ $ cat aze
    abcdhgfe
    

    valgrind下执行,有空就用它

    pi@raspberrypi:~ $ valgrind ./a.out
    ==5321== Memcheck, a memory error detector
    ==5321== Copyright (C) 2002-2017, and GNU GPL'd, by Julian Seward et al.
    ==5321== Using Valgrind-3.13.0 and LibVEX; rerun with -h for copyright info
    ==5321== Command: ./a.out
    ==5321== 
    Enter the name of file you want to create: aze
    Enter data for that file: az
    az
    ==5321== 
    ==5321== HEAP SUMMARY:
    ==5321==     in use at exit: 0 bytes in 0 blocks
    ==5321==   total heap usage: 4 allocs, 4 frees, 6,496 bytes allocated
    ==5321== 
    ==5321== All heap blocks were freed -- no leaks are possible
    ==5321== 
    ==5321== For counts of detected and suppressed errors, rerun with: -v
    ==5321== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 6 from 3)
    pi@raspberrypi:~ $ valgrind ./a.out
    ==5322== Memcheck, a memory error detector
    ==5322== Copyright (C) 2002-2017, and GNU GPL'd, by Julian Seward et al.
    ==5322== Using Valgrind-3.13.0 and LibVEX; rerun with -h for copyright info
    ==5322== Command: ./a.out
    ==5322== 
    Enter the name of file you want to create: aze
    Enter data for that file: azertyu
    azeuytr
    ==5322== 
    ==5322== HEAP SUMMARY:
    ==5322==     in use at exit: 0 bytes in 0 blocks
    ==5322==   total heap usage: 4 allocs, 4 frees, 6,496 bytes allocated
    ==5322== 
    ==5322== All heap blocks were freed -- no leaks are possible
    ==5322== 
    ==5322== For counts of detected and suppressed errors, rerun with: -v
    ==5322== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 6 from 3)
    pi@raspberrypi:~ $ 
    

    【讨论】:

      猜你喜欢
      • 2010-10-12
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多