strcspn - strchr
Eliminar el carácter de nueva línea al final de la entrada de fgets() (15)
A continuación se muestra un enfoque rápido para eliminar un potencial ''/n''
de una cadena guardada por fgets()
.
Utiliza strlen()
, con 2 pruebas.
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'';
}
Ahora usa buffer
y len
según sea necesario.
Este método tiene el beneficio secundario de un valor len
para el código posterior. Puede ser más rápido que strchr(Name, ''/n'')
. Ref YMMV, pero ambos métodos funcionan.
buffer
, desde el original fgets()
no contendrá en "/n"
bajo algunas circunstancias:
A) La línea era demasiado larga para el buffer
por lo que solo el char
precede a ''/n''
se guarda en el buffer
. Los caracteres no leídos permanecen en la transmisión.
B) La última línea del archivo no finalizó con ''/n''
.
Si la entrada ha incrustado caracteres nulos ''/0''
en alguna parte, la longitud informada por strlen()
no incluirá la ubicación ''/n''
.
Algunos otros problemas de respuestas:
strtok(buffer, "/n");
no puede eliminar el''/n''
cuando elbuffer
es"/n"
. De esta answer - enmendada después de esta respuesta para advertir sobre esta limitación.Lo siguiente falla en raras ocasiones cuando la primera lectura de
char
por parte defgets()
es''/0''
. Esto sucede cuando la entrada comienza con un''/0''
incrustado. Luego elbuffer[len -1]
convierte enbuffer[SIZE_MAX]
accediendo a la memoria ciertamente fuera del rango legítimo debuffer
. Algo que un hacker puede intentar o encontrar al leer tontamente los archivos de texto UTF16. Este fue el estado de una answer cuando se escribió esta respuesta. Más tarde, un OP no editado lo incluyó para incluir código como la comprobación de esta respuesta para""
.size_t len = strlen(buffer); if (buffer[len - 1] == ''/n'') { // FAILS when len == 0 buffer[len -1] = ''/0''; }
sprintf(buffer,"%s",buffer);
es un comportamiento indefinido: Ref . Además, no guarda espacios en blanco iniciales, separadores o finales. Ahora deleted .[Editar debido a una buena answer posterior] No hay problemas con el
buffer[strcspn(buffer, "/n")] = 0;
1 linerbuffer[strcspn(buffer, "/n")] = 0;
que no sea el rendimiento en comparación con el enfoquestrlen()
. El rendimiento en el recorte generalmente no es un problema dado que el código está haciendo E / S: un agujero negro de tiempo de CPU. Si el siguiente código necesita la longitud de la cadena o es altamente consciente del rendimiento, use este enfoquestrlen()
. De lo contrario,strcspn()
es una buena alternativa.
Estoy tratando de obtener algunos datos del usuario y enviarlos a otra función en gcc. El código es algo como esto.
printf("Enter your Name: ");
if (!(fgets(Name, sizeof Name, stdin) != NULL)) {
fprintf(stderr, "Error reading Name./n");
exit(1);
}
Sin embargo, me parece que tiene un carácter newline /n
al final. Entonces, si ingreso a John
, termina enviando a John/n
. ¿Cómo elimino eso /n
y envío una cadena adecuada?
Directo para eliminar el ''/ n'' de la salida de los datos de las fgets si cada línea tiene ''/ n''
line[strlen(line) - 1] = ''/0'';
De otra manera:
void remove_newline_ch(char *line)
{
int new_line = strlen(line) -1;
if (line[new_line] == ''/n'')
line[new_line] = ''/0'';
}
Es tan simple como esto:
loco[strlen(loco)-1] = ''/0'';
La manera un poco fea:
char *pos;
if ((pos=strchr(Name, ''/n'')) != NULL)
*pos = ''/0'';
else
/* input too long for buffer, flag error */
La manera un poco extraña:
strtok(Name, "/n");
Tenga en cuenta que la función strtok
no funciona como se espera si el usuario ingresa una cadena vacía (es decir, solo presiona Enter). Deja intacto el carácter /n
.
Hay otros también, por supuesto.
La siguiente función es una parte de la biblioteca de procesamiento de cadenas que estoy manteniendo en Github. Elimina y caracteres no deseados de una cadena, exactamente lo que quieres
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;
}
Un ejemplo de uso podría ser
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
Es posible que desee comprobar otras funciones disponibles, o incluso contribuir al proyecto :) https://github.com/fnoyanisi/zString
Las formas más simples son:
while(fgets(Name, 512, fp) != NULL)
{
if (Name[0] == ''/n'' || Name[0] == ''/r'')
continue;
strtok(Name, "/n");
...
}
Para solo ''/ 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'';
}
}
para múltiples recortes ''/ 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;
}
}
Prueba este:
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;
}
Quizás la solución más simple utiliza una de mis funciones favoritas poco conocidas, strcspn()
:
buffer[strcspn(buffer, "/n")] = 0;
Si desea que también maneje ''/r''
(por ejemplo, si la transmisión es binaria):
buffer[strcspn(buffer, "/r/n")] = 0; // works for LF, CR, CRLF, LFCR, ...
La función cuenta el número de caracteres hasta que golpea una ''/r''
o una ''/n''
(en otras palabras, encuentra la primera ''/r''
o ''/n''
). Si no golpea nada, se detiene en ''/0''
(devolviendo la longitud de la cadena).
Tenga en cuenta que esto funciona bien incluso si no hay línea nueva, porque strcspn
detiene en ''/0''
. En ese caso, toda la línea simplemente está reemplazando ''/0''
con ''/0''
.
Si usa getline
es una opción, sin descuidar sus problemas de seguridad y si desea apuntalar punteros, puede evitar las funciones de cadena ya que getline
devuelve el número de caracteres. Algo como abajo
#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;
}
Nota : Los [ problemas de seguridad ] con getline
no deben descuidarse.
Tim Čas one liner es increíble para las cadenas obtenidas por un llamado a los fgets, porque sabes que contienen una nueva línea al final.
Si se encuentra en un contexto diferente y desea manejar cadenas que pueden contener más de una nueva línea, es posible que esté buscando strrspn. No es POSIX, lo que significa que no lo encontrará en todas las Unices. Escribí uno para mis propias necesidades.
/* 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;
}
Para aquellos que buscan un equivalente de Perl chomp en C, creo que esto es todo (chomp solo elimina la nueva línea final).
line[strrspn(string, "/r/n")] = 0;
La función 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;
}
Yo personalmente uso el siguiente método al manejar cadenas de fgets
:
if(str[strlen(str) - 1] == ''/n'')
{
str[strlen(str) - 1] = ''/0'';
}
También podría usar las funciones que otros han mencionado en sus respuestas anteriores, pero me gusta la simplicidad de este método.
for(int i = 0; i < strlen(Name); i++ )
{
if(Name[i] == ''/n'') Name[i] = ''/0'';
}
Usted debe darle una oportunidad. Este código básicamente recorre la cadena hasta que encuentra el ''/ n''. Cuando se encuentre, ''/ n'' será reemplazado por el terminador de caracteres nulo ''/ 0''
Tenga en cuenta que está comparando caracteres y no cadenas en esta línea, entonces no es necesario usar strcmp ():
if(Name[i] == ''/n'') Name[i] = ''/0'';
ya que usará comillas simples y no comillas dobles. Here''s un enlace sobre comillas simples versus dobles si desea saber más
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'';
size_t ln = strlen(name) - 1;
if (*name && name[ln] == ''/n'')
name[ln] = ''/0'';