C/C++ - Проблема с cin.getline()

Ответить
Аватара пользователя
Chilli

C/C++ - Проблема с cin.getline()

Сообщение Chilli »

В некоторой части программы требуется ввести строку (включая пробелы), для чего я решил использовать cin.getline().



Код:

Код: Выделить всё

char *text;
text=new char;
. . . . .
cin.sync();
cin.getline(text,sizeof(text));
OemToCharA(text,text);
cout<<text; // проверка
cin.sync();
cin.clear();
cin>>hz;
. . . . .

При таком раскладе из введенной строки выводятся первые 3 символа, остальное куда-то пропадает.

Если написать, к примеру, cin.getline(text,40); , т.е. ограничить строку до 40 символов включая символ перехода на след. строку, тогда никаких проблем нет.

Но задача состоит как раз таки в том, чтобы через cin.getline() вывести строку, размер которой, так сказать, динамический.

Я, конечно, подозреваю, что подобное невозможно без ограничения/декларации символьного массива, но все же - возможно ли решить такую проблему?
Аватара пользователя
pva

Re: C/C++ - Проблема с cin.getline()

Сообщение pva »

Код:

Код: Выделить всё

char *text; //1
text=new char; //2

(1) text имеет тип char* (указатель на char), его размер sizeof(text) = 4

(2) new char() вернёт указатель на 1 (!) символ. Попытка записи туда более 1 символа приведёт к порче разметки памяти.

basic_istream::getline считывает символы и складывает их в заранее выделенную память, поэтому на вход ему надо подсовывать столько памяти, во сколько уместится самая большая строка, которую хочешь прочитать. Размер строки можно потом узнать поиском нулевого символа '\0'.

Доставшаяся `C++` строка char* по наследству от `C` не умеет сама менять свой размер. Вместо этого нужно выделять новую память, копировать туда новое содержимое строки и удалять старую память.

Если тебе нужно такую строку, которая умеет менять свой размер, используй шаблон basic_string.



Код:

Код: Выделить всё

#include <string>
using namespace std;
...
string text;
// в файле string определена глобальная функция
// getline(basic_istream<..>& source, basic_string<..>& dest, int char_delimiter='\n');
getline(cin, text);
cout << text << endl;

В различных версиях STL может быть по-разному, но как правило внутри string содержится char*, для которого сделано автоматическое управление памятью.
Аватара пользователя
ganselo

Re: C/C++ - Проблема с cin.getline()

Сообщение ganselo »

Цитата Chilli:



При таком раскладе из введенной строки выводятся первые 3 символа, остальное куда-то пропадает.
C/C++ - Проблема с cin.getline()




siezof(text) возвращает 4, следовательно cin записывает 3 символа и плюс один на \0.




Цитата Chilli:



char *text; text=new char;
C/C++ - Проблема с cin.getline()




вы динамически выделили память под 1 символ, а пытаетесь записывать строку.




Цитата Chilli:



Но задача состоит как раз таки в том, чтобы через cin.getline() вывести строку, размер которой, так сказать, динамический.
C/C++ - Проблема с cin.getline()




Используйте класс std::string.





Код:

Код: Выделить всё

#include <iostream>
#include <string>
using namespace std;
int main()
{
    string text;
    getline(cin, text);
    cout << text << endl;
}

Пока писал, pva опередил с ответом)
Аватара пользователя
Chilli

Re: C/C++ - Проблема с cin.getline()

Сообщение Chilli »

pva,
Цитата pva:



Код:

#include

using namespace std;

...

string text;

// в файле string определена глобальная функция

// getline(basic_istream& source, basic_string& dest, int char_delimiter='\n');

getline(cin, text);

cout
num;
cin.sync();
do
{
coutch;
cin.sync();
}
while (ch!='y' && ch!='n');
if (g1)
{
s=gr.st=new students;
q->next=s;
q=s;
}
else
{
top=q=gr.st=new students;
g1=true;
}
while (ch=='y')
{
f=true;
q->fio=new char;
q->bk=new char;
q->mark=new int[5];
coutfio,q->fio);
do
{
coutch;
cin.sync();
switch (ch)
{
case 'b':
q->bk="Бюджет";
break;
case 'k':
q->bk="Контракт";
break;
}
}
while (ch!='b' && ch!='k');
coutNEXT=0;
break;
case 2:
system("cls");
S=TOP;
while (S)
{
cout[/code]
По задаче с помощью программы нужно записать студенческий поток при помощи списков, где относительно групп вводится только номер каждой группы, а относительно студентов вводятся ФИО, форма обучения, 5 оценок и стипендия. Это малая часть того, что будет в итоге, но не суть. Код очень трудно читать, т.к. я отвык комментить строки и, к сожалению, лень временами отделять куски кода пустыми строками.

В общем проблема возникла именно с вводом ФИО.

Стоит оставить все в таком виде или все таки есть вариант преобразования string в char* ?
Аватара пользователя
ganselo

Re: C/C++ - Проблема с cin.getline()

Сообщение ganselo »

Цитата Chilli:



Стоит оставить все в таком виде или все таки есть вариант преобразования string в char* ?
C/C++ - Проблема с cin.getline()




Используйте:

char *string::c_str();



Код:

Код: Выделить всё

string text = "text";
printf(text.c_str());
Аватара пользователя
Drongo

Re: C/C++ - Проблема с cin.getline()

Сообщение Drongo »

Chilli, Прошу прощения, возможно я неправильно понял задачу. Так не пойдёт?



Код: Выделить всё

#include <iostream>
using namespace std;
int main()
{
  const int sizeString = 510;  // размер символьного массива ввода
  char string[sizeString];  // массив ввода
  int z;
  cout<<"   Array 510 Characther!!!\n\n"; // приглашение ввода
  cin.getline(string, sizeString, '\n');  // функция ввода
  cout<<endl;
  cout<<string<<endl;   // ПРОВЕРКА: введённого массива, вывод массва
  cin>>z;
  return 0;
}
//---------------------------------------------------------------------------
Аватара пользователя
pva

Re: C/C++ - Проблема с cin.getline()

Сообщение pva »

Цитата Chilli:



но такие строки не прогнать через OemToChar()
C/C++ - Проблема с cin.getline()




std::string этому нисколько не препятствует. Как правило string сделана как массив из char, поэтому можно пользоваться конструкцией типа:



Код:

Код: Выделить всё

string
    str_1251 = "ывалорфывадлвр",
    str_oem;
str_oem.resize(str_1251.size());
CharToOem(str_1251.c_str(), &str_oem[0], str_oem.size());
cout << str_oem << endl;

но я бы посоветовал либо выставлять в консоли кодировку 1251 (chcp 1251), либо исходник писать в кодировке 866, и не париться.



Ещё, как вариант, можно вынести отдельно текстовые ресурсы, тогда ещё и на разные языки переводить программу можно будет
Ответить

Вернуться в «Программирование и базы данных»