Форум программистов, компьютерный форум, киберфорум
Наши страницы
C для начинающих
Войти
Регистрация
Восстановить пароль
 
Ducas
0 / 0 / 0
Регистрация: 22.01.2015
Сообщений: 11
1

Обработка имен и оценок студентов указателями

22.01.2015, 14:23. Просмотров 406. Ответов 8
Метки нет (Все метки)

Описание:
Пользователь вводит строкой имена студентов и их оценку за экзамен, например:
Yossi 59 Chedva 94 Rivka 46 Ran 99 Amir 43 Zohar 79
Нужно создать два массива и записать в один - имена, в другой - оценку. Затем обработать данные: проверить правильность ввода данных (имена состоят из английских букв, а оценки в интервале от 0 до 100), записать в failed[] тех, у кого меньше 60 баллов, посчитать максимальную и среднюю оценки.
Предполагается использовать функции:
int validate_data(int grades[], char *names[], int size)
для проверки правильности ввода. Если условия не удовлетворены, то имя и соответствующая оценка удаляются, данные смещаются на место удаленного, возвращается количество студентов (размер массива)
и
int find_failures(int grades[], char *names[], int students_num, char *failed[], double *average, int *maximal)
которая записывает в failed[] провалившихся, находит максимальную оценку, считает среднее, возвращает количество провалившихся (размер массива failed).
Проблема в том, что я категорически, не смотря на десятки уже прочтенных статей, не понимаю, как пользоваться указателями.
Моя идея решения:
пользователь вводит данные, данные записываются в строку char str[].
Дальше функция init_arrays обрабатывает эту строку.
for(i=0; str[i]!='\0'; i++)
{
проверяет, если и-тое значение буква, то до пробела записывается в names[] (массив указателей. Должен быть двумерный, потому что имена столбиком), если пробел - идет дальше, если цифра, то через str[i]-'0' записывается в grades[]. Возвращаемое значение - количество студентов (т.е. количество рядов двумерных массивов)
}
int validate_data(int grades[], char *names[], int size) - идет по колонкам массива неймс, если там есть ошибка - включается флаг на удаление. Потом проходит по массиву грейдс. Если там ошибки - опять в флаг. Далее на основании флага - удаляются и смещаются данные.
int find_failures(int grades[], char *names[], int students_num, char *failed[]) проверяет членов грейдс на <60, и если да, то заносит соответствующее имя в фейлд, увеличивает счетчик после каждого внесения имени, возвращает счетчик.
Вопрос в том, как правильно использовать указатели в таком случае. Вот хоть убей не понимаю.
Вопросы:
1. Функция init_arrays принимает массив указателей, массив, строку
C
1
init_arrays(char **names[][SIZE_COL], int grades[], char str[])
правильно ли я объявила аргументы?
в чем разница между char* var, char *var и char **var?
при вызове функции, что я должна передать функции, чтобы передать именно массив указателей?
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
{
        int i;
    int rows=0; 
    int columns=0;
    int number_of_students;
    for (i = 0; str[i]!='\0'; i++) //пока не дойду до конца строки
        {
            if((str[i]>65 && str[i]<90) || (str[i]>97 && str[i]<122)) //если буква
            {
                while(str[i]!=' ') //пока не дойду до пробела
                {
            
                    names[rows][columns] = &str[i]; //записывается в массив указателей на имена
                    i++;
                    columns++;
                }
            }
            else if(str[i]>48 && str[i]<57) //если цифра
            {
                while(str[i]!=' ')//пока не дойду до нуля
                {
            
                    grades[rows] = grades[rows]*10+str[i]-'0'; //перевожу в интовое
                    i++;
                }
            }
            else
            {
                i++; //если попадаю на пробел, просто иду дальше
            }
            rows++; //после того, как записались данные одного студента, перехожу на следующий ряд 
                                     //массива
    }
    number_of_students=rows-1; //после того, как достигли конца строки, считаем количество студентов
//-1 - потому что после последнего студента количество рядов все-таки увеличилось
    return number_of_students; //возвращаем количество студентов
}
вопросы: правильное и корректное использование знаков * и &
C
1
names[rows][columns] = &str[i]
вот тут я указателю даю значение, поэтому я ставлю &. А если мне надо указателю дать указатель?

Фухх.. простите, что путано. Сама слабо понимаю, чего я не понимаю. Надеюсь, если объясните, дальнейшее решу сама. Если нет - выложу еще куски говнокода с конкретными вопросами.

Спасибо.
0
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
22.01.2015, 14:23
Ответы с готовыми решениями:

