Форум программистов, компьютерный форум CyberForum.ru

Вывести на экран фамилии и имена трех худших по среднему баллу учеников - C++

Войти
Регистрация
Восстановить пароль
 
cooky
0 / 0 / 0
Регистрация: 26.02.2012
Сообщений: 9
26.02.2012, 22:00     Вывести на экран фамилии и имена трех худших по среднему баллу учеников #1
задача
На вход программе подаются сведения о сдаче экзаменов учениками 9-х классов некоторой средней школы. В первой строке сообщается количество учеников N, которое не меньше 10, но не превосходит 100, каждая из следующих N строк имеет следующий формат:
<Фамилия> <Имя> <оценки>,
где <Фамилия> – строка, состоящая не более чем из 20 символов, <Имя> – строка, состоящая не более чем из 15 символов, <оценки> – через пробел три целых числа, соответствующие оценкам по пятибалльной системе. <Фамилия> и <Имя>, а также <Имя> и <оценки> разделены одним пробелом. Пример входной строки:
Иванов Петр 4 5 3
Требуется написать как можно более эффективную программу (укажите используемую версию языка программирования, например, Borland Pascal 7.0), которая будет выводить на экран фамилии и имена трех худших по среднему баллу учеников. Если среди остальных есть ученики, набравшие тот же средний балл, что и один из трех худших, то следует вывести и их фамилии и имена.


А вот мое "решение":
Код:

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
#include <iostream>
#include <string.h>
#include <math.h>
 
struct data
{
     int sum;
     char *user;
};
 
void packer (char *tmpD, data *pupin, int i)
{
    pupin[i].user = new char[37];
    pupin[i].user = strtok(tmpD," ");
    strcat(pupin[i].user, " ");
    strcat(pupin[i].user, strtok(NULL," "));
 
    pupin[i].sum=atoi(strtok(NULL," "))+atoi(strtok(NULL," "))+atoi(strtok(NULL," "));
 
}
 
int main()
{
    int N=4;
    int const S=43;
    data *pupin = new data [N];
    char *tmpData = new char[S] ;
 
    for (int i=0; i<N; i++)
    {
        std::cout<<"Введите данные участника:"<<std::endl;
        std::cin.getline(tmpData,S);
        packer ( tmpData, pupin, i);
    }
 
    data min1, min2, min3;
    min1.sum=min2.sum=min3.sum=15;
 
 
    for(int i=0; i<N; i++)
    {
        if(pupin[i].sum<=min1.sum)
        {
            data tmp=min1;
            min1=pupin[i];
            min3=min2;
            min2=tmp;
        }
        else if (pupin[i].sum<=min2.sum)
        {
            min3=min2;
            min2=pupin[i];
        }
        else if(pupin[i].sum <= min3.sum)
            min3=pupin[i];
    }
 
    std::cout<<"Ученики с наименьшими результатом:"<<std::endl
        <<min1.user<<std::endl
        <<min2.user<<std::endl
        <<min3.user<<std::endl;
    
    for(int i=0; i<N; i++)
        if(pupin[i].sum==min3.sum)
            std::cout<<pupin[i].user<<std::endl;
 
    int r;
    std::cin>>r;
        
}
Не могу разобраться, почему во время выполнения программы все время вылазят ошибки "доступа" и ghjxtt.. разъясните,пожалуйста,что здесь не так..п.с.компилировал на Visual Studio 2010
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
26.02.2012, 22:00     Вывести на экран фамилии и имена трех худших по среднему баллу учеников
Посмотрите здесь:

C++ Структуры: вывести фамилии трех лучших учеников данного класса
C++ Вывести имена трех худших по баллу
Составить программу, которая корректирует список и сортирует его либо по среднему баллу C++
Вывести трех лучших учеников C++
C++ Вывести на экран в текущем каталоге имена тех каталогов, которые в себе не содержат подкаталогов
Структура "Студент". Сортировка по среднему баллу C++
C++ Как используя цикл и массивы вводить с клавиатуры фамилии и имена, и затем выводить их на экран?
После регистрации реклама в сообщениях будет скрыта и будут доступны все возможности форума.
OstapBender
 Аватар для OstapBender
