为什么fopen()无法识别我的文件名?

时间:2017-12-04 09:25:02

标签: c string fopen strstr

程序应该能够打开像myFile.txt这样的文件, 虽然它的真实姓名是myFile而没有扩展名.txt。 所以我按顺序编写了function removeFileExtension() 实现这一点。

它会将stringtext复制到filename打开我的文件:

strcpy(filename,text);
FILE *fp = fopen(filename, "r");

所以我试着检查一下text与我处理的区别 来自string的{​​{1}}是。

要检查它是否有效,我会与名为removeFileExtension的{​​{1}}交配, 如果为qual,则返回function;如果不相等则返回strComparison()。 问题是,在删除文件扩展名后,它会显示两个字符串 是限定的,但我仍然无法打开文件。

当我输入0时,我的比较1会返回./a.out myFile.txt, 它是相同的,但function仍然无法打开文件, 我总是得到一个0

有人在这看到问题吗? 我为什么得到fopen()

Segmentation fault

产生的结果:

Segmentation fault

2 个答案:

答案 0 :(得分:1)

引用C11,第7.24.5.7章

char *strstr(const char *s1, const char *s2);
     

strstr函数在s1指向的字符串中找到第一个匹配项   指向的字符串中的字符序列(不包括终止空字符)   s2

因此,传递给strstr的参数都必须是字符串。在你的情况下,

 char needle[1] = ".";

不是字符串。您没有允许 null-terminator 的空间。使用

  • char needle[2] = ".";,至少,或
  • char needle[ ] = ".";,或
  • char const* needle = ".";

作为副作用,每当达到removeFileExtension()的来电时,您将面对undefined behavior

那就是说,要小心!!

你正在做类似

的事情
retp = strstr(haystack,needle);
  if (*retp == '.')

,即从strstr()取消引用返回的指针。如果,strstr()返回一个NULL指针,你将再次被困在UB中。

编辑:

对于仍然对 string 感到困惑的人,请查看章节§7.1.1中的定义(强调我的

  

字符串是连续的字符序列由第一个空格终止并包括第一个空格   性格。 [...]

答案 1 :(得分:1)

至少我发现了问题:
删除文件的扩展名后,我仍然是 试图打开旧文件指针fp,其中 给了我一个NULL指针。新文件指针 仅在if(fp == NULL){...}的正文内部 存在于if - 声明范围内。

所以我创建了一个test_pointer,首先查看是否 文件甚至存在,如果没有,他删除扩展名。 比我再次尝试打开文件,这次是fp

感谢大家的提示,尤其是 Sourav Ghosh 为了你的改进建议!

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

int removeFileExtension(char *haystack);

int main(int argc, char const *argv[])
{
  char filename[64];
  strcpy(filename, argv[1]);


  //----------------------------------------------------------------------------
  // CHECK INPUT VALIDITY
  //
  if (argc != 2)
  {
    printf("Usage: ./ass2 [file-name]\n");
    return 1;
  }


  //----------------------------------------------------------------------------
  // CHECK FILE EXISTENSE
  //
  FILE *test_pointer = fopen(filename, "r");                             //FOPEN
  if (test_pointer == NULL)   // if not found: remove extension
  {
    int ret_val = removeFileExtension(filename);
    if (ret_val == -1)
    {
      printf("[ERR] Could not remove file extension.\n");
      return 3;
    }
  }


  //----------------------------------------------------------------------------
  // OPEN FILE (INITIAL)
  //
  FILE *fp = fopen(filename, "r");                                       //FOPEN
  if (fp == NULL)   // if still doesn't work: error
  {
    printf("[ERR] Could not read file %s.\n", filename);
    return 3;
  }


  //----------------------------------------------------------------------------
  // READ DATA (INITIAL)
  //
  int bufsize = 1024;
  char *buffer = malloc(bufsize * sizeof(char));                        //MALLOC
  if (!buffer)
  {
    printf("[ERR] Out of memory.\n");
    return 2;
  }
  fseek(fp, 0, SEEK_SET);
  fread(buffer, bufsize, 1, fp);
  fclose(fp);                                                           //FCLOSE

  printf("[DEBUG] %s\n", buffer);
  free(buffer);                                                           //FREE
  buffer = NULL;
  return 0;
}


int removeFileExtension(char *haystack)
{
  char needle[] = ".";
  char *retp;   // return pointer
  retp = strstr(haystack,needle);
  if(!retp)     // to prevent UB
    return -1;

  if (*retp == '.')
  {
    while (*retp != '\0')
    {
      *retp++ = '\0';
    }
    printf("[DEBUG] %s\n", haystack);
  }
  return 0;
}