Son satırsonu karakterini fgets () girişinden kaldırma


236

Ben kullanıcıdan bazı veri almak ve gcc içinde başka bir işleve göndermek çalışıyorum. Kod böyle bir şey.

printf("Enter your Name: ");
if (!(fgets(Name, sizeof Name, stdin) != NULL)) {
    fprintf(stderr, "Error reading Name.\n");
    exit(1);
}

Ancak \nsonunda bir satırsonu karakteri olduğunu düşünüyorum . Yani eğer Johngirersem gönderir John\n. Bunu nasıl kaldırabilirim \nve uygun bir dize gönderirim.


21
if (!fgets(Name, sizeof Name, stdin))(en azından iki olumsuzlama kullanmayın,! ve! =)

4
@Roger Pate "iki olumsuzlama kullanma" -> hmmm, eğer derin kazarsak "yapma" ve "olumsuzluk" her ikisi de negatiftir . ;-). Belki "Kullanın if (fgets(Name, sizeof Name, stdin)) {.
chux - Monica

3
@chux, eminim demek istedinizif (fgets(Name, sizeof Name, stdin) == NULL ) {
R Sahu

@RSahu True : sinir bozucu !:
chux - Monica'yı eski durumuna getir

Yanıtlar:


155

Biraz çirkin yol:

char *pos;
if ((pos=strchr(Name, '\n')) != NULL)
    *pos = '\0';
else
    /* input too long for buffer, flag error */

Biraz garip bir yol:

strtok(Name, "\n");

strtokKullanıcı boş bir dize girerse (yani yalnızca Enter tuşuna basarsa) işlevin beklendiği gibi çalışmadığını unutmayın . Bu bırakır \nkarakter sağlam.

Elbette başkaları da var.


7
İş parçacığı farkında olan herhangi bir C çalışma zamanı kitaplığı (diğer bir deyişle, çok iş parçacıklı bir platformu hedefleyen herhangi biri), strtok()iş parçacığı için güvenli olacaktır ('çağrılar arası' durumu için yerel iş parçacığı depolama alanını kullanır). Bununla birlikte, standart olmayan (ancak yeterince yaygın) strtok_r()varyantı kullanmak genellikle daha iyidir .
Michael Burr

2
strtokYaklaşımınıza benzer, tamamen iş parçacığı açısından güvenli ve yeniden giriş varyantı için cevabımı görün (ve boş girdilerle çalışır). Aslında, uygulamak için iyi bir yol strtokkullanmaktır strcspnve strspn.
Tim Čas

2
Aşırı uzun çizgiler riski olan bir ortamdaysanız, diğer durumu ele almanız önemlidir. Sessizce kesilen giriş çok zararlı hatalara neden olabilir.
Malcolm McLean

2
Tek gömleklerden hoşlanıyorsanız ve glibc kullanıyorsanız, deneyin *strchrnul(Name, '\n') = '\0';.
twobit

Daha strchr(Name, '\n') == NULLsonra "arabellek için çok uzun girdi, bayrak hatası" dışında, diğer olasılıklar da var: Son metin stdinbir '\n'veya bitmiş gömülü boş karakterle sonlanmadı .
chux - Monica

440

Belki de en basit çözüm, en sevdiğim az bilinen işlevlerimden birini kullanıyor strcspn():

buffer[strcspn(buffer, "\n")] = 0;

Ayrıca işlemesini istiyorsanız '\r'(diyelim ki akış ikiliyse):

buffer[strcspn(buffer, "\r\n")] = 0; // works for LF, CR, CRLF, LFCR, ...

İşlev, a '\r'veya a'ya kadar karakter sayısını sayar '\n'(başka bir deyişle, ilkini '\r'veya öğesini bulur '\n'). Hiçbir şeye çarpmazsa, '\0'(dizenin uzunluğunu döndürerek) konumunda durur .

Yeni satır olmasa bile bunun iyi çalıştığını unutmayın, çünkü strcspna '\0'. Bu durumda, tüm hat basitçe değiştiriyor '\0'ile '\0'.


30
Bu bile nadir kolları bufferdaha başlar ile '\0', nedenleri için keder o şey buffer[strlen(buffer) - 1] = '\0';yaklaşımı.
chux - Monica adlı kişiyi geri yükle

5
@chux: Evet, keşke daha fazla kişi hakkında bilgi sahibi olsaydı strcspn(). Kütüphanedeki daha kullanışlı işlevlerden biri olan IMO. Bugün bunun gibi bir sürü ortak C korsanlığı yazmaya ve yayınlamaya karar verdim; Bir strtok_rkullanarak uygulama strcspnve strspn: ilk biriydi codepad.org/2lBkZk0w ( Uyarı: Bence hata olmadan olduğunu garanti olamaz; o aceleyle yazılmış ve muhtemelen bir kaç sahiptir edildi). Yine de onları nerede yayınlayacağımı bilmiyorum, ama bunu ünlü "biraz dönen hackler" ruhuyla yapmak niyetindeyim.
Tim Čas

4
Sağlam bir şekilde düzeltmefgets() yollarına baktım . Bu tek doğru tek astar strcspn()gibi görünüyor . daha hızlı - basit değil. strlen
chux - Monica adlı kişiyi geri yükle

6
@sidbushes: Hem başlıkta hem de içerikte soru, girişten gelenfgets() yeni satır hakkında soru sorar . Bu da her zaman ilk satırsonu.
Tim Čas

9
@sidbushes: Nereden geldiğinizi anlıyorum, ancak belirli terimler için Google arama sonuçlarından sorumlu tutulamaz. Benimle değil Google ile konuş.
Tim Čas

83
size_t ln = strlen(name) - 1;
if (*name && name[ln] == '\n') 
    name[ln] = '\0';

8
Dize boşsa büyük olasılıkla istisna atar, değil mi? Endeks aralık dışında.
Edward Olamisan

1
@EdwardOlamisan, dize asla boş olmayacak.
James Morris

5
@James Morris Olağandışı durumlarda fgets(buf, size, ....)-> strlen(buf) == 0. 1) fgets()ilk olarak okur chara '\0'. 2) size == 13) fgets()İade NULLo zaman bufiçerik herhangi bir şey olabilir. (OP'nin kodu yine de NULL için test ediyor) Öneri:size_t ln = strlen(name); if (ln > 0 && name[ln-1] == '\n') name[--ln] = '\0';
chux - Monica'yı eski durumuna döndür

2
Dize boşsa ne olur? ln-1 olurdu, gerçek için kaydet size_timzasız, böylece rastgele belleğe yazma. Bence kullanmak istiyorsun ssize_tve kontrol etmek ln> 0.
15'te

2
@ legends2k: Derleme zamanı değeri için arama (özellikle de olduğu gibi sıfır değeri strlen), düz karakterlerle yapılan bir aramaya göre çok daha verimli bir şekilde uygulanabilir. Bu nedenle bu çözümü bir strchrveya strcspntemelli çözümlerden daha iyi düşünürdüm .
Mart'ta AnT

17

Aşağıda, '\n'tarafından kaydedilen bir dizeden bir potansiyeli kaldırmak için hızlı bir yaklaşım verilmiştir fgets(). 2 test ile
kullanır 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';
  }