581 / 519 / 35
Регистрация: 22.03.2011
Сообщений: 1,585
27.02.2012, 02:17     Вывести на экран фамилии и имена трех худших по среднему баллу учеников #2
для начала так:
C
1
2
3
4
5
6
7
8
9
10
void packer (char *tmpD, data *pupin, int i)
{
pupin[i].user = new char[37];
strcpy(pupin[i].user,strtok(tmpD," "));
strcat(pupin[i].user, " ");
strcat(pupin[i].user, strtok(NULL," "));
 
pupin[i].sum=atoi(strtok(NULL," "))+atoi(strtok(NULL," "))+atoi(strtok(NULL,"\n"));
 
}
cooky
0 / 0 / 0
Регистрация: 26.02.2012
Сообщений: 9
27.02.2012, 11:19  [ТС]     Вывести на экран фамилии и имена трех худших по среднему баллу учеников #3
Спасибо! проглядел этот момент)
Подскажите еще, что в нижеприведенном коде не так?

C++
1
2
3
4
5
6
7
8
9
10
11
#include "stdafx.h"
 
 
int main()
{
    int N;
    std::cin>>N;
    int i=0;
    while(i<=N)
        i++;
}
суть в том, что количество интераций циклов пользователь должен ввести с клавиатуры....но вылазит ошибка доступа...как этого можно избежать??

Добавлено через 1 час 6 минут
вот например, если после строки исходного когда: char *tmpData = new char[S] ;

вставить : std::cin>>N;

