通过 Termial 写入文件名时出现分段错误

Segmentation Fault when writing name of file via Termial

提问人:RMS 提问时间:9/4/2023 最后编辑:Sam VarshavchikRMS 更新时间:9/4/2023 访问量:63

问:

我已经研究了一段时间,但无法弄清楚。 我有以下代码和一个包含 10 个数据点的 test.txt 文件:

int main(){
//opening file for reading ("r").
    char *filename;
    printf("Please enter file name: ");
    scanf("%s", filename);
    FILE *file = fopen(filename,"r");


//Counting total number of data points
    int ch; //store character reading
    while(!feof(file)){
      ch = fgetc(file);
      if(ch == '\n'){
        count++;
      }
    }
      fclose(file);
    printf("it is done \n");
    printf("%i", count);

如果我直接用文件名对它进行编码,它会起作用,并且它成功地计算了 10 个数据点。但是,每当我尝试将其设置为扫描文件名时,一旦我在终端上运行它并收到消息“请输入文件名”,我就会将其写入,并且我总是最终得到“分段错误”。我做错了什么,请帮忙。

C 字符串 文件 scanf

评论

1赞 Pepijn Kramer 9/4/2023
您有“C”或“C++”问题吗?我认为“C”,如果是这样,请删除“C++”标签,C++是一种不同的语言(使用std::string作为字符串而不是char*,std::ifstream而不是FILE*等)。
1赞 Pepijn Kramer 9/4/2023
我记得从“C”中。您似乎没有为文件名分配任何内存。因此,您正在将文件名读入随机内存中。用char[some contant buffer size]
1赞 Ted Lyngmo 9/4/2023
注意:是错误的,您将阅读的最后一个字符将是 。将其更改为while(!feof(file)){ ch = fgetc(file);EOFwhile((ch = fgetc(file) != EOF) {

答:

0赞 hhakim 9/4/2023 #1

该诊断是在 ChatGPT 的帮助下生成的。我确实修改了答案以适应您的问题。 首先,您没有在 while 循环中声明用于递增的变量。 其次,在使用“scanf”函数之前,您需要为指针分配内存countfilename

下面是代码的修改版本:

#include < stdio.h>

int main() {
    char filename[100]; // Allocate memory for the filename
    int count = 0; // Initialize count to zero

    printf("Please enter file name: ");
    scanf("%s", filename);

    FILE *file = fopen(filename, "r");

    if (file == NULL) {
        printf("Unable to open the file.\n");
        return 1; // Exit with an error code
    }

    int ch; // Store character reading
    while ((ch = fgetc(file)) != EOF) {
        if (ch == '\n') {
            count++;
        }
    }

    fclose(file);
    printf("Number of lines in the file: %d\n", count);

    return 0; // Exit with success code
}
```

在此代码中:

  1. filename使用固定大小(最多 100 个字符)声明以存储文件名。
  2. 添加了错误检查案例 (File== NULL) 以确保文件可以成功打开。
  3. Count已声明并初始化为零。
  4. 循环被修改为读取字符,直到文件结束 ()。whileEOF

此代码应正确计算指定文本文件中的行数。确保包括错误处理,以处理文件可能不存在或无法打开的情况。

评论

4赞 Mehdi Charife 9/4/2023
你是用chatGPT生成这个答案的吗?
2赞 Joel 9/4/2023
仅供参考临时政策:禁止生成式 AI(例如 ChatGPT)
1赞 Luke 9/4/2023 #2

就像另一位回答者说的那样,这是一个大小问题,但你也可以将文件名缓冲区设置为 NULL:

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

void read_line_stdin(const char* message, char **buffer) {
  printf("%s", message);
  size_t len;
  int read = getline(buffer, &len, stdin)
  if (read == -1)
    printf("No line read...\n");
}

int main() {
  char *filename = NULL;
  read_line_input("Input filename > ", &filename);
  
  ...
  
  free(filename); // FREE the memory!
}

编辑:

这个答案不是用 ChatGPT 生成的:)

评论

1赞 Oka 9/4/2023
据推测,这是使用 POSIX getline,应该注意的是,它不是严格可移植的(问题没有指定平台)。
1赞 Luis Colorado 9/4/2023 #3
    char *filename;
    printf("Please enter file name: ");
    scanf("%s", filename);
    FILE *file = fopen(filename,"r");

不能使用未初始化的指针(文件名),它必须指向具有足够数据来保存文件名的某个位置。最好使用数组,如下所示:

    char filename[256];
    printf("Please enter file name: ");
    scanf("%.255s", filename);
    FILE *file = fopen(filename,"r");

(我添加了以指示 scanf 您将要阅读最多 256 个字符的文本)或者您甚至可以:.255

    char filename[256];
    printf("Please enter file name: ");
    scanf("%.*s", (sizeof filename) - 1, filename);
    FILE *file = fopen(filename,"r");

(我使用了一对不需要的括号来表示参数值少了一个(为字符串 null 字符的结尾留出空间,因此最大字符串长度仅在一个地方使用,使代码更健壮)sizeof filename

阅读 scanf(3) 的手册页,了解格式说明符的更多细节。