Продолжать получать ошибку сегментации на этом?

Я продолжаю получать ошибку сегментации (ядро сброшено) в коде ниже. Любые идеи о том, почему это происходит. Код предназначен для чтения чисел из текстового документа, преобразования их в целые числа, выполнения радикальной сортировки и распечатки массива.

#include <cstdlib>
#include <iostream>
#include <iomanip>
#include <fstream>
#include <string>
#include <time.h>
#include <sstream>

using namespace std;

int getMax(int arr[], int n)
{
    int max = arr[0];
    for (int i = 1; i < n; i++)
        if (arr[i] > max)
            max = arr[i];
    return max;
}

void countSort(int arr[], int n, int exp)
{
    int output[n];
    int i, count[10] = {0};
    for (i = 0; i < n; i++)
        count[(arr[i] / exp) % 10]++;
    for (i = 1; i < 10; i++)
        count[i] += count[i - 1];
    for (i = n - 1; i >= 0; i--)
    {
        output[count[(arr[i] / exp) % 10] - 1] = arr[i];
        count[(arr[i] / exp) % 10]--;
    }
    for (i = 0; i < n; i++)
        arr[i] = output[i];
}

void radixsort(int arr[], int n)
{
    clock_t clockStart;
    clockStart = clock();

    int m = getMax(arr, n);
    for (int exp = 1; m / exp > 0; exp *= 10)
        countSort(arr, n, exp);

    cout << "\nTime taken by radix sort: " << (double)(clock() - clockStart) / CLOCKS_PER_SEC << endl;
}

int StrToInt(string sti) 
{
    int f;
    stringstream ss(sti); //turn the string into a stream
    ss >> f;
    return f;
}

int main()
{
    int arr[10000];
    int i = 0;
    int result;
    string line = "";

    ifstream myfile;
    myfile.open("integers2.txt");
    if(myfile.is_open())
    {
        while(!myfile.eof())
        {
            getline(myfile, line);
            result = StrToInt(line);
            arr[i] = result;
            //cout<< arr[i] <<"\n";
            i++;
        }
    }


    int n = sizeof(arr)/sizeof(arr[0]);
    radixsort(arr, n);

    for (int i = 0; i < n; i++)
    {
        cout << arr[i] << "\n";
    }

    return 0;
}

Содержание текстового файла, который я использую для ввода: 1244 3455 6565 55 765 8768 687 879

2 ответа

Решение

Ваша программа имеет неопределенное поведение, потому что она использует больше записей массива, чем вы инициализировали с данными. Вы передаете длину всего массива для n хотя только небольшая его часть, от 0 в i, был инициализирован.

Изменить код для использования n на месте i в цикле чтения, и передать это n неизменен для функции сортировки. Это собирается решить проблему ( демо).

int n = 0;
myfile.open("integers2.txt");
if(myfile.is_open()) {
    while (myfile >> arr[n]) {
        n++;
    }
}
radixsort(arr, n);

Вот ваш рабочий код:

#include <cstdlib>
#include <iostream>
#include <iomanip>
#include <fstream>
#include <string>
#include <time.h>
#include <sstream>

using namespace std;

int getMax(int arr[], int n)
{
    int max = arr[0];
    for (int i = 1; i < n; i++)
        if (arr[i] > max)
            max = arr[i];
    return max;
}

void countSort(int arr[], int n, int exp)
{
    int output[n];
    int i, count[10] = {0};
    for (i = 0; i < n; i++)
        count[(arr[i] / exp) % 10]++;
    for (i = 1; i < 10; i++)
        count[i] += count[i - 1];
    for (i = n - 1; i >= 0; i--)
    {
        output[count[(arr[i] / exp) % 10] - 1] = arr[i];
        count[(arr[i] / exp) % 10]--;
    }
    for (i = 0; i < n; i++)
        arr[i] = output[i];
}

void radixsort(int arr[], int n)
{
    clock_t clockStart;
    clockStart = clock();

    int m = getMax(arr, n);
    for (int exp = 1; m / exp > 0; exp *= 10)
        countSort(arr, n, exp);

    cout << "\nTime taken by radix sort: " << (double)(clock() - clockStart) / CLOCKS_PER_SEC << endl;
}

int StrToInt(string sti) 
{
    int f;
    stringstream ss(sti); //turn the string into a stream
    ss >> f;
    return f;
}

int main()
{
    const int MAX_SIZE = 10;

    int arr[ MAX_SIZE ] = { 0 };

    //int i = 0;
    //int result = 0;
    string line = "";

    ifstream myfile;
    myfile.open("integers2.txt");
    if(!myfile.is_open())
    {
        cerr << "Could not open file!\n";
        return -1;
    }

    cout << "Reading integers...\n";

    int index = 0;
    //while ( index < SIZE && getline( myfile, line ) )
    while ( index < MAX_SIZE && myfile >> arr[ index ] )
    {
        //getline( myfile, line );
        //result = StrToInt( line );
        //arr[index] = std::stoi( line );
        cout << arr[index] <<"\n";
        index++;
    }

    cout << "Sorting integers...\n";

    //int n = sizeof(arr) / sizeof(arr[0]);

    radixsort( arr, index );

    for ( int i = 0; i < index; i++ )
    {
        cout << arr[i] << "\n";
    }

    return 0;
}

Некоторые моменты:

  1. Проверьте std:: stoi для преобразования строки в целое число; Кстати, вам не нужно этого делать. Просто прочитайте это прямо так: while ( file >> integer ),
  2. Необходимо проверить, открыт ли файл; в противном случае верните ERROR; в вашем случае остальная часть кода выполнялась в любом случае, даже если файл не был открыт, т.е. код после if ( myfile.open() ) { ... }
  3. while( !myfile.eof() ) это плохая практика. Смотрите: почему iostream:: eof внутри условия цикла считается неправильным?
  4. Вам не нужно рассчитывать размер как int n = sizeof(arr) / sizeof(arr[0]); потому что вы уже знаете размер. Просто используйте const за это.
  5. При чтении из файла вам также необходимо проверить максимальный размер вашего массива. Вы должны прочитать, что позволяет размер. Заботиться о out-of-bounds ошибки чтения / записи.
  6. использование <ctime> вместо <time.h>,
Другие вопросы по тегам