вылазит ошибка(
dimcoder
Полярный
 Аватар для dimcoder
449 / 422 / 66
Регистрация: 11.09.2011
Сообщений: 1,110
27.02.2012, 11:32     Вывести на экран фамилии и имена трех худших по среднему баллу учеников #4
Нет ошибки:
http://liveworkspace.org/code/58a58a...8d8ef9cf10eafb
И зачем вам stdafx.h?

Добавлено через 1 минуту
Цитата Сообщение от cooky Посмотреть сообщение
интераций
итераций
cooky
0 / 0 / 0
Регистрация: 26.02.2012
Сообщений: 9
27.02.2012, 11:45  [ТС]     Вывести на экран фамилии и имена трех худших по среднему баллу учеников #5
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
#include <iostream>
#include <string.h>
#include <math.h>
 
 
 
 
 
struct data
{
    int sum;
    char *user;
};
 
void packer (char *tmpD, data *pupin, int i)
{
   pupin[i].user = new char[37];
   strcpy(pupin[i].user, strtok(tmpD," "));
   strcat(pupin[i].user, " ");
   strcat(pupin[i].user, strtok(NULL," "));
 
   pupin[i].sum=atoi(strtok(NULL," "))+atoi(strtok(NULL," "))+atoi(strtok(NULL,"\n"));
 
}
 
int main()
{
   int N=5;
   int const S=43;
   data *pupin = new data [N];
   char *tmpData = new char[S] ;
   
   
   
 
   for (int i=0; i<N; i++)
   {
      std::cout<<"Введите данные участника:"<<std::endl;
      std::cin.getline(tmpData,S);
      packer ( tmpData, pupin, i);
   }
 
   data min1, min2, min3;
   min1.sum=min2.sum=min3.sum=15;
 
 
   for(int i=0; i<N; i++)
   {
      if(pupin[i].sum<=min1.sum)
      {
         data tmp=min1;
         min1=pupin[i];
         min3=min2;
         min2=tmp;
      }
      else if (pupin[i].sum<=min2.sum)
      {
         min3=min2;
         min2=pupin[i];
      }
      else if(pupin[i].sum <= min3.sum)
         min3=pupin[i];
   }
 
   std::cout<<"Ученики с наименьшими результатом:"<<std::endl
      <<min1.user<<std::endl
      <<min2.user<<std::endl
      <<min3.user<<std::endl;
   
   
 
   return 0;
      
}
Тут все работает идеально
Но если я добавляю 2 сточки:
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
#include <iostream>
#include <string.h>
#include <math.h>
 
 
 
 
 
struct data
{
    int sum;
    char *user;
};
 
void packer (char *tmpD, data *pupin, int i)
{
   pupin[i].user = new char[37];
   strcpy(pupin[i].user, strtok(tmpD," "));
   strcat(pupin[i].user, " ");
   strcat(pupin[i].user, strtok(NULL," "));
 
   pupin[i].sum=atoi(strtok(NULL," "))+atoi(strtok(NULL," "))+atoi(strtok(NULL,"\n"));
 
}
 
int main()
{
   int N=5;
   int const S=43;
   data *pupin = new data [N];
   char *tmpData = new char[S] ;
   
   
   std::cout<<"Введите чило участников:";                            \\вот они!!!!!!!!!!!!!!!!!
   std::cin>>N;
 
   for (int i=0; i<N; i++)
   {
      std::cout<<"Введите данные участника:"<<std::endl;
      std::cin.getline(tmpData,S);
      packer ( tmpData, pupin, i);
   }
 
   data min1, min2, min3;
   min1.sum=min2.sum=min3.sum=15;
 
 
   for(int i=0; i<N; i++)
   {
      if(pupin[i].sum<=min1.sum)
      {
         data tmp=min1;
         min1=pupin[i];
         min3=min2;
         min2=tmp;
      }
      else if (pupin[i].sum<=min2.sum)
      {
         min3=min2;
         min2=pupin[i];
      }
      else if(pupin[i].sum <= min3.sum)
         min3=pupin[i];
   }
 
   std::cout<<"Ученики с наименьшими результатом:"<<std::endl
      <<min1.user<<std::endl
      <<min2.user<<std::endl
      <<min3.user<<std::endl;
   
   
 
   return 0;
      
}

вылазят ошибки(

Добавлено через 4 минуты
во всяком случае, на моем компиляторе так..

Добавлено через 2 минуты
после ввода "числа участников" вылазит
"Необработанное исключение в "0x1027d2f3 (msvcr100d.dll)" в "EVILcooky.exe": 0xC0000005: Нарушение прав доступа при чтении "0x00000000"."
darkknight2008
 Аватар для darkknight2008
62 / 62 / 6
Регистрация: 16.10.2011
Сообщений: 200
27.02.2012, 13:57     Вывести на экран фамилии и имена трех худших по среднему баллу учеников #6
Код вообще бередовый. У тебя есть массив с данными, под который ты выделяешь память. У тебя сначало N = 5, затем ты выделяешь память под 5! элементов, а затем вводишь N. Т.е. ты выделил память под 5! элементов, затем ввел N = 100, начал перебор всех, и когда у тебя i становится >= 5, то понятное дело вылезет исключение, ведь массив у тебя всего на 5 элементов.
Тебе надо сначало запрашивать ввод N, а уже после этого выделять память под массив.
cooky
0 / 0 / 0
Регистрация: 26.02.2012
Сообщений: 9
27.02.2012, 14:09  [ТС]     Вывести на экран фамилии и имена трех худших по среднему баллу учеников #7
C++
1
2
3
4
5
6
7
int N;
    int const S=43;
    std::cout<<"Введите чило участников:";
    std::cin>>N;
    
    data *pupin = new data [N];
    char *tmpData = new char[S] ;
подправил эту часть кода и все равно во время ввода N вылазит та же ошибка

Добавлено через 3 минуты
а если я нициализирую N(любым значением) в самой программе, то все идет отлично...
darkknight2008
 Аватар для darkknight2008
62 / 62 / 6
Регистрация: 16.10.2011
Сообщений: 200
27.02.2012, 14:22     Вывести на экран фамилии и имена трех худших по среднему баллу учеников #8
Скинь заново весь подправленный код.

Добавлено через 5 минут
Одна из твоих ошибок - ты неправильно используешь функцию strtok

Добавлено через 4 минуты
strcpy(pupin[i].user, strtok(tmpD," "));
Что тут получается? В строке tmpD ищется символ пробела, возращается на него указатель. А далее ты копируешь все, что стоит после пробела. А нужно наоборот копировать все что стоит до пробела.
strtok(NULL," ") - Такая запись вообще не имее смысла, т.к. на месте NULL должна стоять строка, в которой выполняется поиск. А вообще советую читать MSDN!

Добавлено через 45 секунд
Я бы посоветовал сделать через потоки, либо используя функцию sscanf
cooky
0 / 0 / 0
Регистрация: 26.02.2012
Сообщений: 9
27.02.2012, 14:41  [ТС]     Вывести на экран фамилии и имена трех худших по среднему баллу учеников #9
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
#include <iostream>
#include <string.h>
#include <math.h>
 
 
 
 
 
struct data
{
    int sum;
    char *user;
};
 
void packer (char*, data*, int );
 
int main()
{
   int N;
   std::cout<<"Введите число участников: ";
   std::cin>>N;
   //Если убрать эти строки и инициализировать N прямо в коде - ошибок не будет.почему?
   
 
   int const S=43;
   
   
   
   data *pupin = new data [N];
   char *tmpData = new char[S] ;
   
   
   
 
   for (int i=0; i<N; i++)
   {
      std::cout<<"Введите данные участника:"<<std::endl;
      std::cin.getline(tmpData,S);
      packer ( tmpData, pupin, i);
   }
 
   data min1, min2, min3;
   min1.sum=min2.sum=min3.sum=15;
 
 
   for(int i=0; i<N; i++)
   {
      if(pupin[i].sum<=min1.sum)
      {
         data tmp=min1;
         min1=pupin[i];
         min3=min2;
         min2=tmp;
      }
      else if (pupin[i].sum<=min2.sum)
      {
         min3=min2;
         min2=pupin[i];
      }
      else if(pupin[i].sum <= min3.sum)
         min3=pupin[i];
   }
 
   std::cout<<"Ученики с наименьшими результатом:"<<std::endl
      <<min1.user<<std::endl
      <<min2.user<<std::endl
      <<min3.user<<std::endl;
   
   
 
   return 0;
      
}
 
 
 
 
 
void packer (char *tmpD, data *pupin, int i)
{
   pupin[i].user = new char[37];
   strcpy(pupin[i].user, strtok(tmpD," "));
   strcat(pupin[i].user, " ");
   strcat(pupin[i].user, strtok(NULL," "));
 
   pupin[i].sum=atoi(strtok(NULL," "))+atoi(strtok(NULL," "))+atoi(strtok(NULL,"\n"));
 
}
 Комментарий модератора 
выкладывай код на форум!

Вот "исправленный вариант"..
а можете привести в качестве примера фрагмен кода с ипользованием "потоков" или ф-ции сканф
только условие следующее: данные о участнике(фамилия имя оценка оценка оценка) вводятся в одну строку, как указано в задании выше

Добавлено через 11 минут
Что тут получается? В строке tmpD ищется символ пробела, возращается на него указатель. А далее ты копируешь все, что стоит после пробела. А нужно наоборот копировать все что стоит до пробела.
Он возвращает указатель на первую лексему, то есть, внашем случае, Фамилию участника..место пробела заменятеся символом конца строки....помоему так)) ну в этой части программа работает правильно
darkknight2008
 Аватар для darkknight2008
