Попытка отсортировать массив

194
22 февраля 2018, 14:41
#include <iostream>
#include <vector>
#include <string>
#include <cstdlib>
#include <algorithm>
int main()
{
// Поддержка кириллицы в консоли Windows
system("chcp 1251 > nul");
// Создание вектора из строк
std::vector<std::string> students;
// Буфер для ввода фамилии студента
std::string buffer = "";
std::cout <<"\n\t "<<  "     Вводите фамилии студентов. "
          <<"\n\t"<< "По окончание ввода введите пустую строку"<<"\n "<< 
std::endl;
do {
    std::getline(std::cin, buffer);
    if (buffer.size() > 0) {
        // Добавление элемента в конец вектора
        students.push_back(buffer);
    }
} while (buffer != "");

// Сохраняем количество элементов вектора
int vector_size = students.size();     //unsigned   !@!!!!!!!!!    
std::cout <<"\n"<<std::endl;
// Вывод заполненного вектора на экран
std::cout<< "\t"<< "Ваш вектор." << std::endl;
for (int i = 0; i < vector_size; i++) {    //
    std::cout<<"\t"<<i+1<<". " << students[i] << std::endl;
}
std::cout <<"\n"<<std::endl;
std::sort(students.begin(), students.end());
for (int i = 0; i < vector_size; i++){
    std::cout <<"\t"<<i+1<<". "<< students[i] << std::endl;
}
return 0;
}

Все поправил.Только с выводом Фамилий не пойму, как сделать, чтобы 
печаталось на крае с отступом  "\t"
Answer 1

Разбор полетов

Самый главный совет: Прислушивайтесь к компилятору

  1. Неиспользуемые переменные

    temp.c:242:6: warning: unused variable 'str_spisok' [-Wunused-variable]
    char str_spisok[29][19], str[19];
    temp.c:240:18: warning: unused variable 'c' [-Wunused-variable]
    int i, a, b, c, n;
    

    Что говорит компилятор?

    Предупреждение: неиспользуемая переменная str_spisok.
    Предупреждение: неиспользуемая переменная c.

    Что делаем мы?

    Убираем переменные, они же не используются! Мелочь, но лог по-чище станет.

  2. Опечатка

    temp.c:288:11: warning: unknown escape sequence: '\320'
    cout << "\Массив после сортировки: \n";
    

    Что говорит компилятор?

    Предупреждение: неизвестная escape-последовательность '\320'.

    Что делаем мы?

    Стираем обратный слэш: "Массив после сортировки: \n".

  3. Использование необъявленных сущностей

    temp.c:288:3: error: 'cout' was not declared in this scope
    cout << "\Массив после сортировки: \n";
    ^~~~
    temp.c:288:3: note: suggested alternative:
    In file included from temp.c:234:0:
    c:\mingw\lib\gcc\mingw32\6.3.0\include\c++\iostream:61:18: note:   'std::cout'
    extern ostream cout;  /// Linked to standard output
                  ^~~~
    

    Что говорит компилятор?

    Ошибка: cout не был объявлен в этом пространстве.
    Заметка: рекомендуемая альтернатива - std::cout.

    Что делаем мы?

    Следуем предложению компилятора и заменяем cout на std::cout.

  4. Сравнение между знаковой и беззнаковой переменной

    temp.c:272:19: warning: comparison between signed and unsigned integer expressions [-Wsign-compare]
    for (int i = 0; i < vector_size; i++) {
    

    Что говорит компилятор?

    Предупреждение: сравнение между знаковым и беззнаковым целочисленным выражением.

    Что делаем мы?

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

     for (unsigned i = 0; ...)
    
  5. Присваивание с разными типами

    temp.c: In function 'int main()':
    temp.c:284:47: error: cannot convert '__gnu_cxx::__alloc_traits<std::allocator<std::__cxx11::basic_string<char> > >::value_type {aka std::__cxx11::basic_string<char>}' to 'const char*' for argument '2' to 'char* strcpy(char*, const char*)'
                           strcpy(str,students[b-1]);
                                                   ^
    temp.c:285:55: error: cannot convert '__gnu_cxx::__alloc_traits<std::allocator<std::__cxx11::basic_string<char> > >::value_type {aka std::__cxx11::basic_string<char>}' to 'char*' for argument '1' to 'char* strcpy(char*, const char*)'
                           strcpy(students[b-1],students[b]);
                                                           ^
    temp.c:286:45: error: cannot convert '__gnu_cxx::__alloc_traits<std::allocator<std::__cxx11::basic_string<char> > >::value_type {aka std::__cxx11::basic_string<char>}' to 'char*' for argument '1' to 'char* strcpy(char*, const char*)'
                           strcpy(students[b],str);
    

    Что говорит компилятор?

    Ошибка: не могу преобразовать тип std::__cxx11::basic_string<char> к типу char* для первого аргумента функции char* strcpy(char*, const char*).

    Что делаем мы?

    Сначала внимательно смотрим на ошибку. Функция первым аргументом принимает char*, а мы ей подсовываем string.

    У нас всего два варианта решения этой проблемы: 1) сменить тип переменной на char*; 2) использовать другую функцию (или, вообще, другой подход).

    Мы воспользуемся вторым способом. Вместо

    strcpy(str,students[b-1]);                            
    strcpy(students[b-1],students[b]);                               
    strcpy(students[b],str);   
    

    Напишем

     str = students[b-1];
     students[b-1] = students[b];
     students[b] = str;
    
  6. Теперь у нас новая ошибка: Несовместимые типы в присваивании

    temp.c: In function 'int main()':
    temp.c:280:39: error: incompatible types in assignment of '__gnu_cxx::__alloc_traits<std::allocator<std::__cxx11::basic_string<char> > >::value_type {aka std::__cxx11::basic_string<char>}' to 'char [19]'
                          str = students[b-1];
    

    Что говорит компилятор?

    Ошибка: несовместимые типы в присваивании. Переменная типа std::__cxx11::basic_string<char> присваивается переменной типа char [19].

    Что делаем мы?

    Меняем тип переменной str с char[19] на std::string:

    std::string str;
    