Şimdi kullanın bufferve lengerektiği gibi.

Bu yöntem, lensonraki kod için bir değerin yan faydasına sahiptir . Kolayca daha hızlı olabilir strchr(Name, '\n'). Ref YMMV, ancak her iki yöntem de çalışır.


buffer, Orijinal fgets()olarak içermez "\n": bazı koşullar altında
A) hattı için çok uzun olduğu bufferbu yüzden sadece char, önceki '\n'kaydedilir buffer. Okunmamış karakterler akışta kalır.
B) Dosyadaki son satır a ile bitmedi '\n'.

Giriş bir '\0'yere boş karakterler yerleştirmişse , tarafından bildirilen uzunluk konumu strlen()içermez '\n'.


Diğer bazı cevapların sorunları:

  1. strtok(buffer, "\n");kaldırma başarısız '\n'olduğunda bufferise "\n". Bu cevaptan - bu cevaptan sonra değiştirilen bu sınırlamayı uyarmak için.

  2. İlk ne zaman şu nadiren de olsa başarısız chartarafından okunan fgets()olduğunu '\0'. Bu, giriş gömülü ile başladığında olur '\0'. Sonra buffer[len -1]olur buffer[SIZE_MAX]meşru aralığının dışında kesinlikle belleğe erişim buffer. Bir bilgisayar korsanı UTF16 metin dosyalarını aptalca okurken deneyebilir veya bulabilir. Bu cevap yazıldığında bir cevap durumuydu. Daha sonra bir OP olmayan kişi bu cevabın kontrolü gibi bir kod içerecek şekilde düzenledi "".

    size_t len = strlen(buffer);
    if (buffer[len - 1] == '\n') {  // FAILS when len == 0
      buffer[len -1] = '\0';
    }
  3. sprintf(buffer,"%s",buffer);undefined davranışı: Ref . Ayrıca, önde gelen, ayrılan veya sondaki boşlukları kaydetmez. Şimdi silindi .

  4. [Daha sonraki iyi yanıt nedeniyle düzenleme ] Yaklaşımla buffer[strcspn(buffer, "\n")] = 0;karşılaştırıldığında performanstan başka 1 astarla ilgili bir sorun yoktur strlen(). Kırpma işleminde performans genellikle kod I / O yapıyor - CPU zamanının kara deliği - bir sorun değildir. Aşağıdaki kod dizenin uzunluğuna ihtiyaç duyuyorsa veya yüksek performans bilincindeyse, bu strlen()yaklaşımı kullanın . Başka strcspn()iyi bir alternatiftir.