62 / 62 / 6
Регистрация: 16.10.2011
Сообщений: 200
28.02.2012, 08:36     Вывести на экран фамилии и имена трех худших по среднему баллу учеников #10
Приведи пример строки ввода.

Добавлено через 8 минут
С использование sscanf получится вот так:
C++
1
2
3
4
5
6
7
void packer (char *tmpD, data *pupin, int i)
{
   pupin[i].user = new char[37];
   int a1, a2, a3;
   sscanf(tmpD, "%*s %36s %i %i %i", pupin[i].user, &a1, &a2, &a3);
   pupin[i].sum = a1 +a2 + a3;
}
Лучше будет использовать sscanf_s - это безопасная версия sscanf. Там просто на один аргумент будет больше и это длина строки tmpD.
Ну и можешь попробовать через std::cin считать. Это тоже не сложно, писать пока не буду.
cooky
0 / 0 / 0
Регистрация: 26.02.2012
Сообщений: 9
28.02.2012, 08:37  [ТС]     Вывести на экран фамилии и имена трех худших по среднему баллу учеников #11
Ремизова Валерия 5 4 3
darkknight2008
 Аватар для darkknight2008
62 / 62 / 6
Регистрация: 16.10.2011
Сообщений: 200
28.02.2012, 08:45     Вывести на экран фамилии и имена трех худших по среднему баллу учеников #12
В моем примере, в строку имени занесется Валерия.
Вызов strtok(NULL," ") вызовет исключение(или просто вернет NULL) Эта функция ищет в строке первую встречу символов из другой строки. А то что ты написал, ты вместо строки передаешь NULL и ищешь пробел...
В строке tmpD = "Ремизова Валерия 5 4 3" вызов char *a = strtok(tmpD, " ") Вернет указатель на пробел. Т.е. строка 'a' буде равна " Валерия 5 4 3" вызов a = strtok(a + 1, " ") Вернет указатель на второй пробел т.е. " 5 4 3".
Пока все, потом смогу отписаться только вечером.
Nameless One
Эксперт С++
 Аватар для Nameless One
