【问题标题】:Shuffle array (seg fault)洗牌数组(段错误)
【发布时间】:2023-03-30 08:07:01
【问题描述】:

所以我应该创建一个函数来完成: 目的:程序来打乱文本文件的行

  • 将文件读入数组
  • 行数和最大长度
  • 计算数组的最大宽度
  • 获取指向开头的文件指针
  • 为动态字符串数组保留内存
  • 读取一行并存储在分配的内存中
  • 把\n变成\0
  • 从数组中打印行(测试)
  • 随机数组
  • 从数组中打印行(测试)
  • 释放内存并关闭文件

(只是提供一些背景)

但是,当我打印混洗后的数组时,会出现分段错误。有时,它会打印一两个字符串,但有时它只是说“Shuffled Array”,然后我得到一个分段错误。有什么想法吗?

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

// Accepts: command line input
// Returns: 0 if no error

int main(int argc, char *argv[] ){
    int x = 0, i, lineCount = 0, maxLen = 0;
    char line[500], temp;
    FILE *file = fopen( argv[1], "r" );
//  check if file exists
    if (file == NULL){
        printf("Cannot open file\n");
        return 1;
    }
//  Gets lines, max length of string    
    while (fgets(line, sizeof(line), file) != NULL){
        lineCount++;
        if (strlen(line) > maxLen)
            maxLen = strlen(line);
    }
    rewind(file);
    char *lineArray[lineCount];
    while (fgets(line, sizeof(line), file) != NULL) {
            lineArray[x] = malloc(strlen(line));
        if (lineArray[x] == NULL){
            printf("A memory error occurred.\n");
            return(1);
        }
            strcpy(lineArray[x], line);
//  change \n to \0
        lineArray[x][strlen(lineArray[x])-1] = '\0';
        x++;
    }
    printf("File %s has %d lines with maximum length of %d characters\n",
        argv[1], lineCount, maxLen);
    printf("Original Array\n");
    for (x = 0; x < lineCount; x++)
        printf("%2d %s\n", x, lineArray[x]);
//  Shuffle array
    srand( (unsigned int) time(NULL));
    for (x = lineCount - 1; x >= 0; x--){
        i = (int) rand() % lineCount;
        temp = lineArray[x];
        lineArray[x] = lineArray[i];
        lineArray[i] = temp;
    }
    printf("\nShuffled Array\n");
    for (x = 0; x < lineCount; x++)
        printf("%2d %s\n", x, lineArray[x]);
//  free allocated memory
    for (x = 0; x < lineCount; x++)
        free(lineArray[x]);
    free(lineArray);
    fclose(file);
    return 0;
}

【问题讨论】:

  • 如果您对输入字符串进行硬编码,而不是尝试从文件中读取它们会怎样?
  • 你已经问过了,去做你的功课
  • @WorldDominator C 需要编译器在这种情况下发出警告。再次检查,因为如果您没有警告,那么您没有使用 C 编译器。
  • 编译时添加-Wall标志,坦率地说,你应该一直使用它。

标签: c arrays segmentation-fault


【解决方案1】:

在我的机器上运行cc 的输出使错误非常明显。

$ cc tmp.c -o tmp
tmp.c:46:14: warning: incompatible pointer to integer conversion assigning to
      'char' from 'char *'; dereference with * [-Wint-conversion]
        temp = lineArray[x];
             ^ ~~~~~~~~~~~~
               *
tmp.c:48:22: warning: incompatible integer to pointer conversion assigning to
      'char *' from 'char'; take the address with & [-Wint-conversion]
        lineArray[i] = temp;
                     ^ ~~~~
                       &
2 warnings generated.

你需要修复你的变量,你不能在你打算使用char *的地方使用char

对不起,为了更清楚:

char line[500], temp;

应该是:

 char line[500], *temp;

如果您想了解为什么会这样,请告诉我。

最后,在方法的顶部声明变量不是 C 风格的(除非您正在编写嵌入式 C)。将它们声明为尽可能靠近使用点。它使您更容易找到您声明的内容。例如,temp 可以在使用它的循环的正上方声明,或者更好的是,在循环本身中声明。

哦,还有:

$ cc --version
Apple LLVM version 5.0 (clang-500.2.76) (based on LLVM 3.3svn)
Target: x86_64-apple-darwin13.0.0
Thread model: posix

【讨论】:

  • 哦,segfault的确切原因,将指针(char *)转换为char会导致数据丢失,从而使指针完全失效;因为指针只是一个int
  • 指针只是一个 int 这是错误的,绝对不能保证 int 可以保存指针值。
  • 指针在所有平台上都是unsigned int。这个的大小可能会有所不同,你是对的,我忘记了未签名的部分。但是,这是 POSIX 标准,但不幸的是不是 C 标准。不过,很难找到不支持此功能的现代编译器。
  • 谢谢。我对指针感到困惑,我不太关心 gcc 编译器。我似乎拥有您提供的帮助所需的 I/O。
  • @Nava2 指针在所有平台上都是无符号整数 这在 C 和 POSIX 中是错误的。 64 位系统中的 32 位 unsigned int 如何在 64 位地址空间中保存指针?
【解决方案2】:

你在这里做什么?

free(lineArray);

lineArray是一个数组,定义如下:

char *lineArray[lineCount];

你不应该尝试free()它,因为你一开始就没有malloc()它。

最重要的是,这个:

char line[500], temp;

应该是这样的:

char line[500], *temp;

正如你的编译器应该试图告诉你的那样。

可能还有其他问题,但是由于您选择不提供输入文件或提供不需要的程序版本,因此没有人可以编译并运行它来找出答案。

编辑:进行上述更改,按照另一个答案的建议将 lineArray[x] = malloc(strlen(line)); 更改为 lineArray[x] = malloc(strlen(line) + 1);,并使用合适的输入文件,我得到以下输出:

paul@local:~/src/c/scratch$ ./sta testfile
File testfile has 4 lines with maximum length of 13 characters
Original Array
 0 john doe
 1 jane fish
 2 donny brutus
 3 fishy mcgee

Shuffled Array
 0 john doe
 1 jane fish
 2 fishy mcgee
 3 donny brutus
paul@local:~/src/c/scratch$

不过,您确实需要学习更好地使用您的编译器。你应该像这样调用 gcc:

gcc -o myprog myfile.c -std=c99 -pedantic -Wall -Wextra

获取所有最有用的警告。

【讨论】:

  • 对此我深表歉意。我们使用的文件只有最后一个,然后是我自己和其他同学的名字在不同的行中。
猜你喜欢
  • 2015-04-15
  • 2013-06-28
  • 1970-01-01
  • 1970-01-01
  • 2019-02-07
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多