Подсчитать число студентов, не имеющих оценок 2 и 3
вводя в цикле по 5 оценок каждого студента, подсчитывается число студентов, не имеющих оценок 2 и...

Обработка результатов оценок
Написать программу, которая обрабатывает результат экзамена. Для каждой оценки программа должна...

Обработка строк с указателями
Почему вот эта строчка(while(*w1)) не работает ?? , вроде *w1 это значение элемента по этому...

Обработка оценок студентов
известно что в следующем фрагменте программы массив матрица содержит оценки студентов группы,...

Вводя в цикле по 5 оценок каждого студента, подсчитать число студентов, не имеющих оценок 2 и 3
Помогите пожалуйста запутался) Вводя в цикле по 5 оценок каждого студента, подсчитать число...

8
HighPredator
5707 / 2030 / 724
Регистрация: 10.12.2010
Сообщений: 5,817
Записей в блоге: 3
22.01.2015, 14:35 2
Смотрите, поскольку у вас столько вопросов, попробуйте сначала облегчить себе задачу следующим образом: возьмите книгу (по которой учитесь или получше что, если есть возможность) и прочтите разделы про массивы, а затем про указатели. Часть вопросов после прочтения должна решиться.

P.S. не подумайте, что мне лень в вашем коде/мыслях ковыряться, просто книги написаны теми, кто хорошо умеет объяснять (иначе бы их не читали и не рекомендовали). А тонкости мы вам обмозгуем Успехов.
0
Ducas
0 / 0 / 0
Регистрация: 22.01.2015
Сообщений: 11
22.01.2015, 14:40  [ТС] 3
Читала. Не помогает.
Ладно. Облегчим вопросы.
Массив - это сам по себе указатель на первую ячейку памяти в неразделимой череде ячеек. Значит ли это, что я могу передавать в функцию в качестве аргумента-указателя просто массив?
0
HighPredator
5707 / 2030 / 724
Регистрация: 10.12.2010
Сообщений: 5,817
Записей в блоге: 3
22.01.2015, 14:48 4
Цитата Сообщение от Ducas Посмотреть сообщение
Значит ли это, что я могу передавать в функцию в качестве аргумента-указателя просто массив?
Да. Это полностью легально.
C
1
2
3
4
5
6
7
8
9
10
11
12
13
void DemoFunction(int* a)
{
  /* some code here */
}
 
/* ... */
 
int main(void)
{
  int a[] = {1, 2, 3, 4};
  DemoFunction(a);
  return 0;
}
1
22.01.2015, 14:48
Ducas
0 / 0 / 0
Регистрация: 22.01.2015
Сообщений: 11
22.01.2015, 14:54  [ТС] 5
Далее.
Массив указателей на имена должен быть одномерным или двумерным?
По идее, каждый элемент этого массива указывает на первую букву имени, а дальше уже все обрабатывается подобно обычному массиву.
НО
у меня пользователь вводит все данные ОДНОЙ строкой. Как мне "сказать" программе, что с пробелом заканчивается элемент, на который "указывает" элемент массива имен?
0
HighPredator
5707 / 2030 / 724
Регистрация: 10.12.2010
Сообщений: 5,817
Записей в блоге: 3
22.01.2015, 14:59 6
Цитата Сообщение от Ducas Посмотреть сообщение
Массив указателей на имена должен быть одномерным или двумерным?
Ok, давайте определяться.
1) Что вы хотите хранить в принципе?
2) В каком виде?
3) Как вы видите организацию 1+2?
4) Соответствует ли 3 требованиям задачи?
0
Ducas
0 / 0 / 0
Регистрация: 22.01.2015
Сообщений: 11
22.01.2015, 16:46  [ТС] 7
1) Что вы хотите хранить в принципе?
Имена студентов
2) В каком виде?
Массив строк
типа names[][SIZE] = {"Yossi", "Chedva", "plant", "Rivka", "Ran", "Amir", "Zohar"}

И вот тут мне стало легче. Спасибо за правильно заданные вопросы!
3) Как вы видите организацию 1+2?
4) Соответствует ли 3 требованиям задачи?
Создать массив строк (само собой он будет двумерный), и просто в него записать строки-имена.
Нет, не противоречит
Спасибо! Сейчас займусь написанием. Появятся новые вопросы - буду задавать.