Yararlı cevap için teşekkürler. strlen(buffer)Arabellek boyutu kullanılarak dinamik olarak ayrıldığında kullanabilir miyiz malloc?
rrz0

@ Rrz0 buffer = malloc(allocation_size); length = strlen(buffer);kötü - ile gösterilen bellekteki veriler bufferbilinmiyor. buffer = malloc(allocation_size_4_or_more); strcpy(buffer, "abc"); length = strlen(buffer);tamam
chux - Monica

Bunun için teşekkürler!! CS dersi alıyorum ve bu ödevlerden biri için büyük ölçüde yardımcı oldu. cevabını kaynak koduna yatırdım.
Nathaniel Hoyt

8

Her satırda '\ n' varsa doğrudan '\ n' öğesini fgets çıktısından kaldırma

line[strlen(line) - 1] = '\0';

Aksi takdirde:

void remove_newline_ch(char *line)
{
    int new_line = strlen(line) -1;
    if (line[new_line] == '\n')
        line[new_line] = '\0';
}

1
Bunun yerine kullanmanın daha güvenli olacağını unutmayın . strnlenstrlen
Mike Mertsock

3
"Strlen (), strcmp () ve strdup () yöntemlerinin güvenli olduğunu unutmayın. 'N' alternatifleri size ek işlevsellik kazandırır."
Étienne

4
@esker hayır, olmazdı. a eklemek ngüvenliği sihirli bir şekilde artırmaz, bu durumda kodu daha tehlikeli hale getirir. Benzer şekilde strncpy, çok güvenli olmayan bir işlev. Bağlantı kurduğunuz gönderi kötü bir tavsiye.
MM

3
Bu, boş bir dize ( "") için sefil bir şekilde başarısız olur . Ayrıca strlen()döner size_tdeğil int.
alk

4
bu boş bir dize için güvenli değildir, -1 dizinine yazacaktır. Bunu kullanma.
Jean-François Fabre

3

Tek '\ n' kırpma için,

void remove_new_line(char* string)
{
    size_t length = strlen(string);
    if((length > 0) && (string[length-1] == '\n'))
    {
        string[length-1] ='\0';
    }
}

çoklu '\ n' kırpma için,

void remove_multi_new_line(char* string)
{
  size_t length = strlen(string);
  while((length>0) && (string[length-1] == '\n'))
  {
      --length;
      string[length] ='\0';
  }
}

1
ifBir koşulu kullanarak yazabildiğinizde neden yuva yapıyorsunuz &&? Bu whiledöngü garip bir yapıya sahip; basitçe olabilir while (length > 0 && string[length-1] == '\n') { --length; string[length] = '\0'; }.
melpomene

@melpomene öneri için teşekkürler. Kodu güncelleyin.
BEPP

