| Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате |
| Форум программистов > C/C++: Общие вопросы > Тип String |
| Автор: mr.Anderson 5.8.2005, 13:58 | ||
Есть код:
Задача: считать введенный пользователем текст, записать его в файл. - ну, дальше я сделал. НО! Программа выполняется В КОНСОЛИ! Т.е. это консольное приложение, а не Windows! Поскольку надо считать весь текст, введенный пользователем в консоль, тип char не подходит (ведь переменные этого типа хранят 1 символ). Я думаю, что тут подходит тип String. Но как записать переменную этого типа в файл? Обычные функции типа fprintf, fwrite, putc у меня не сработали. Что делать? |
| Автор: Дрон 5.8.2005, 14:11 | ||
| А что это за тип такой String? И где ты в переменную текст-то считывешь? А если попробовать:
|
| Автор: ManiaK 5.8.2005, 14:15 | ||||
В Си++ нет встроенного типа String. В стандартной библиотеке есть класс string. С помощью него можно сделать это так:
|
| Автор: Дрон 5.8.2005, 14:19 |
| Кстати, я бы рекомендовал в fopen явно указывать текстовый или двоичный файл мы используем, т.е. fopen("howmuch.txt","wt") для текстового и fopen("howmuch.txt","wb") для двоичного А то я видел реализации fopen, которые не знают типа файла по умолчанию и выдают ошибку. |
| Автор: ManiaK 5.8.2005, 14:28 | ||
Угу. У меня был компилятор какой-то, который глючил если не указать параметр 'b' и читал вместо текста ерунду какую-то. |
| Автор: mr.Anderson 5.8.2005, 16:23 | ||||||||
Я это знаю. При описании своей проблемы я имел в виду именно библиотечный класс. Кстати, с маленькой буквы он у меня не пишется... Только с большой. Причем компайлер считает его типом AnsiString. Он чем-нибудь отличается?
Сейчас попробую. Добавлено @ 16:26 Да, Maniak, еще пара вопросов. В вашем коде написано
Вопрос 1. Разве надо писать "use"? А не "using"? Вопрос 2. Можно ли эту строку не писать, а написать вот так:
Или тут что-то не так? |
| Автор: Дрон 5.8.2005, 16:27 | ||
Так бы сразу и говорил, что используешь C++ Builder'ом! Тогда можно писать так: fputs(text.c_str(), file); или fprintf(fp,"%s", text.c_str()); или в двоичный файл: fwrite(text.c_str(), 1, strlen(text.c_str()), file); |
| Автор: mr.Anderson 5.8.2005, 16:29 | ||
| Вопрос 3. В вашей функции fwrite вы ничего не напутали с порядком аргументов? Вроде, по ее прототипу сначала должен идти размер вводимых данных, а уж только затем - количество блоков текста (кстати, что это такое - блоки?). Разве должно быть не так:
А? И потом, почему у вас в коде в аргументах этой функции стоит string, когда имя переменной text? (в приведенном тут своем коде я это поправил). Прошу ответить на все вопросы. Добавлено @ 16:31 Дрон, нет, стоп! Я пишу в Билдере, но через запущенный мастер Console Wizard, т.е. в принципе никакого билдера там нет... |
| Автор: ManiaK 5.8.2005, 16:42 | ||||
Не знаю, я как-то экспериментировал с этими параметрами - что так, что так работает.
Если так, то мой способ правильнее. Сначала идёт размер одного блока данных (в данном случае - символ, 1 байт), а потом - количество блоков (тут правда описался, test.size() должно быть Всё это работает не только в Билдере. А вот String, судя по всему, чисто билдеровский тип. В стандартной библиотеке его нет. |
| Автор: Дрон 5.8.2005, 16:45 | ||||
А какие у тебя include написаны?
Да это не особо важно. Это имеет смысл скорее при чтении, т.к. fread возвращает именно количество прочитанных блоков, а не байт. Добавлено @ 16:47 Блок в данном случае -- это минимальный элемент данных. Например, если ты пишешь массив, то логично сделать так: кол-во блоков = кол-во элементов массива размер блока = sizeof(одного элемента массива) Хотя от того, что ты напишешь кол-во блоков = 1 размер блока = кол-во элементов массива * sizeof(элемента) ничего не изменится. |
| Автор: mr.Anderson 5.8.2005, 16:49 | ||
| Maniak, странно как-то получается. В заранее определенной функции можно переставлять местами аргументы?! Вот это да. Дрон, вот такие у меня инклуды:
А функцию мы используем fwrite, а не fread. Добавлено @ 16:51 ManiaK, да, кстати, я пару постов назад еще два вопроса задал. Ответье на них, пожалуйста. |
| Автор: Дрон 5.8.2005, 16:52 | ||||
Что и требовалось доказать VCL -- это и есть главная библиотека Билдера, в которой определены все классы вроде AnsiString, TForm и прочих Добавлено @ 16:53
1. Конечно using 2. Да. Только переменная называется text, а не string |
| Автор: mr.Anderson 5.8.2005, 16:54 |
| А-а-а... Она просто подрубается по умолчанию (при создании шаблона через Console Wizard она уже подключена), поэтому я ее и не вырубал - вдруг все работать перестанет? |
| Автор: Дрон 5.8.2005, 16:55 |
| sim7 Если ты её не подключишь, то у тебя не будет AnsiString |
| Автор: ManiaK 5.8.2005, 16:56 | ||||||
Отвлекаюсь, ошибки делаю
Для консоли можно. Добавлено @ 16:57
Ну и нафиг он не нужон... |
| Автор: mr.Anderson 5.8.2005, 17:01 | ||||||
А он вообще нужен? Maniak, написал вот это:
Пишет ошибку:
Что такое? И еще: как в объявленную переменную text загнать текст, введенный пользователем в консоли? |
| Автор: Дрон 5.8.2005, 17:03 | ||
| Уфф... Люди вы что, с Луны свалились? Пиши
|
| Автор: ManiaK 5.8.2005, 17:05 | ||
Всё нормально, я эту ветку в закладки брошу - чуть что, сразу пошлю сюда |
| Автор: Дрон 5.8.2005, 17:05 | ||||||
Во-первых
Во-вторых
|
| Автор: mr.Anderson 5.8.2005, 17:06 |
| Дрон, а как же тип string? |
| Автор: Дрон 5.8.2005, 17:07 | ||
Э-э-э... А что с ним не так? |
| Автор: mr.Anderson 5.8.2005, 17:07 |
| Про загон понял, а все же, тип string куда девать? Как с ним сделать (уж очень с ним хочется |
| Автор: Дрон 5.8.2005, 17:08 |
| sim7 Так я ж его и использовал. |
| Автор: Fixin 5.8.2005, 17:08 | ||||
|
| Автор: mr.Anderson 5.8.2005, 17:09 |
| И еще: #include <iostream> и #include <iostream.h> эквивалентны или нет? Про тип string - я имею в виду, ваша строчка отличается от той, что Maniak указал. Приведите весь фрагмент моего кода (который я в 1-м посте дал) в переделанной форме. |
| Автор: Дрон 5.8.2005, 17:09 |
| Fixin Уже есть. Просто fwrite первым параметром принимает void* |
| Автор: mr.Anderson 5.8.2005, 17:10 |
| А как же тогда? В общем, приведите весь код в целости (см предыдущий мой пост). |
| Автор: Fixin 5.8.2005, 17:10 |
| Да быстро очень... не успеваю |
| Автор: Дрон 5.8.2005, 17:13 | ||||
Почти. Для iostream.h не надо приставки std:: перед cin. Просто в VS7, где я пишу есть только iostream
И кстати, если уж используем cin, то логичней вместо puts использовать cout. |
| Автор: Fixin 5.8.2005, 17:13 | ||
|
| Автор: Дрон 5.8.2005, 17:15 |
| Fixin У тебя тоже string вместо text ЗЫ: Я от этой темы помру со смеху... |
| Автор: mr.Anderson 5.8.2005, 17:15 |
| А зачем? Разве есть разница, если надо вывести просто текст? И еще вопрос. Если используется cin, то, значит, текст будет принят после нажатия Enter. А мне это не нужно. Ведь прога должна считать еще и количество переводов строки. Как это обеспечить? |
| Автор: Fixin 5.8.2005, 17:16 | ||||||
Ну если
|
| Автор: Дрон 5.8.2005, 17:16 | ||||
Для единообразия.
А таких функций нет. Придумывай сам. И, кстати, а чем тогда окончание ввода будет обозначаться? |
| Автор: mr.Anderson 5.8.2005, 17:17 |
| Fixin, как это? Объявлять указатель на файл надо (это я по учебнику делал). Иначе с файлом оперировать не получится... |
| Автор: ManiaK 5.8.2005, 17:18 | ||||
Дрон не флеймим
Зациклить. Что-то вроде:
|
| Автор: Дрон 5.8.2005, 17:18 | ||
sim7
Он имеет ввиду, что надо использовать функции из iostream, а не из stdio... Но ты забудь... Не забивай голову |
| Автор: mr.Anderson 5.8.2005, 17:18 |
| Да елки! Никогда не успеваю ответить до другого участника! Здорово! Дрон, ну, предположим, будет символ ~ (тильда). Я просто не представляю, как увязать cout и символ конца ввода... |
| Автор: Fixin 5.8.2005, 17:20 | ||||
|
| Автор: mr.Anderson 5.8.2005, 17:20 |
| Ешкин кот! Опять не успел! Maniak, но тогда ведь придется пользователю вводить текст посимвольно. Т.е. символ-энтер, символ-энтер и т.д. Я пробовал этот вариант, но он же неверный в данной задаче. |
| Автор: ManiaK 5.8.2005, 17:21 | ||||
Никак. Тут можно так сделать (с тильдой):
|
| Автор: Fixin 5.8.2005, 17:22 | ||
|
| Автор: Дрон 5.8.2005, 17:22 | ||
| sim7 Я бы всё сделал вообще по-другому...
Ввод закончится либо после 1024 символов, либо по нажатию ESC |
| Автор: mr.Anderson 5.8.2005, 17:23 |
| Ну, тогда ведь и получится, как я сказал, Maniak. А вводить текст побуквенно не совсем реально, по-моему. |
| Автор: Дрон 5.8.2005, 17:23 | ||
Fixin
Ну не очень... ЗЫ: Хочу на этой теме до 1000 постов дойти |
| Автор: Fixin 5.8.2005, 17:24 | ||
|
| Автор: ManiaK 5.8.2005, 17:24 |
| При использовании функции getch нажатие необходимости в нажатии ввода нет. |
| Автор: mr.Anderson 5.8.2005, 17:24 |
| Дрон, интересное предложение... Можете объяснить свой код? А то я не совсем въехал... С указателями всегда путался... |
| Автор: Fixin 5.8.2005, 17:24 | ||
|
| Автор: mr.Anderson 5.8.2005, 17:25 |
| Maniak, у меня вообще при использовании getch() в консоли текст не вводится. Нажимаю клавиши, и никакой реакции. Я тоже хотел изначально такой способ использовать. |
| Автор: ManiaK 5.8.2005, 17:26 |
| Дрон, Fixin угомонитесь |
| Автор: Fixin 5.8.2005, 17:26 | ||||
Добавлено @ 17:26
|
| Автор: mr.Anderson 5.8.2005, 17:27 | ||
| Я ж попросил объяснить, Fixin. Добавлено @ 17:27
Абсолютно, за исключением энтеров. |
| Автор: ManiaK 5.8.2005, 17:28 | ||
Модератор: если это продолжится - приму меры!
Код пожалуйста в студию. |
| Автор: Дрон 5.8.2005, 17:29 | ||
Этот код надо вставить за место всего того, что у тебя в блоке else. |
| Автор: Дрон 5.8.2005, 17:31 | ||||
Если присмотреться, то у меня используется getche, которая выводит символ на экран. // offtop
Я имел ввиду свою 1000 Вот уже и 1 пост остался. ManiaK Сорри. Меня просто от этой темы изначально расплющило... |
| Автор: mr.Anderson 5.8.2005, 17:32 | ||
Ах, да. Ну, пробовал вот так вот:
|
| Автор: Fixin 5.8.2005, 17:34 | ||||
2 ManiaKИзвини, не понял вопроса |
| Автор: mr.Anderson 5.8.2005, 17:35 |
| Fixin, а я-то думаю, чего у меня она не работала... Укажите ее прототип, плиз. |
| Автор: Fixin 5.8.2005, 17:42 | ||||
Вот формат:
В твоем примере нужно так:
Буква "f" перед этой функцией обозначает форматный вывод. Про формат читай справку, должно быть |
| Автор: ManiaK 5.8.2005, 18:03 | ||||
Вот этот код:
Заменить на этот:
Тогда и символы вводимые будут отображаться и закончится ввод на тильде. |
| Автор: mr.Anderson 5.8.2005, 18:12 |
| Спасибо! Пойду пробовать. Сейчас отпишу, что получится. Добавлено @ 18:15 Отлично! Maniak, полный порядок. Ваш код вполне сработал. Осталось только придать ему "красоты". Спасибо большое всем, кто мне тут помогал. Просто огромное спасибо. И еще: несмотря на то, что я использовал код без класса string, все равно его изучение в этой теме для меня лишним не было. |
| Автор: mr.Anderson 5.8.2005, 19:38 |
| Так. Стоп-с. Одна проблема. Enter вводить нельзя. Почему-то. Когда его нажимаешь, то указатель курсора в консоли становится на начало строки, и весь текст просто перетирается (переписывается) новыми буквами, которые я потом ввожу. Кстати, когда нажимаешь Backspace, то указатель тоже просто перемещается на 1 позицию назад, и при последующем вводе букв опять-таки просто "перетирает" символы. Как поправить? |
| Автор: mr.Anderson 5.8.2005, 20:10 | ||
| Что, устали отвечать? А как тут все бойко шло час назад... Эх... Но эту проблему я сам решил. Если у кого еще будет такой вопрос, то надо просто подставить в код проверку на нажатие энтера вот таким вот кодом:
Вот и все! Теперь ваши консольные приложения будут вполне адекватно обрабатывать нажатие клавиши Enter. |
| Автор: Fixin 5.8.2005, 20:34 |
| Забой не работает тк ты читаешь каждый символ по отдельности из буфера и забираешь его. Потому ты не можешь удалить последний введенный символ из буфера тк его там уже нет. С ентером прикольно получилось. |
| Автор: mr.Anderson 5.8.2005, 20:51 | ||
| Нравится? Сам радуюсь. Теперь еще задача. Тоже с использованием типа string, наверное, поэтому, ув. модераторы, это не оффтопик. Задача такая. Пользователь вводит (опять же, в консоли) путь к файлу (естественно, в путь включено и имя). И вот надо открыть файл по указанному пути и обработать его. Я попробовал так:
Но компайлер ругается, что в прототипе функции fopen нет места переменным типа string. Так как же решить эту задачу? |
| Автор: ManiaK 5.8.2005, 21:20 | ||
Приведением к типу char*, уже писали сто раз.
Открой любой справочник по STL и найди там string. Не стоит засорять данный форум подобными вопросами. Я подниму вопрос по созданию чего-нибудь вроде школьного форума по Си++ раз такое дело получается, но вообще гораздо выгоднее дойти до технического решения самому - проще потом будет. |
| Автор: mr.Anderson 5.8.2005, 21:23 |
| Это понятно, но я бы, конечно, не догадался так сделать. Спасибо! Сейчас буду пробовать. |
| Автор: mr.Anderson 6.8.2005, 08:48 | ||
| Программа-то скомпайлилась, но не так работает, как надо. Что бы я в консольном окне не написал, прога все равно пишет, что не может открыть файл... Код-то верный, может, я что не так набираю? Как надо писать имя файла в консоли? Пример приведите. Если надо, вот код:
|
| Автор: Guest 6.8.2005, 10:50 | ||
Как и в gui. Если не работает, значит считываешь имя файла не так(если считываешь посимвольно, то проверь чтобы в имя файла не попадали символы быкспейса и ентера). В конце концов выведи file_name на экран/посмотри в отладчике. и еще - while((x==getc(c_file))!=EOF) заменить на while((x=getc(c_file))!=EOF). Кстати, а компилер не ругается? ЗЫ. Если указываешь имя файла в коде, то не забывай удваивать все \ знаки - то есть rebuild rebuild_source_file("c:\\autoexec.bat") ЗЫЫ. Ой нафлудили |
| Автор: Guest 6.8.2005, 10:55 | ||||||
| (Guest это был Mayk) Ну чтобы эта мессага не совсем флуд была, то выскажу еще свое имхо, что смешивать С++ с С нехорошо. В плюсах есть удобные fstream для файлов. И еще -
вместо gets стоит использовать fgets
|
| Автор: Fixin 6.8.2005, 11:29 | ||||
|
| Автор: Mayk 6.8.2005, 11:43 | ||
Да так же - константа EOF, которую возвращает fgetc при конце файла, равна -1(0xFFFFFFFF), в то время как размер char'а ограничен одним байтом(0xFF максимум). Ну двумя, если мы о wchar_t будем говорить. Поэтому fgetc'у нет принципиальной разницы, бинарен файл, или нет. Плюс еще feof(FILE* stream) есть. Только из контекста я понял, что файл как раз текстовой, а не бинарный. |
| Автор: En_t_end 6.8.2005, 12:37 |
| sim7 Маленькое замечание. Двойные кавычки в контексте C++ в большинстве случаев используются для обозначение строки. "\n" - хоть ошибкой и не является, но в некоторых местах программы это может сбить с толку читающего программу. |
| Автор: mr.Anderson 6.8.2005, 12:58 | ||
| Да, файл текстовый. А про двойные кавычки - это о чем? Где я их вместо одинарных использовал? Что-то не найду никак... И я еще раз повторюсь. Прога вообще не воспринимает имя файла. В консоли пишу:
По коду после этого ввода запускается описанная выше функция rebuild_source_file(std::string file_name) с новым значением. Файл newtext.txt расположен в директории самой программы, поэтому нет смысла указывать путь. Однако, выдается Fatal Error (по моему коду это тогда, когда файл нельзя открыть). Так в чем же дело-то?! |
| Автор: Fixin 6.8.2005, 20:14 | ||||
Измени код
Добавлено @ 20:14 И посмотри, что напишет. |
| Автор: mr.Anderson 7.8.2005, 11:29 |
| Ладно, сейчас попробую. |
| Автор: mr.Anderson 7.8.2005, 11:53 | ||||
Я для верности вставил имя файла в кавычки, так он нарисовал в этих кавычках квадратик, а затем несколько пробелов, общая длина которых равна длине имени файла! А вы сами попробуйте! Вот мой полный код:
Имя файла у меня "text.txt". Я его изначально создал в директории программы и попытался открыть. Ноль внимания (в смысле, ошибка). И еще вопрос. Почему, когда я переменную file_name заранее переделал в строковый тип вот так:
Чтобы потом не забывать это писать и не ошибаться, компайлер снова заорал, что в fopen не может быть типа char (!)? |
| Автор: Void 7.8.2005, 12:40 | ||||||
| sim7 Давайте уже определяться, что мы используем - сишные строки и stdio или std::string и iostreams. Потому что одно с другим плохо сочетается.
Вот за это люди и не любят stdio. Компилятор молча пропустил грубейшую ошибку: если в строке формата стоит %s, то в качестве параметра должен быть char*, ссылающийся на буфер достаточной длины. А мы что передали? Правильно, указатель на объект типа std::string. Что у нас получилось? Правильно, undefined behaviour и вообще повезло, что все сразу не упало.
Это попытка избежать варнинга? Неудачная, потому что в данном случае надо именно:
|
| Автор: mr.Anderson 7.8.2005, 13:34 | ||||||
А как с ними делать надо? Перепишите мой код по новой...
А как же надо? Ведь имя файла не может быть типа char, он же хранит 1 символ...
Вот это действительно моя ошибка. В общем, перепишите мой код со string. А тоя так до след. года биться буду. |
| Автор: mr.Anderson 7.8.2005, 13:48 | ||||||
УРА!!!
Однако, осталась проблема. В файле text.txt, который я открываю через эту программу, находится текст:
Но программа, выводя содержимое файла через инструкцию else в функции перестройки файла в моем коде, выводит какие-то цифры:
Почему так и как это исправить? |
| Автор: mr.Anderson 7.8.2005, 15:31 |
| Люди! Я вопрос задал! Почему читается не текст, а цифры (см. пред. пост)?! Помогите! |
| Автор: Void 7.8.2005, 16:19 | ||
| sim7 Очень просто - x имеет тип int - целое число. И в cout выводится в соответствующем виде. Можно сделать вот так: cout << char(x); Или вовсе перейти полностью на потоки:
std::string умеет сам выводиться в поток, поэтому писать cout << s.c_str() бессмысленно. |
| Автор: mr.Anderson 8.8.2005, 17:27 | ||
Спасибо, разобрался. Действительно, дело было в типе. Я объявил ее как int, потому что в учебнике было написано:
|
| Автор: Void 8.8.2005, 20:06 |
| sim7 В учебнике написано правильно. Но это расчитано на модель ввода/вывода stdio, где типы всегда указываются явно. А здесь опять пошла мешанина из потоков и stdio. |
| Автор: mr.Anderson 8.8.2005, 20:32 |
| Ну, надо же. А я уж было собрался в учебнике править... |