Теперь мы (наконец-то!) можем скомпилировать и запустить программу. Но она, естественно, не будет работать правильно.

Как заставить ее работать верно!?

Заменить

 // Попытка отсортировать
    for (b=n;b>=a;b--){                                               
      ch1=students[b-1][0];  
      ch2=students[b][0];                                                     
           if (ch1>ch2){ 
                 strcpy(str,students[b-1]);                            
                 strcpy(students[b-1],students[b]);                               
                 strcpy(students[b],str);                                         
           }                                                                
     }

На

std::sort(students.begin(), students.end());

Не забудьте подключить заголовочный файл <algorithm>!

А for (i = 0; i <= n; i++) заменить на for (i = 0; i < vector_size; i++).

Почему? Подумайте сами, основываясь на новых предупреждениях компилятора.

Советы

  1. Определитесь с языком. Не стоит смешивать C и C++. Кто-бы что ни говорил, но это разные языки.
  2. Форматируйте код. Привыкайте к нормальному форматированию кода с начала обучения. Ну а добавлять плохо отформатированный код в вопрос — это моветон. Кому хочется разбираться в бесконечной простыне кода? Стоит прочитать про coding-style.
  3. Пространства имен. Где-то вы пишете std::cout, где-то — просто cout. Лучше писать все в одном стиле. Подробнее о том, стоит ли использовать using namespace здесь.
  4. Счетчики циклов. Некоторые циклы вы записываете так:

    // Попытка отсортировать
    for (b = n; b >= a; b--) {
    ...
    for (i = 0; i <= n; i++)
    

    Причем ни переменная b, ни i больше нигде не используются. Мы же не в C89, да? Лучше будет объявлять эти переменные прямо в заголовке цикла:

    // Кстати, почему b? Счетчики принято называть i, j, k... Правим!
    for (int i = n; i >= a; i--) {
    ...
    for (int i = 0; i <= n; i++)
    

    Почему лучше? Мы, по крайней мере, избавились от двух переменных, которые захламляют пространство имен внутри функции main. Кроме того, уменьшили "длительность жизни" ("Совершенный код" Стив Макконнелл. Часть 3.10. Переменные. Область видимости) переменных.

  5. Не используйте русский текст в коде во время обучения. Это тот еще геморрой, который только отвлекает от обучения. Если не в ладах с английским, используйте транслит: std::cout << "Vvedite chislo: ". Уж лучше так...

Второй самый главный совет: Не бойтесь задавать вопросы

Комментарий автора:

Проект в в CodeBlocks я создал, в нем и работаю. А вот разбирась пока не очень, поэтому и сижу здесь. Иной раз и путаю Си и Си++.Запутался потому, что пытаюсь методом тыка что то сделать. Знаний мало. Книжки читаю. Ошибаюсь. Как написано на сайте, если не хочешь быть дураком - спроси. Вот я и прошу помощи и понимания. С уважением к Вам, новичок. – igorekvp

Никто из нас не рождается кулц-хакерами и труЪ C++ программистами. Все мы учимся. Мне (да и всем) было также трудно, как вам. Не стесняйтесь, задавать вопросы, вам с удовольствием ответят!

READ ALSO
Записать рекуррентную формулу иначе C++

Записать рекуррентную формулу иначе C++

Проблема в том что при вычислении не хватает памяти и считает только до 7 символов после запятой, нужно чтобы считало хотя бы 10 символов после

228
Запуск окна wxWidgets в DLL с потока

Запуск окна wxWidgets в DLL с потока

Как осуществить запуск окна с нового потока?

313
возврат значения из потока

возврат значения из потока

Надо чтобы возвращаемое значение с можно было использовать как-то в int main()Как в случае передачи аргументов функции в поток принять возвращаемое...

193
Преобразование ломанной линии

Преобразование ломанной линии

Я имею неравномерную сетку в виде координат узлов в двумерном пространстве Узлы сетки хранятся в одномерном векторе, где нумерация снизу-вверх...

218