1
Ben ilk fonksiyon daha doğal olarak tanımlandığını öneririm: size_t length = strlen(string); if (length > 0 && string[length-1] == '\n') { string[length-1] = '\0'; }. Bu aynı zamanda ikinci tanımı daha iyi yansıtır (sadece ifyerine kullanarak while).
Melpomene

@elpomene teşekkürler. Mantıklı. Kodu güncelledim.
BEPP

1

Newbie yolum ;-) Lütfen bunun doğru olup olmadığını bana bildirin. Tüm davalarım için çalışıyor gibi görünüyor:

#define IPT_SIZE 5

int findNULL(char* arr)
{
    for (int i = 0; i < strlen(arr); i++)
    {
        if (*(arr+i) == '\n')
        {
            return i;
        }
    }
    return 0;
}

int main()
{
    char *input = malloc(IPT_SIZE + 1 * sizeof(char)), buff;
    int counter = 0;

    //prompt user for the input:
    printf("input string no longer than %i characters: ", IPT_SIZE);
    do
    {
        fgets(input, 1000, stdin);
        *(input + findNULL(input)) = '\0';
        if (strlen(input) > IPT_SIZE)
        {
            printf("error! the given string is too large. try again...\n");
            counter++;
        }
        //if the counter exceeds 3, exit the program (custom function):
        errorMsgExit(counter, 3); 
    }
    while (strlen(input) > IPT_SIZE);

//rest of the program follows

free(input)
return 0;
}

1

Yeni satır karakterini belki de en belirgin şekilde kaldırma adımları:

  1. Üstbilgiyi NAMEkullanarak içerideki dizenin uzunluğunu belirleyin . Not sonlanan sayılmaz .strlen()string.hstrlen()\0
size_t sl = strlen(NAME);

  1. Dizenin bir \0karakterle (boş karakter) başlayıp başlamayacağına bakın . Bu durumda slolurdu 0çünkü strlen()ben saymak gelmiyor.Fark yukarıda söylediği gibi \0ve bunun ilk geçtiği durur:
if(sl == 0)
{
   // Skip the newline replacement process.
}

  1. Doğru dizenin son karakterinin yeni satır karakteri olup olmadığını kontrol edin '\n'. Bu durumda, \na ile değiştirin \0. Dizin sayımlarının başladığını unutmayın, 0bu nedenle şunları yapmamız gerekir NAME[sl - 1]:
if(NAME[sl - 1] == '\n')
{
   NAME[sl - 1] = '\0';
}

fgets()Dize isteğinde yalnızca Enter tuşuna bastıysanız (dize içeriği yalnızca bir yeni satır karakterinden oluşuyordu), NAMEdizenin bundan sonra boş bir dize olacağını unutmayın.


  1. ifMantık operatörünü kullanarak adım 2 ve 3'ü tek bir aşamada birleştirebiliriz &&:
if(sl > 0 && NAME[sl - 1] == '\n')
{
   NAME[sl - 1] = '\0';
}

  1. Bitmiş kod:
size_t sl = strlen(NAME);
if(sl > 0 && NAME[sl - 1] == '\n')
{
   NAME[sl - 1] = '\0';
}

fgetsÇıktı dizelerini genel olarak her seferinde yeniden yazmadan işleyerek bu tekniği kullanmaktan hoşlanıyorsanız , işte burada fgets_newline_kill:

void fgets_newline_kill(char a[])
{
    size_t sl = strlen(a);

    if(sl > 0 && a[sl - 1] == '\n')
    {
       a[sl - 1] = '\0';
    }
}

Sağladığınız örnekte şöyle olur:

printf("Enter your Name: ");

if (fgets(Name, sizeof Name, stdin) == NULL) {
    fprintf(stderr, "Error reading Name.\n");
    exit(1);
}
else {
    fgets_newline_kill(NAME);
}

Giriş dizesi gömülü ise, bu yöntemin çalışmadığını unutmayın \0. Durum böyle olsaydı strlen(), sadece ilk karaktere kadar olan karakterlerin miktarını döndürürdü \0. Ancak bu oldukça yaygın bir yaklaşım değildir, çünkü çoğu dize okuma işlevi genellikle ilk başta durur\0 ve dizeyi bu boş karaktere kadar alır.

