Я прочитал строки с пробелами в них, используя следующий оператор scanf()
.C язык программирования (scanf)
scanf("%[^\n]", &stringVariableName);
Что означает строка управления [^\n]
?
Есть ли способ читать строки с таким пробелом?
Я прочитал строки с пробелами в них, используя следующий оператор scanf()
.C язык программирования (scanf)
scanf("%[^\n]", &stringVariableName);
Что означает строка управления [^\n]
?
Есть ли способ читать строки с таким пробелом?
Это значит «прочитать что-нибудь, пока вы не найдете„\ п“»
Это нормально, но было бы лучше, чтобы сделать это «что-нибудь прочитать, пока вы не найдете„\ п“, или читать больше символов, чем мой буфер поддержки»
char stringVariableName[256] = {}
if (scanf("%255[^\n]", stringVariableName) == 1)
...
Edit: убрана & от аргумента, и проверить результат зсапЕ.
+1 для правильного использования размера переменной в спецификации формата. –
@JonathanLeffler Прискорбно, что ширина поля, по-видимому, является единственным фокусом. Есть еще две проблемы с этим кодом. Интересно, найдет ли кто-нибудь еще их ... – Sebivor
@undefinedbehaviour: Адрес массива; и проверить возвращаемое значение из 'scanf()'? Да, вам нужно пойти с тем, что там ... –
Указатель формата "%[^\n]"
дает указание scanf()
читать, но не включает символ новой строки. Из связанного ссылочной страницы:
matches a non-empty sequence of character from set of characters. If the first character of the set is ^, then all characters not in the set are matched. If the set begins with ] or ^] then the ] character is also included into the set.
Если строка находится на одной линии, fgets()
является альтернативой, но символ новой строки должны быть удалены, как fgets()
записывает его в выходной буфер. fgets()
также заставляет программист, чтобы указать максимальное количество символов, которые могут быть считаны в буфер, что делает его менее вероятно, для переполнения буфера произойдет:
char buffer[1024];
if (fgets(buffer, 1024, stdin))
{
/* Remove newline. */
char* nl = strrchr(buffer, '\n');
if (nl) *nl = '\0';
}
Можно указать максимальное количество символов для чтения через scanf()
:
scanf("%1023[^\n]", buffer);
, но нельзя забывать, чтобы сделать это для fgets()
, как компилятор будет жаловаться. Хотя, конечно, программист мог указать неправильный размер, но по крайней мере они вынуждены это учитывать.
Чтение с человеком страниц для scanf()
...
[Соответствует непустой последовательности символов из определенного набора принятых символов; следующий указатель должен быть указателем на символ, и должно быть достаточно места для всех символов в строке, а также завершающего нулевого байта. Обычный пропущенный пробел подавляется. Строка должна состоять из символов в (или не в) конкретном наборе; набор определяется символами между открытым кронштейном [символ и закрывающей скобкой] символ. Набор исключает эти символы, если первый символ после открытой скобки является circumflex (^). Чтобы включить скот в комплект, сделайте его первым символом после открытой скобки или circumflex; любая другая позиция закончит набор. Символ дефиса - также особенный; при размещении между двумя другими символами он добавляет все входящие символы в набор. К прилагается дефис, сделайте его последним символом перед окончательным закрытием скобки . Например, [^] 0-9-] означает набор «все, кроме , закройте скобки, от нуля до девяти и дефис». Строка заканчивается на внешностью символа, не входящего в комплект (или с набором circumflex, in), или когда заканчивается ширина поля.
В двух словах, [^ \ п] означает, что читать все из строки, которая не является \n
и хранить, что в указателе согласования в списке аргументов.
Другие люди объяснили, что значит %[^\n]
.
не хороший способ читать строки. Это так же опасно, как и небезопасное небезопасное gets
, и по той же причине: он понятия не имеет, насколько велик буфер на stringVariableName
.
Лучший способ прочитать одну полную строку из файла - getline
, но не у всех библиотек C есть это. Если вы этого не сделаете, вы должны использовать fgets
, который знает, насколько велик буфер, и помните, что вы не можете получить полную строку (если строка слишком длинная для буфера).
'get' * может * знать, насколько большой буфер ... – Sebivor
@undefinedbehaviour Я могу представить себе компилятор, который переписывает' char buf [N]; ... получает (buf); 'как' fgets (buf, N, stdin); 'но насколько я знаю, никакой компилятор в производстве не делает этого. Это то, о чем вы думаете? В противном случае, пожалуйста, объясните. – zwol
Как «realloc» знает, сколько байтов копировать из старого в новый? – Sebivor
Технически это невозможно определить.
Соответствует непустой последовательности символов из набора ожидаемых символов (сканирование).
Если ни один модификатор л Длина не присутствует, то соответствующий аргумент должен быть указателем на начальный элемент символьного массива достаточно большого принять последовательность и завершающий нулевой символ, который будет добавлен автоматически.
Предположив декларацию stringVariableName
выглядит char stringVariableName[x];
, то &stringVariableName
является char (*)[x];
, не char *
. Тип неправильный. Поведение не определено. Это может Работа по совпадению, но все, что полагается на совпадение, не Работа по моему определению.
Единственный способ сформировать char *
с помощью &stringVariableName
, если stringVariableName
является символ! Это означает, что массив символов достаточно велик, чтобы принять завершающий нулевой символ. В случае, когда пользователь вводит один или несколько символов перед нажатием enter, scanf будет писать за пределами массива символов и вызывать неопределенное поведение. В случае, когда пользователь просто нажимает кнопку ввода, директива %[...]
потерпит неудачу и даже '\0'
не будет записана в ваш массив символов .
Теперь, с этим все сказано и сделано, я предполагаю, что вы имели в виду следующее: scanf("%[^\n]", stringVariableName);
(примечание опущенной амперсанд)
Вы действительно должны проверять возвращаемое значение !!
A %[
Директива %[
вызывает scanf для извлечения последовательности символов, состоящих из тех, которые указаны между квадратами квадратных скобок [
]
. A ^
в начале набора указывает, что нужный набор содержит все символы, кроме тех, которые находятся между скобками. Следовательно, %[^\n]
сообщает scanf читать как можно больше символов не '\n'
и хранить их в массиве, на который указывает соответствующий char *
.
'\n'
будет оставлен непрочитанным. Это может вызвать проблемы. Пустое поле приведет к ошибке совпадения. В этой ситуации возможно, что никакие данные не будут скопированы в ваш массив (даже не заканчивающийся символ '\0'
). По этой причине (и другим), вам действительно нужно проверить возвращаемое значение!
В каком руководстве содержится информация о возвращаемых значениях scanf? The scanf manual.
Я рекомендую использовать fgets. – BLUEPIXY
Не забудьте прочитать новую строку, которую вы оставляете в потоке. Кроме того, вы, вероятно, хотите указать максимальную длину, чтобы избежать переполнения буфера. – effeffe
Bluepixy является правильным. scanf - большой риск для безопасности. – ncmathsadist