Лучшая опция ... просто разделите все незнаковые символы на входе (кроме знаков «x» и «впереди» +), заботясь о том, что британская тенденция писать числа в нестандартной форме +44 (0) ...
, когда попросил использовать международный префикс (в этом конкретном случае вы должны полностью отбросить (0)
).
Затем вы получите такие значения, как:
12345678901
12345678901x1234
345678901x1234
12344678901
12345678901
12345678901
12345678901
+4112345678
+441234567890
Тогда, когда вы показываете, переформатируете в свои сердца. например,
1 (234) 567-8901
1 (234) 567-8901 x1234
Немного уродливый способ:
char *pos;
if ((pos=strchr(Name, '\n')) != NULL)
*pos = '\0';
else
/* input too long for buffer, flag error */
Немного странный способ:
strtok(Name, "\n");
Обратите внимание, что функция strtok
не работает должным образом, если пользователь входит пустую строку (т.е. нажмите только Enter). Он оставляет неизменным \n
.
Конечно, есть и другие.
Прямо удалить «\n» из вывода fgets, если каждая строка имеет «\n»
line[strlen(line) - 1] = '\0';
В противном случае:
void remove_newline_ch(char *line)
{
int new_line = strlen(line) -1;
if (line[new_line] == '\n')
line[new_line] = '\0';
}
strnlen
вместо strlen
.
– Mike Mertsock
30 June 2013 в 02:37
n
не волшебным образом повышает безопасность, в этом случае это фактически сделает код более опасным. Аналогично strncpy
, ужасно опасная функция. Сообщение, с которым вы связались, является плохим советом.
– M.M
28 October 2015 в 21:55
""
). Также strlen()
возвращает size_t
не int
.
– alk
17 June 2017 в 09:55
Попробуйте следующее:
int remove_cr_lf(char *str)
{
int len =0;
len = strlen(str);
for(int i=0;i<5;i++)
{
if (len>0)
if (str[len-1] == '\n')
{
str[len-1] = 0;
len--;
}
if (len>0)
if (str[len-1] == '\r')
{
str[len-1] = 0;
len--;
}
}
return 0;
}
Ниже приведен быстрый подход к удалению потенциала '\n'
из строки, сохраненной в fgets()
. Он использует strlen()
с двумя тестами.
char buffer[100];
if (fgets(buffer, sizeof buffer, stdin) != NULL) {
size_t len = strlen(buffer);
if (len > 0 && buffer[len-1] == '\n') {
buffer[--len] = '\0';
}
Теперь используйте buffer
и len
по мере необходимости.
Этот метод имеет побочное преимущество len
значение для последующего кода. Это может быть быстрее, чем strchr(Name, '\n')
. Ref YMMV, но оба метода работают.
buffer
, из оригинала fgets()
не будет содержать в "\n"
при некоторых обстоятельствах: A) Линия был слишком длинным для buffer
, поэтому только char
, предшествующий '\n'
, сохраняется в buffer
. В потоке остаются непрочитанные символы. B) Последняя строка в файле не заканчивалась символом '\n'
.
Если на входе есть встроенные нулевые символы '\0'
в нем где-то, длина, сообщенная strlen()
, не будет содержать местоположение '\n'
.
Некоторые другие ответы ' Проблемы:
strtok(buffer, "\n");
не удаляет '\n'
, когда buffer
- "\n"
. Из этого ответа - изменен после этого ответа, чтобы предупредить об этом ограничении. char
, прочитанный fgets()
, является '\0'
. Это происходит, когда ввод начинается со встроенного '\0'
. Тогда buffer[len -1]
становится buffer[SIZE_MAX]
доступным к памяти, конечно, вне допустимого диапазона buffer
. Что-то хакер может попытаться найти в глупости чтения текстовых файлов UTF16. Это было состояние ответа , когда этот ответ был написан. Позже не-OP отредактировал его, чтобы включить код, подобный проверке этого ответа на ""
. size_t len = strlen(buffer);
if (buffer[len - 1] == '\n') { // FAILS when len == 0
buffer[len -1] = '\0';
}
sprintf(buffer,"%s",buffer);
- неопределенное поведение: Ref . Кроме того, он не сохраняет никаких ведущих, разделяющих или завершающих пробелов. Теперь удален . buffer[strcspn(buffer, "\n")] = 0;
, отличным от производительности, по сравнению с strlen()
. Производительность при обрезке обычно не является проблемой, поскольку код вводит I / O - черную дыру процессорного времени. Если следующий код нуждается в длине строки или имеет высокую производительность, используйте этот подход strlen()
. Иначе strcspn()
является прекрасной альтернативой. char name[1024];
unsigned int len;
printf("Enter your name: ");
fflush(stdout);
if (fgets(name, sizeof(name), stdin) == NULL) {
fprintf(stderr, "error reading name\n");
exit(1);
}
len = strlen(name);
if (name[len - 1] == '\n')
name[len - 1] = '\0';
""
). Также strlen()
возвращает size_t
не int
.
– alk
17 June 2017 в 09:56
Нижеприведенная функция является частью библиотеки обработки строк, которую я поддерживаю в Github. Он удаляет и нежелательные символы из строки, что вы хотите
int zstring_search_chr(const char *token,char s){
if (!token || s=='\0')
return 0;
for (;*token; token++)
if (*token == s)
return 1;
return 0;
}
char *zstring_remove_chr(char *str,const char *bad) {
char *src = str , *dst = str;
while(*src)
if(zstring_search_chr(bad,*src))
src++;
else
*dst++ = *src++; /* assign first, then incement */
*dst='\0';
return str;
}
Пример использования может быть
Example Usage
char s[]="this is a trial string to test the function.";
char const *d=" .";
printf("%s\n",zstring_remove_chr(s,d));
Example Output
thisisatrialstringtotestthefunction
Вы можете проверить другие доступные функции или даже внести свой вклад к проекту :) https://github.com/fnoyanisi/zString
*
в *src++;
и сделать bad
, token
и d
const char *
. Также почему не использовать strchr
вместо zChrSearch
? *src
не может быть '\0'
в вашей функции zStrrmv
.
– chqrlie
17 August 2016 в 14:43
strchr
– Fehmi Noyan ISI
21 October 2016 в 08:30
for(int i = 0; i < strlen(Name); i++ )
{
if(Name[i] == '\n') Name[i] = '\0';
}
Вы должны попробовать. Этот код в основном проходит через строку до тех пор, пока не найдет «\n». Когда он будет найден, '\n' будет заменен на нулевой символ terminator '\ 0'
Обратите внимание, что вы сравниваете символы, а не строки в этой строке, тогда нет необходимости использовать strcmp ():
if(Name[i] == '\n') Name[i] = '\0';
, поскольку вы будете использовать одинарные кавычки, а не двойные кавычки. Здесь ссылка о одиночных или двойных кавычках, если вы хотите узнать больше
for(int i = 0; i < strlen(Name); i++ )
будет много раз называть strlen(Name)
(изменения цикла Name[]
), поэтому с длиной N
это решение O(N*N)
. Для обеспечения решения O (N) требуется только 1 вызов strlen(Name)
, если он есть. Непонятно, почему int i
используется вместо size_t i
. Рассмотрим for(size_t i = 0; i < Name[i]; i++ )
– chux
6 December 2017 в 23:03
Для одиночного '\n' trmming,
void remove_new_line(char* string)
{
size_t length;
if( (length =strlen(string) ) >0)
{
if(string[length-1] == '\n')
string[length-1] ='\0';
}
}
для множественной обрезки '\n',
void remove_new_line(char* string)
{
size_t length = strlen(string);
while(length>0)
{
if(string[length-1] == '\n')
{
--length;
string[length] ='\0';
}
else
break;
}
}
size_t ln = strlen(name) - 1;
if (*name && name[ln] == '\n')
name[ln] = '\0';
fgets(buf, size, ....)
- & gt; strlen(buf) == 0
. 1) fgets()
читается как первый char
a '\0'
. 2) size == 1
3) fgets()
возвращает NULL
, тогда содержимое buf
может быть любым. (Код OP действительно проверяет значение NULL, хотя) Предложите: size_t ln = strlen(name); if (ln > 0 && name[ln-1] == '\n') name[--ln] = '\0';
– chux
2 July 2014 в 15:00
ln
будет -1, за исключением того факта, что size_t
не имеет знака, поэтому записывается в случайную память. Я думаю, вы хотите использовать ssize_t
и проверить ln
is & gt; 0.
– abligh
16 March 2015 в 23:38
strlen
) может быть реализован гораздо эффективнее, чем простой поиск char-by-char. По этой причине я считаю это решение лучше, чем на основе strchr
или strcspn
.
– AnT
29 March 2016 в 18:28
Тим Čas один лайнер поражает строки, полученные вызовом fgets, потому что вы знаете, что они содержат одну новую строку в конце.
Если вы находитесь в другом контексте и хотите обрабатывать строки, которые могут содержать более одной новой строки, вы можете искать strrspn. Это не POSIX, то есть вы не найдете его во всех Unices. Я написал один для своих собственных нужд.
/* Returns the length of the segment leading to the last
characters of s in accept. */
size_t strrspn (const char *s, const char *accept)
{
const char *ch;
size_t len = strlen(s);
more:
if (len > 0) {
for (ch = accept ; *ch != 0 ; ch++) {
if (s[len - 1] == *ch) {
len--;
goto more;
}
}
}
return len;
}
Для тех, кто ищет эквивалент Perl chomp в C, я думаю, что это он (chomp только удаляет конечную новую строку).
line[strrspn(string, "\r\n")] = 0;
Функция strrcspn:
/* Returns the length of the segment leading to the last
character of reject in s. */
size_t strrcspn (const char *s, const char *reject)
{
const char *ch;
size_t len = strlen(s);
size_t origlen = len;
while (len > 0) {
for (ch = reject ; *ch != 0 ; ch++) {
if (s[len - 1] == *ch) {
return len;
}
}
len--;
}
return origlen;
}
'\n'
(или строка ""
).
– chux
18 November 2015 в 18:59
strrcspn
, если нет \n
.
– Philippe A.
18 November 2015 в 19:14
goto
s в вашем коде: бесполезный goto
, который можно заменить выражением return
и назад goto
, который считается злым. Использование strchr
помогает реализовать strrspn
и strrcspn
более простым способом: size_t strrspn(const char *s, const char *accept) { size_t len = strlen(s); while (len > 0 && strchr(accept, s[len - 1])) { len--; } return len; }
и size_t strrcspn(const char *s, const char *reject) { size_t len = strlen(s); while (len > 0 && !strchr(reject, s[len - 1])) { len--; } return len; }
– chqrlie
30 November 2016 в 00:04
Если использование getline
является опцией - не пренебрегая его проблемами безопасности, и если вы хотите привязать указатели, вы можете избежать строковых функций, так как getline
возвращает количество символов. Что-то вроде ниже
#include<stdio.h>
#include<stdlib.h>
int main(){
char *fname,*lname;
size_t size=32,nchar; // Max size of strings and number of characters read
fname=malloc(size*sizeof *fname);
lname=malloc(size*sizeof *lname);
if(NULL == fname || NULL == lname){
printf("Error in memory allocation.");
exit(1);
}
printf("Enter first name ");
nchar=getline(&fname,&size,stdin);
if(nchar == -1){ // getline return -1 on failure to read a line.
printf("Line couldn't be read..");
// This if block could be repeated for next getline too
exit(1);
}
printf("Number of characters read :%zu\n",nchar);
fname[nchar-1]='\0';
printf("Enter last name ");
nchar=getline(&lname,&size,stdin);
printf("Number of characters read :%zu\n",nchar);
lname[nchar-1]='\0';
printf("Name entered %s %s\n",fname,lname);
return 0;
}
Примечание: [проблемы безопасности] с getline
не следует пренебрегать.
Возможно, самое простое решение использует одну из моих любимых малоизвестных функций, strcspn()
:
buffer[strcspn(buffer, "\n")] = 0;
Если вы хотите, чтобы она также обрабатывала '\r'
(скажем, , если поток двоичный):
buffer[strcspn(buffer, "\r\n")] = 0; // works for LF, CR, CRLF, LFCR, ...
Функция подсчитывает количество символов до тех пор, пока оно не достигнет '\r'
или '\n'
(другими словами, он найдет первый '\r'
или '\n'
). Если он ничего не ударил, он останавливается на '\0'
(возвращает длину строки).
Обратите внимание, что это отлично работает, даже если нет новой строки, поскольку strcspn
останавливается на '\0'
. В этом случае вся строка просто заменяет '\0'
на '\0'
.
buffer
, чем начинается i> с '\0'
, что вызывает горе для подхода buffer[strlen(buffer) - 1] = '\0';
.
– chux
11 February 2015 в 20:39
strcspn()
. Одна из наиболее полезных функций в библиотеке, ИМО. Я решил написать и опубликовать кучу обычных C-хаков, подобных этому сегодня; реализация strtok_r
с использованием strcspn
и strspn
была одной из первых: codepad.org/2lBkZk0w ( Предупреждение: i> Я не могу гарантировать, что это без ошибок , он был написан спешно и, вероятно, есть несколько). Я не знаю, где я еще опубликую их, но я намерен сделать это в духе знаменитых «бит-скрипучих хаков».
– Tim Čas
11 February 2015 в 20:44
fgets()
. Этот strcspn()
, по-видимому, является only i> правильным однострочным. strlen
быстрее - хотя и не так просто.
– chux
11 February 2015 в 21:04
fgets()
ввода i>. Который всегда является первой новой линией.
– Tim Čas
9 April 2017 в 13:44
strtok()
будет потокобезопасной (она будет использовать локальное хранилище потоков для состояния «inter-call»). Тем не менее, как правило, лучше использовать нестандартный (но достаточно общий) вариантstrtok_r()
. – Michael Burr 22 April 2010 в 22:36strtok
подходу (и он работает с пустыми вводами). На самом деле хорошим способом реализацииstrtok
является использованиеstrcspn
иstrspn
. – Tim Čas 11 February 2015 в 20:09*strchrnul(Name, '\n') = '\0';
. – twobit 17 August 2017 в 08:55