5759 / 3408 / 255
Регистрация: 08.02.2010
Сообщений: 7,393
28.02.2012, 09:11     Вывести на экран фамилии и имена трех худших по среднему баллу учеников #13
Цитата Сообщение от darkknight2008 Посмотреть сообщение
strtok(NULL," ") - Такая запись вообще не имее смысла, т.к. на месте NULL должна стоять строка, в которой выполняется поиск. А вообще советую читать MSDN!
это не так. Советую почитать маны

Добавлено через 1 минуту
Цитата Сообщение от darkknight2008 Посмотреть сообщение
Вызов strtok(NULL," ") вызовет исключение(или просто вернет NULL)
нет, не вызовет, это вообще С-ая функция. И NULL она вернет только при определеном случае
cooky
0 / 0 / 0
Регистрация: 26.02.2012
Сообщений: 9
28.02.2012, 09:19  [ТС]     Вывести на экран фамилии и имена трех худших по среднему баллу учеников #14
Цитата Сообщение от Nameless One Посмотреть сообщение
это не так. Советую почитать маны

Добавлено через 1 минуту

нет, не вызовет, это вообще С-ая функция. И NULL она вернет только при определеном случае
strtok(stroka, " "); -вернет первую лексему строки

strtok(NULL, " "); -вторая лексема строки

и работает моя программа именно так...выше есть рабочий вариант, проверь..
Nameless One
Эксперт С++
 Аватар для Nameless One
5759 / 3408 / 255
Регистрация: 08.02.2010
Сообщений: 7,393
28.02.2012, 09:21     Вывести на экран фамилии и имена трех худших по среднему баллу учеников #15
cooky, так я тебе ничего и не говорил. Я отвечал на необоснованные утверждения darkknight2008
cooky
0 / 0 / 0
Регистрация: 26.02.2012
Сообщений: 9
28.02.2012, 09:33  [ТС]     Вывести на экран фамилии и имена трех худших по среднему баллу учеников #16
Nameless One, извиняюсь)
C++
1
2
3
4
5
6
7
8
9
10
void packer (char *tmpD, data *pupin, int i)
{
   pupin[i].user = new char[37];
   strcpy(pupin[i].user, strtok(tmpD," "));
   strcat(pupin[i].user, " ");
   strcat(pupin[i].user, strtok(NULL," "));
 
   pupin[i].sum=atoi(strtok(NULL," "))+atoi(strtok(NULL," "))+atoi(strtok(NULL,"\n"));
 
}
вообщем, мой вариант,конечно,чудовещный, но работает он чОтка
darkknight2008
 Аватар для darkknight2008
62 / 62 / 6
Регистрация: 16.10.2011
Сообщений: 200
28.02.2012, 15:16     Вывести на экран фамилии и имена трех худших по среднему баллу учеников #17
Да, простите облажался(( После вызова std::cin >> N; в потоке ввода остается символ перевода строки. Поэтому при вызове std::cin.getline(tmpData,S); сразу ловится символ перевода строки и считается, что ввод закончен, т.е. строка остается пустой. Чтобы его отловить, можно после std::cin >> N; вставить getchar() либо std::cin.ignore();
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
28.02.2012, 15:29     Вывести на экран фамилии и имена трех худших по среднему баллу учеников
Еще ссылки по теме:

C++ Упорядочить массив по среднему баллу
Сортировка списка студентов по среднему баллу C++
C++ Вывести фамилии неуспевающих учеников
Описать структуру STUDENT, упорядочить по среднему баллу C++
Задание из ЕГЭ: поиск худших учеников C++

Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
cooky
0 / 0 / 0
Регистрация: 26.02.2012
Сообщений: 9
28.02.2012, 15:29  [ТС]     Вывести на экран фамилии и имена трех худших по среднему баллу учеников #18
Вот оно!))спасибо огромное)
Yandex
Объявления
28.02.2012, 15:29     Вывести на экран фамилии и имена трех худших по среднему баллу учеников
Ответ Создать тему
Опции темы

Текущее время: 03:44. Часовой пояс GMT +3.
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2017, vBulletin Solutions, Inc.
Рейтинг@Mail.ru