Форум программистов, компьютерный форум, киберфорум
Наши страницы
С++ для начинающих
Войти
Регистрация
Восстановить пароль
 
 
Рейтинг 5.00/5: Рейтинг темы: голосов - 5, средняя оценка - 5.00
Алерон
5 / 5 / 2
Регистрация: 13.10.2009
Сообщений: 542
#1

Запись в строку char*, входящую в структуру

20.04.2015, 22:35. Просмотров 945. Ответов 28
Метки нет (Все метки)

Данная функция, преобразует строку в структуру student. Ошибки нет, но записывается ересь. Вроде и понимаю, что написано ужасно криво, но где неверно, понять не могу.
Строка представляет собой следующее: "Владимир Математика 3".
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
struct student
{
    char* name;
    char* subject;
    int mark;
};
 
student LineToStudent(string line)
{
    student st;
    st.name = (char*)malloc(1);
    st.subject = (char*)malloc(1);
    st.mark = 0;
    int i = 0;
    int k = 1;
    while (line[i] != ' ')
    {
        st.name = (char*)realloc(st.name, k*sizeof(char));
        st.name[k] = line[i];
        i++;
        k++;
    }
    cout << st.name;
    i++;
    k = 1;
    while (line[i] != ' ')
    {
        st.subject = (char*)realloc(st.subject, k*sizeof(char));
        st.subject[k] = line[i];
        i++;
        k++;
    }
    i++;
    st.mark = atoi(&line[i]);
    return st;
}
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
20.04.2015, 22:35
Ответы с готовыми решениями:

Запись символов из файла в единичный char и строку
Всем привет, учусь получать данные из файла и нашёл такое явление: если у нас...

Что означает такая запись char *smt=new char[1]?
что означает такая запись char *smt=new char?