Sorunun yanı sıra tek başına. Kodunuzu daha anlaşılır hale getiren çift olumsuzlamalardan kaçının if (!(fgets(Name, sizeof Name, stdin) != NULL) {}. Sadece yapabilirsin if (fgets(Name, sizeof Name, stdin) == NULL) {}.


Bunu neden yapmak isteyeceğinizden emin değilim. Yeni satırları kaldırmanın amacı, dizeleri boş sonlandırmak değildir; yeni satırları kaldırmaktır. Bir Değiştirme \nbir ile \0en sonunda bir dize yeni satırını "kaldırma" bir yoldur. Ancak \nbir dize içindeki karakterlerin değiştirilmesi , dizeyi temelden değiştirir. Kasıtlı çoklu yeni satır karakterleri olan dizelere sahip olmak nadir değildir ve bu, bu dizelerin uçlarını etkili bir şekilde keser. Bu gibi yeni satır satırlarını kaldırmak için dizi içeriğinin üzerine yazmak için sola kaydırılması gerekir \n.
eski nihilo

@exnihilo Birini kullanarak birden fazla satır içeren bir dize nasıl girebilir fgets()?
Roberts Monica CELLIO destekler

Pek çok çağrıyla elde edilen dizeleri birleştirebilirsiniz fgets(). Ancak itirazınızı anlamıyorum: birden fazla satırsonu işleyen tek teklif kodu sizsiniz.
eski nihilo

@exnihilo Haklısın, stratejiyi gözden geçireceğim. Sadece istenen sonucu elde etmek için çok sert ama olası bir yol eklemek istedim.
Roberts Monica CELLIO destekler

@exnihilo Cevabımı tamamen düzenledi ve strlenvb. kullanarak ana yaklaşımı takip etti . Kopya olmaması için gerekçe: 1. Kodun adım adım açıklaması. 2. Fonksiyon ve bağlama dayalı çözüm olarak sağlanır. 3. Çift olumsuzlama ifadelerinden kaçınmak için ipucu.
RobertS, Monica Cellio

0

Bir astar olarak Tim, fgets çağrısı ile elde edilen dizeler için şaşırtıcı, çünkü sonunda tek bir satırsonu içerdiğini biliyorsunuz.

Farklı bir bağlamdaysanız ve birden fazla yeni satır içerebilecek dizeleri işlemek istiyorsanız strrspn arıyor olabilirsiniz. POSIX değildir, yani tüm Unices'te bulamazsınız. Kendi ihtiyaçlarım için bir tane yazdım.

/* 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;
}

C bir Perl chomp eşdeğeri arayanlar için, bu olduğunu düşünüyorum (chomp sadece sondaki satırsonu kaldırır).

line[strrspn(string, "\r\n")] = 0;

Strrcspn işlevi:

/* 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;
}

1
"çünkü sonunda tek bir satırsonu içerdiğini biliyorsunuz." -> Hayır '\n'(veya dize varsa "") bile çalışır .
chux - Monica'yı eski durumuna getir

İlk yorum chux'una yanıt olarak, cevabım bunu koruyor. Ben yokken strrcspniçin resetlen atmak zorunda kaldı \n.
Philippe A.

Neden kullanmak goto end;yerine return len;?
chqrlie

@chqrlie Girdiğim bu yetersiz 2 seviyeli döngüden kurtulmam gerekiyordu. Zarar verildi. Neden gitmiyoruz?
Philippe A.

gotoKodunuzda iki tür s vardır: bir gotoifade ile değiştirilebilecek yararsız returnve gotokötülük olarak kabul edilen bir geriye doğru . Kullanılması strchruygulamama yardımcı oluyor strrspnve strrcspn: daha basit bir şekilde 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; }vesize_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

0

Kullanmak getlinebir seçenekse - Güvenlik sorunlarını ihmal etmemek ve işaretçileri desteklemek istiyorsanız - getlinekarakter sayısını döndürdüğü için dize işlevlerinden kaçınabilirsiniz . Aşağıdaki gibi bir şey

#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;
}

Not : [ güvenlik sorunları ] ile birlikte getlineihmal edilmemelidir.


-1

Aşağıdaki işlev, Github üzerinde sürdürdüğüm dize işleme kütüphanesinin bir parçasıdır. Tam olarak istediğinizi bir dizeden kaldırır ve istenmeyen karakterleri kaldırır

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;
}

Örnek bir kullanım

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

Mevcut diğer işlevleri kontrol etmek, hatta projeye katkıda bulunmak isteyebilirsiniz :) https://github.com/fnoyanisi/zString


Sen kaldırmalısınız *içinde *src++;ve yapmak bad, tokenve d const char *. Ayrıca neden kullanmıyorsunuz?strchr yerinezChrSearch ? *srcolamaz '\0'senin içinde zStrrmvişlevi.
chqrlie

Teşekkürler @chqrlie! önerilerinizi yansıtmak için kod güncellendi ..... zstring herhangi bir standart kütüphane fonksiyonlarını kullanmadan bir dize manipülasyon kütüphanesi oluşturmak amacıyla eğlenceli bir proje olarak başladı, bu yüzden ben kullanmadımstrchr
fnisi

1
" Herhangi bir standart kütüphane işlevini kullanmadan dize düzenleme kütüphanesi " yazmak iyi bir alıştırmadır, ama neden diğer insanlara bunu kullanmasını söyleyin? Herhangi bir şey varsa, herhangi bir standart kütüphaneden daha yavaş ve daha az test edilecektir.
melpomene

Bu, sorunun sorduğundan farklı bir iş çıkarıyor. Muhtemelen tek satırsonundan kurtulmak için kullanılabilir, ancak aşırıya kaçmak gibi geliyor.
Jonathan Leffler

-1
 for(int i = 0; i < strlen(Name); i++ )
{
    if(Name[i] == '\n') Name[i] = '\0';
}

Denemelisin. Bu kod temelde '\ n' harfini bulana kadar dize üzerinden geçer. Bulunduğunda '\ n' yerine '\ 0' boş karakter sonlandırıcısı kullanılır

Bu satırdaki karakterleri değil karakterleri karşılaştırdığınızı, o zaman strcmp () kullanmanıza gerek olmadığını unutmayın:

if(Name[i] == '\n') Name[i] = '\0';

çünkü çift tırnak değil, tek tırnak kullanacaksınız. Daha fazla bilgi edinmek istiyorsanız single vs double quotes hakkında bir link


2
kodunuzun biçimini açıklar ve düzenlerseniz daha iyi olur.
Anh Pham

Genellikle, bazı anonim kod satırlarını göndermek yerine bir çözümü açıklamak daha iyidir. İyi bir yanıtı nasıl yazarım ve ayrıca tamamen kod tabanlı cevapları açıklamayı okuyabilirsiniz .
Massimiliano Kraus

1
Buraya ilk katkım olduğu için üzgünüm. Düzelteceğim. Geri bildiriminiz için teşekkürler
Matheus Martins Jerônimo

3
Verimsiz: birçok kez for(int i = 0; i < strlen(Name); i++ )çağıracaktır strlen(Name)(döngü değişiklikleri Name[]) N, bu yüzden bir uzunlukla , bu bir O(N*N)çözümdür. strlen(Name)Bir O (N) `çözeltisi sağlamak için , varsa, sadece 1 çağrı gerekir . int iBunun yerine neden kullanıldığı net değil size_t i. Düşünfor(size_t i = 0; i < Name[i]; i++ )
chux - Monica

@chux Daha fazla beğenfor (size_t i = 0; Name[i]; i++) { if (Name[i] == '\n') { Name[i] = '\0'; break; } }
melpomene

-1

Bunu dene:

        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;
        }

1
len = strlen(str)taşabilir: strlendöner size_t, değil int. Tuhaf if (len>0) if (...)şartlar nedir? Bilmiyor musun &&? Birden fazla sondaki CR / LF örneğini kaldıracaksanız, neden kendinizi 5 ile sınırlandırıyorsunuz? Neden hepsini kaldırmıyorsunuz? Neden inther zaman geri döndüğünde işlevin bir dönüş türü vardır 0? Neden sadece geri dönmeyelim void?
melpomene
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.