Добавлено через 1 час 32 минуты
Так. а вот теперь конкретный вопрос:
ниже код с камментами, где че не работает.
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
int find_failures(int grades[], char *names[], int students_num, char *failed[], double *average, int *maximal)
{
    int i,j;
    int n=0;
    for(i=0;i<students_num; i++) //проходит через массивы
    {
        if(grades[i]<60) //если оценка меньше 60, значит завалил, значит это имя идет в фейлд
        {
            *failed[n]=&names[i]; //здесь ругается и вылетает. Видимо, из-за * и & как правильно написать?
            n++;
        }
        if(i!=0 && grades[i]>grades[i-1])//если данная оценка больше предыдущей, она записывается в макс
        {
            *maximal=&grades[i];//здесь тоже ругается. Идея такова, что значение, на которое указывает
                                                      //максимал, менялось на большее
        }
        *average=*average+grades[i];//здесь должно считаться среднее. Заменяются значения
    }
    *average=*average/students_num;//здесь тоже ругается, что тип даббл не может поделить. Почему?
    printf("maximal = %d\n", *maximal);
    printf("average = %d\n", *average);
    return n;
}
 
int main()
{
int grades[SIZE_ROWS];
char names[SIZE_ROWS][SIZE_COL];
char *failed[SIZE_ROWS][SIZE_COL];
int students_num=SIZE_ROWS;
char name[STR_SIZE];
double ave=0; //среднее
int max = 0; //максимальное
<....>
        find_failures(grades, names, students_num, failed, &average, &max);
    printf("max = %d\n", max);
    printf("average = &d", average);
Собсна, вопрос: как правильно расставить * И & и почему?
0
HighPredator
5707 / 2030 / 724
Регистрация: 10.12.2010
Сообщений: 5,817
Записей в блоге: 3
22.01.2015, 17:16 8
Вот не зря я сказал почитать про указатели...
Ладно, поехали.
1)
C++
1
*failed[n]=&names[i]; //здесь ругается и вылетает. Видимо, из-за * и & как правильно написать?
Смотря что вы хотели сделать. Подозреваю, что требовалось скопировать указатель names[i] в failed[n]. В таком случае, просто:
C
1
failed[n]=names[i];
. + Обратите внимание, что у вас криво объявлен failed в главной функции.
2)
C++
1
*maximal=&grades[i];//здесь тоже ругается.
Здесь вы свалили все в кучу. Сделав grades[i] вы уже получаете значение, не надо брать его адрес.
C
1
*maximal=grades[i];
3)
C++
1
*average=*average/students_num;
попробуйте заменить на
C
1
*average=(*average)/students_num;
В общем подтяните знания, а то у вас уже функции вовсю...
0
Ducas
0 / 0 / 0
Регистрация: 22.01.2015
Сообщений: 11
27.01.2015, 11:35  [ТС] 9
Так. Стало яснее и понятнее. Теперь есть совершенно конкретный вопрос по поинтеровой арифметике.
есть функция
C
1
2
3
4
5
6
7
8
int validate_data(int grades[], char *names[][STR_SIZE],  int size) 
{ 
    int i; 
    int rows=0; 
    int columns=0; 
    int flag=0; 
 
    printf("names[%d] = %s \n", 1, *(names+STR_SIZE));
(это "отладочная" версия - тут я ошибки ищу, принцип работы разбираю. Поэтому все так обрезано и примитивно).
Функция принимает указатель на двумерный массив, т.е., по идее, функция знает, что массив двумерный. В двумерном массиве содержатся три имени. Ну, допустим, names[0]="Yossi"; names[1]="Dana", names[2]="Rivka".
Как вывести на экран второй и третий ряд массива?
Вот что нужно написать вместо "*(names+STR_SIZE)"? Я уже перепробовала вообще все на свете.... Увеличивать указатель на ряды на 1 - не помогает. Кстати, почему.

Добавлено через 17 часов 54 минуты
Все дело в типе указателя -_-
0
27.01.2015, 11:35
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
27.01.2015, 11:35

Один метод должен в новой ведомости размещать студентов в алфавитном порядке. Другой – сохранять только студентов с долей оценок (равных заданной оц
Один метод должен в новой ведомости размещать студентов в алфавитном порядке. Другой – сохранять...

Запись оценок и имен в отдельные переменные
Задача состоит в следующем - мы имеем файл с данными вида Иванов Иван 6; 8; 4; 7; 5; 8; 3...

Массиа групп, студентов, оценок
Нужно создать массив в котором будут хранится группы, в группах студенты и их оценки.


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

Или воспользуйтесь поиском по форуму:
9
Ответ Создать тему
Опции темы

КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2019, vBulletin Solutions, Inc.
Рейтинг@Mail.ru