Запись в *char элемента из массива *char[i]
Есть динамический массив, например char *drives = {&quot;A:&quot;, &quot;B:&quot;, &quot;C:&quot;, &quot;D:&quot;,...

Запись строки char в массив char
Глупый вопрос, но что поделать, многое забыл... Хочу записть строку типа char...

Конвертация unsigned char[7] в структуру
Как сделать конвертацию unsigned char в структуру. Есть датчик, который...

28
nmcf
6260 / 5572 / 2532
Регистрация: 14.04.2014
Сообщений: 23,464
20.04.2015, 22:37 #2
Где установка '\0'?
0
Алерон
5 / 5 / 2
Регистрация: 13.10.2009
Сообщений: 542
20.04.2015, 22:40  [ТС] #3
nmcf, а зачем? У меня в строке 3 слова разделенные проблемами. Первые два ищу до пробела, а последнее это цифра к которой обращаюсь напрямую.
0
nmcf
6260 / 5572 / 2532
Регистрация: 14.04.2014
Сообщений: 23,464
20.04.2015, 22:46 #4
Ты собрал слово из букв и выводишь в 23-й строке, а '\0' где? Это же не string, как программа найдёт конец? У тебя и массив должен быть больше на 1 под это.
1
Kerry_Jr
Эксперт PHP
2210 / 2006 / 940
Регистрация: 14.05.2014
Сообщений: 5,869
Записей в блоге: 1
Завершенные тесты: 5
20.04.2015, 22:48 #5
Цитата Сообщение от Алерон Посмотреть сообщение
а зачем?
а затем что вы под имя и название предмета выделяете мало памяти, выделяйте на один символ больше и последним вводите терминальный ноль.
1
Алерон
5 / 5 / 2
Регистрация: 13.10.2009
Сообщений: 542
20.04.2015, 22:48  [ТС] #6
nmcf, ах да, просто не сразу понял о чём вы.
После исправления выводиться: НКоролёвээээ<<<<<<<<оюоюНСемёновээээ<<<<<<<<оюоюДля продолжения нажмите любую кл
авишу . . .
0
ValeryS
Модератор
7170 / 5437 / 674
Регистрация: 14.02.2011
Сообщений: 18,372
20.04.2015, 22:52 #7
Цитата Сообщение от Алерон Посмотреть сообщение
nmcf, а зачем?
затем что без нуля строка не строка а набор символов и пока не вставишь 0 в name и subject они строкой не будут
далее
Цитата Сообщение от Алерон Посмотреть сообщение
int k = 1;
..........
* * * * st.name[k] = line[i];
что пишешь в первый элемент строки (индекс 0)?
где проверки выделения, перевыделения памяти?
что будет если между словами будет 2 пробела?
1
Bushmeister
22 / 22 / 10
Регистрация: 19.03.2015
Сообщений: 137
20.04.2015, 22:56 #8
В C++ new и delete
В С malloc realloc free

Код на C++? Да. - Используй new и delete
1
ValeryS
Модератор
7170 / 5437 / 674
Регистрация: 14.02.2011
Сообщений: 18,372
20.04.2015, 23:00 #9
Цитата Сообщение от Bushmeister Посмотреть сообщение
Код на C++? Да. - Используй new и delete
там нет realloc
в первом подсчитывать количество букв выделить память и во втором прочитать символы

Добавлено через 39 секунд
Цитата Сообщение от Bushmeister Посмотреть сообщение
В С malloc realloc free
я правильно понимаю что в С++ эти функции под запретом?
0
nmcf
6260 / 5572 / 2532
Регистрация: 14.04.2014
Сообщений: 23,464
20.04.2015, 23:01 #10
Если код на C++, то только string.
Без realloc придётся копировать каждый раз содержимое.
1
Алерон
5 / 5 / 2
Регистрация: 13.10.2009
Сообщений: 542
20.04.2015, 23:04  [ТС] #11
Переписал код:
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
student LineToStudent(string line)
{
    student st;
    st.name = (char*)malloc(1);
    st.subject = (char*)malloc(1);
    st.mark = 0;
    int i = 0;
    int k = 1;
    while (line[i] != ' ')
    {
        st.name = (char*)realloc(st.name, (k));
        st.name[k-1] = line[i];
        i++;
        k++;
    }
    i++;
    st.name[k-1] = '\0';
    cout << st.name;
    k = 1;
    while (line[i] != ' ')
    {
        st.subject = (char*)realloc(st.subject, (k));
        st.subject[k-1] = line[i];
        i++;
        k++;
    }
    i++;
    st.subject[k-1] = '\0';
    cout << st.subject;
    st.mark = atoi(&line[i]);
    cout << st.mark;
    return st;
}
Выводит вроде бы правильно. Благодарю всех за оказанную помощь!
0
ValeryS
Модератор
7170 / 5437 / 674
Регистрация: 14.02.2011
Сообщений: 18,372
20.04.2015, 23:05 #12
Цитата Сообщение от nmcf Посмотреть сообщение
Если код на C++, то только string.
а если в условии ясно сказано char*?
0
nmcf
6260 / 5572 / 2532
Регистрация: 14.04.2014
Сообщений: 23,464
20.04.2015, 23:08 #13
Цитата Сообщение от ValeryS Посмотреть сообщение
а если в условии ясно сказано char*
Тогда не получится строгого C++.
0
IrineK
Заблокирован
20.04.2015, 23:14 #14
Цитата Сообщение от Алерон Посмотреть сообщение
Строка представляет собой следующее: "Владимир Математика 3"
А если имя с фамилией, предмет из двух-трех слов и несколько оценок?
Как-то всё это не то.
0
Алерон
5 / 5 / 2
Регистрация: 13.10.2009
Сообщений: 542
20.04.2015, 23:20  [ТС] #15
IrineK, у строки(которая передается функции) есть четкие ограничения. То есть, мы абсолютно уверены, что строка содержит два слова и цифру разделенные пробелами.
0
ValeryS
Модератор
7170 / 5437 / 674
Регистрация: 14.02.2011
Сообщений: 18,372
20.04.2015, 23:27 #16
Алерон, смотри другую реализацию
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
student LineToStudent(string line)
{
    student st;
    int i;
    int k ;
    int m;
    for(i=0;line[i]==' ',i++);// отбрасываем первые пробелы
   m=i;// запоминаем позицию первой буквы фамилии
   for(k=0;line[i]!=' ',i++,k++);// подсчитываем количество букв в фамилии 
  st.name=new char[k+1]; //выделяем память 
   for(k=0;m<i;m++,k++) // копируем фамилию
     st.name[k]=line[m];
    st.name[k]=0;
    
    for(;line[i]==' ',i++);// отбрасываем пробелы перед именем
   m=i; // запоминаем позицию первой буквы имени 
   for(k=0;line[i]!=' ',i++,k++);// подсчитываем количество букв в фамилии 
   st.subject=new char[k+1]; // выделяем память
    memcpy(st.subject,&line[m],k); копируем имя
    st.subject[k]=0;
   
    for(;line[i]==' ',i++);// отбрасываем  пробелы перед числом
   sscanf(&line[i],"%d",&st.mark);//считываем число 
 
    cout << st.name;
    cout << st.subject;
    cout << st.mark;
    return st;
}
при копировании имени и фамилии я использовал два разных метода
в работе не проверял возможно где то и ошибся
1
Bushmeister
22 / 22 / 10
Регистрация: 19.03.2015
Сообщений: 137
20.04.2015, 23:32 #17
Есть динамический массив с данными. Для того чтобы его расширить надо создать временный массив текущего размера, скопировать данные, удалить основной массив и создать его же, но, с новым размером. Потом данные из временного массива скопировать в основной и временный удалить. Никто не мешает написать аналог realloc. А вообще в cpp надо использовать new и delete.
Чтобы избежать мусора в массивах типа char я всегда делаю
C++
1
2
3
4
5
6
7
8
char *a = new char[20];
char b[]="privet";
for(int i=0; i<blabla; i++)
{
     a[i]=b[i];
     a[i+1]='\0';//Внимание на эту строчку. После того как я стал так заполнять массивы мусор в моих переменных больше не встречается
}
delete [] a;
Ну, раз код уже работает то делай как хочешь. Но я бы не советал использовать сишные аллоки и фри
upd:похоже я уже опоздал
1
ValeryS
Модератор
7170 / 5437 / 674
Регистрация: 14.02.2011
Сообщений: 18,372
20.04.2015, 23:36 #18
Цитата Сообщение от Bushmeister Посмотреть сообщение
А вообще в cpp надо использовать new и delete.
это пожелание а не требование
Цитата Сообщение от Bushmeister Посмотреть сообщение
a[i+1]='\0';
при blabla равному 20 получи ошибку выхода за пределы памяти
зачем на каждом проходе записывать терминальный 0?
достаточно в конце записать
например так
C++
1
2
3
4
5
int i=0
for(; i<blabla; i++)
     a[i]=b[i];
   
  a[i]='\0';
1
IrineK
Заблокирован
21.04.2015, 00:11 #19
Цитата Сообщение от Алерон Посмотреть сообщение
То есть, мы абсолютно уверены, что строка содержит два слова и цифру разделенные пробелами.
Ну, тогда можно так:
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
#define _CRT_SECURE_NO_WARNINGS
#include <iostream>
#include <sstream>
 
struct student
{
    char* name;
    char* subject;
    int mark;
};
 
void LineToStudent(student *Student, std::string &line)
{
    std::istringstream iss(line);
    std::string word;
    
    iss >> word;
    Student->name = new char[word.length()+1];
    strcpy(Student->name, word.c_str());
 
    iss >> word;
    Student->subject = new char[word.length() + 1];
    strcpy(Student->subject, word.c_str());
 
    iss >> Student->mark;
}
 
void ClearStudent(student *Student)
{
    delete [] Student->name;
    delete[] Student->subject;
    delete Student;
}
 
int main()
{
    std::string line = "Vasya History 2";
 
    student *Student = new student;
    LineToStudent(Student, line);
 
    std::cout << "Name: " << Student->name << "\nSubject: " << Student->subject << "\nMark: " << Student->mark;
 
    std::cin.get();
    ClearStudent(Student);
    return 0;
}
Добавлено через 17 минут
И о преимуществах string

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
#include <iostream>
#include <sstream>
 
struct student
{
    std::string name;
    std::string subject;
    int mark;
};
 
void LineToStudent(student *Student, std::string &line)
{
    std::istringstream iss(line);
    iss >> Student->name >> Student->subject >> Student->mark;
}
 
int main()
{
    std::string line = "Vasya History 2";
 
    student *Student = new student;
    LineToStudent(Student, line);
 
    std::cout << "Name: " << Student->name << "\nSubject: " << Student->subject << "\nMark: " << Student->mark;
 
    std::cin.get();
    delete Student;
    return 0;
}
1
Bushmeister
22 / 22 / 10
Регистрация: 19.03.2015
Сообщений: 137
21.04.2015, 11:06 #20
blablabla - это лишь(несуществующая :о) переменная для примера, тем более я не указывал насколько далеко зайдет счетчик. А вылезет за пределы памяти или нет - это уже проблемы программиста. Я лишь показывал как удобно устанавливать нулевой символ так, чтобы при выводе не было мусора. Ещё даже указал, что внимание туда, а не на условие цикла)
зачем на каждом проходе записывать терминальный 0?
Лишние переменные счетчики вне тела циклы - очень нехорошо. А так можно в любой момент прервать цикл и при этом вывод переменной будет правильный, без мусора(не забывая, что все переменные объявленные в цикле пропадут и о них не надо будет заботиться).
это пожелание а не требование
Дк надо сразу учиться правильно.
0
21.04.2015, 11:06
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
21.04.2015, 11:06

Измените структуру CStash чтобы данные хранились в объекте типа vector<char>
Измените структуру CStash чтобы данные хранились в объекте типа vector&lt;char&gt; ...

Запись в структуру
Вот такой вот вопрос - Есть структура struct scan_data{ char login; ...

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


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

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

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