Fgets () ইনপুট থেকে ট্রেলিং করা নতুন লাইনের চরিত্রটি সরানো


235

আমি ব্যবহারকারীর কাছ থেকে কিছু ডেটা নেওয়ার চেষ্টা করছি এবং এটি সিসিতে অন্য কোনও ফাংশনে প্রেরণ করব। কোডটি এরকম কিছু।

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

যাইহোক, আমি দেখতে পাচ্ছি যে এটির \nশেষে একটি নতুন লাইনের চরিত্র রয়েছে। সুতরাং আমি প্রবেশ করে Johnএটি পাঠানো শেষ John\n। আমি কীভাবে এটি সরিয়ে \nএকটি সঠিক স্ট্রিং প্রেরণ করব।


21
if (!fgets(Name, sizeof Name, stdin))(খুব কম সময়ে দুটি প্রত্যাখ্যানগুলি ব্যবহার করবেন না! এবং!)

4
@ রজার পেট "দুটি প্রত্যাখ্যান ব্যবহার করবেন না" -> হুম, আমরা গভীর "খনন" না করি এবং "প্রত্যাখ্যান" উভয় প্রত্যাখ্যান । ;-)। সম্ভবত "ব্যবহার if (fgets(Name, sizeof Name, stdin)) {
chux -

3
@ চাক্স, আমি নিশ্চিত যে আপনি বোঝাতে চেয়েছিলেনif (fgets(Name, sizeof Name, stdin) == NULL ) {
আর সাহু

@ আরসাহু ট্রু : পেস্কি !:
চুক্স

উত্তর:


154

সামান্য কুৎসিত উপায়:

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

সামান্য অদ্ভুত উপায়:

strtok(Name, "\n");

মনে রাখবেন যে strtokব্যবহারকারী যদি খালি স্ট্রিং প্রবেশ করে (অর্থাত্ কেবল এন্টার টিপে) তবে ফাংশনটি প্রত্যাশার মতো কাজ করে না। এটি \nঅক্ষর অক্ষত ছেড়ে দেয় ।

অন্যদের অবশ্যই আছে।


7
থ্রেড সচেতন যে কোনও সি রানটাইম লাইব্রেরি (যার অর্থ, বেশিরভাগ যে কোনও একটি বহু-থ্রেড প্ল্যাটফর্মকে লক্ষ্য করে) strtok()থ্রেড নিরাপদে থাকবে (এটি 'আন্তঃ-কল' অবস্থার জন্য থ্রেড স্থানীয় স্টোরেজ ব্যবহার করবে)। এটি বলেছে যে অ-স্ট্যান্ডার্ড (তবে যথেষ্ট সাধারণ) strtok_r()বৈকল্পিকটি ব্যবহার করা আরও ভাল ।
মাইকেল বুড়

2
সম্পূর্ণরূপে থ্রেড-নিরাপদ এবং পুনঃপ্রেরণকারী বৈকল্পিকের জন্য আমার উত্তরটি দেখুন আপনার strtokপদ্ধতির মতো (এবং এটি খালি ইনপুটগুলির সাথে কাজ করে)। আসলে, প্রয়োগের একটি ভাল উপায় strtokহ'ল ব্যবহার strcspnএবং strspn
টিম Čএফ

2
আপনি যদি এমন পরিবেশে থাকেন যেখানে অতিরিক্ত দীর্ঘ লাইনের ঝুঁকি থাকে তবে অন্য কেসটি পরিচালনা করা গুরুত্বপূর্ণ। নিঃশব্দভাবে কাটা ইনপুট খুব ক্ষতিকারক বাগের কারণ হতে পারে।
ম্যালকম ম্যাকলিন

2
আপনি যদি ওয়ান-লাইনার পছন্দ করেন এবং গ্লিবিসি ব্যবহার করছেন তবে চেষ্টা করুন *strchrnul(Name, '\n') = '\0';
twobit

যখন strchr(Name, '\n') == NULL, "বাফারের জন্য ইনপুট খুব দীর্ঘ, ফ্ল্যাগ ত্রুটি" বাদ দিয়ে অন্য সম্ভাবনা উপস্থিত রয়েছে: শেষ পাঠটি stdinএকটি '\n'বা বিরল এমবেডেড নাল অক্ষর দ্বারা শেষ হয়নি ।
chux - মনিকা

439

সম্ভবত সবচেয়ে সহজ সমাধানটি আমার পছন্দের একটি স্বল্প-পরিচিত ফাংশন ব্যবহার করে 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'


30
এটি এমনকি শুরু হওয়ার bufferচেয়ে বিরলকে পরিচালনা করে '\0', এমন কিছু যা buffer[strlen(buffer) - 1] = '\0';পদ্ধতির জন্য দুঃখের কারণ হয়ে দাঁড়ায় ।
chux - মনিকা পুনরায় স্থাপন

5
@ চাক্স: হ্যাঁ, আমি আশা করি আরও বেশি লোক সম্পর্কে জানত strcspn()। লাইব্রেরির অন্যতম কার্যকর কাজ, আইএমও। আমি আজকের মতো প্রচুর সাধারণ সি হ্যাকগুলি লিখতে এবং প্রকাশ করার সিদ্ধান্ত নিয়েছি; এটি strtok_rব্যবহার করে একটি বাস্তবায়ন strcspnএবং strspnপ্রথমটির মধ্যে একটি ছিল: codepad.org/2lBkZk0w ( সতর্কতা: আমি নিশ্চয়তা দিতে পারি না যে এটি বাগগুলি ছাড়াই; এটি হুট করেই লেখা হয়েছিল এবং সম্ভবত কয়েকটি ছিল)। যদিও আমি এখনও তাদের প্রকাশ করব না, তবে আমি এটি বিখ্যাত "বিট টুইডলিং হ্যাকস" এর চেতনায় তৈরি করার ইচ্ছা নিয়েছি।
টিম Čas

4
দৃ rob়ভাবে ট্রিমfgets() করার উপায়গুলিতে সন্ধান করা । এটি একমাত্র সঠিক ওয়ান-লাইনার strcspn()বলে মনে হচ্ছে । দ্রুততর - যদিও এটি সহজ নয়। strlen
chux - মনিকা পুনরায় ইনস্টল

6
@ সিডবুশস: শিরোনাম এবং বিষয়বস্তু উভয় ক্ষেত্রেই প্রশ্নটি ইনপুট থেকেfgets() পিছনে থাকা নতুন লাইনের বিষয়ে জিজ্ঞাসা করে । যা সর্বদা প্রথম নিউলাইনও।
টিম Čas

9
@ সিডবুশস: আমি বুঝতে পেরেছি আপনি কোথা থেকে এসেছেন তবে নির্দিষ্ট পদগুলির জন্য আমাকে গুগল অনুসন্ধান ফলাফলের জন্য দায়ী করা যায় না। গুগলের সাথে কথা বলুন, আমার সাথে নয়।
টিম

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

8
স্ট্রিং ফাঁকা থাকলে সম্ভবত ব্যতিক্রম ছুঁড়ে ফেলবে, তাই না? পরিসীমা ছাড়াই সূচক পছন্দ।
এডওয়ার্ড ওলামিসান

1
অ্যাডওয়ার্ড ওলামিসান, স্ট্রিংটি অবশ্য কখনও ফাঁকা হবে না।
জেমস মরিস

5
@ জামেস মরিস অস্বাভাবিক ক্ষেত্রে fgets(buf, size, ....)-> strlen(buf) == 0। 1) fgets()প্রথম হিসাবে সার্চ charএকটি '\0'। 2) size == 13) তারপরে fgets()রিটার্নগুলি সামগ্রীতে যে কোনও কিছু হতে পারে। ( NULLbufsize_t ln = strlen(name); if (ln > 0 && name[ln-1] == '\n') name[--ln] = '\0';
ওপির কোডটি

2
স্ট্রিং ফাঁকা থাকলে কী হবে? ln-1 হবে, সত্যের জন্য সংরক্ষণ করুন size_tস্বাক্ষরবিহীন, এইভাবে এলোমেলো স্মৃতিতে লেখা। আমি মনে করি আপনি ব্যবহার করতে চান ssize_tএবং চেক করুন ln> 0।
abligh

2
@ কিংবদন্তি 2 কে: একটি সংকলন-সময় মানের জন্য অনুসন্ধান (বিশেষত শূন্যের মান হিসাবে strlen) একটি সরল চর-বাই-চর অনুসন্ধানের চেয়ে অনেক বেশি দক্ষতার সাথে প্রয়োগ করা যেতে পারে। যে কারণে আমি এই সমাধানটিকে একটি strchrবা strcspnভিত্তিকগুলির চেয়ে ভাল বিবেচনা করব।
এন্টি

17

নীচে '\n'একটি স্ট্রিং থেকে সংরক্ষণের দ্বারা সম্ভাব্য অপসারণ করার জন্য একটি দ্রুত পদ্ধতির রয়েছে fgets()
এটি strlen()2 টি পরীক্ষা সহ ব্যবহার করে ।

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')রেফাই ওয়াইএমএমভি, তবে দুটি পদ্ধতিই কাজ করে।


buffer, আসল থেকে কিছু পরিস্থিতিতে fgets()অন্তর্ভুক্ত থাকবে না "\n":
ক) রেখাটি দীর্ঘ ছিল bufferতাই কেবলমাত্র সংরক্ষণের charপূর্ববর্তীটির জন্য । অপঠিত অক্ষরগুলি প্রবাহে রয়ে গেছে। খ) ফাইলের শেষ লাইনটি a দিয়ে শেষ হয়নি । '\n'buffer
'\n'

যদি ইনপুটটিতে '\0'কোথাও শূন্য অক্ষর এম্বেড করা থাকে তবে রিপোর্ট করা দৈর্ঘ্যটি স্থানটি strlen()অন্তর্ভুক্ত করবে না '\n'


অন্য কয়েকটি উত্তরের সমস্যা:

  1. strtok(buffer, "\n");অপসারণ করতে ব্যর্থ '\n'যখন bufferহয় "\n"। এই উত্তরটি থেকে - এই সীমাবদ্ধতার সতর্ক করার জন্য এই উত্তরের পরে সংশোধন করা হয়েছে।

  2. নিম্নলিখিতটি যখন প্রথম charপড়া হয় তখন বিরল অনুষ্ঠানে ব্যর্থ fgets()হয় '\0'। এম্বেড থাকা অবস্থায় ইনপুট শুরু হলে এটি ঘটে '\0'। তারপরে বৈধ পরিসরের বাইরে অবশ্যই মেমরি অ্যাক্সেস buffer[len -1]হয়ে যায় । হ্যাকার এমন কিছু যা চেষ্টা করতে পারে বা মূর্খতার সাথে ইউটিএফ 16 টেক্সট ফাইলগুলি পড়ে। এই উত্তরটি যখন লেখা হয়েছিল তখন এটি ছিল একটি উত্তরের অবস্থা । পরবর্তীতে একটি নন-ওপি এটিকে উত্তরগুলির চেকের মতো কোড অন্তর্ভুক্ত করার জন্য এটি সম্পাদনা করে ।buffer[SIZE_MAX]buffer""

    size_t len = strlen(buffer);
    if (buffer[len - 1] == '\n') {  // FAILS when len == 0
      buffer[len -1] = '\0';
    }
  3. sprintf(buffer,"%s",buffer);অনির্ধারিত আচরণ: রেফ । তদ্ব্যতীত, এটি কোনও শীর্ষস্থানীয়, পৃথককরণ বা শ্বেত স্থান অনুসরণ করে কোনও সংরক্ষণ করে না। এখন মুছে ফেলা হয়েছে

  4. [ভাল উত্তর পরবর্তী কারণে সম্পাদনা ] পদ্ধতির buffer[strcspn(buffer, "\n")] = 0;তুলনায় কর্মক্ষমতা ব্যতীত 1 টি লাইনারের কোনও সমস্যা নেই strlen()। ট্রিমিংয়ের পারফরম্যান্স সাধারণত প্রদত্ত কোডটি I / O করছে না - সিপিইউ সময়ের একটি ব্ল্যাকহোল। নিম্নলিখিত কোডটির জন্য স্ট্রিংয়ের দৈর্ঘ্য বা উচ্চ কার্যকারিতা সচেতন হওয়া উচিত, এই strlen()পদ্ধতিটি ব্যবহার করুন । অন্যথায় strcspn()একটি দুর্দান্ত বিকল্প।


সহায়ক উত্তরের জন্য ধন্যবাদ। strlen(buffer)যখন বাফার আকারটি ব্যবহার করে গতিশীলভাবে বরাদ্দ করা হয় তখন আমরা কী ব্যবহার করতে পারি malloc?
rrz0

@ আরআরজ0 buffer = malloc(allocation_size); length = strlen(buffer);খারাপ - মেমরির নির্দেশিত ডেটা bufferঅজানা। buffer = malloc(allocation_size_4_or_more); strcpy(buffer, "abc"); length = strlen(buffer);ঠিক আছে
chux

এর জন্য ধন্যবাদ!! আমি একটি সিএস কোর্স নিচ্ছি এবং এটি একটি কার্যভারের জন্য অত্যন্ত সহায়ক ছিল greatly আমি আপনার উত্তরটি উত্স কোডে জমা দিয়েছি।
নাথানিয়েল হোয়েট

8

প্রতিটি লাইনে '\ 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';
}

1
মনে রাখবেন পরিবর্তে এটি ব্যবহার করা নিরাপদ হবে । strnlenstrlen
মাইক মার্টসক

3
প্রশ্নযুক্ত লিঙ্কযুক্ত প্রথম উত্তরের একটি মন্তব্যে "নোট করুন যে স্ট্র্লেন (), আরআরসিএমপি () এবং স্টার্ডআপ () নিরাপদ। 'এন' বিকল্পগুলি আপনাকে অতিরিক্ত কার্যকারিতা দেয়।"
Étienne

4
@ এসকর না, তা হবে না। একটি প্রবেশ করানো nযাদুতে সুরক্ষা বাড়ায় না, এক্ষেত্রে এটি কোডটিকে আরও বিপজ্জনক করে তুলবে। একইভাবে strncpy, একটি মারাত্মক অনিরাপদ ফাংশন। আপনি যে পোস্টটি লিঙ্ক করেছেন সেটি হ'ল খারাপ পরামর্শ।
এমএম

3
এটি খালি স্ট্রিংয়ের জন্য খারাপভাবে ব্যর্থ হয় ( "")। এছাড়াও strlen()ফিরে size_tনা int
alk

4
এটি খালি স্ট্রিংয়ের জন্য অনিরাপদ, এটি সূচি -১ এ লিখবে। এটি ব্যবহার করবেন না।
জিন-ফ্রান্সোইস ফ্যাব্রে

3

একক '\ n' ট্রিমিংয়ের জন্য,

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

একাধিক '' n 'ট্রিমিংয়ের জন্য,

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

1
কেন নীড় ifযখন আপনি কেবল একটি শর্ত ব্যবহার করে লিখতে পারেন &&? এই whileলুপটির একটি অদ্ভুত কাঠামো রয়েছে; এটা সহজভাবে হতে পারে while (length > 0 && string[length-1] == '\n') { --length; string[length] = '\0'; }
মেলপোমেন

পরামর্শের জন্য @ মেলপোমেন ধন্যবাদ। কোড আপডেট করুন।
বেপ্পি

1
আমি প্রস্তাব করব যে প্রথম ফাংশন আরো স্বাভাবিকভাবেই হিসাবে সংজ্ঞায়িত করা হয়: size_t length = strlen(string); if (length > 0 && string[length-1] == '\n') { string[length-1] = '\0'; }। এটি দ্বিতীয় সংজ্ঞাটি আরও ভাল আয়না করে (কেবল ifপরিবর্তে ব্যবহার করে while)।
মেলপোমেন

ধন্যবাদ এলপোমেন এটা বোঝা যায়। আমি কোড আপডেট করেছি।
BEPP

1

আমার নবাবি উপায় ;-) দয়া করে আমাকে যদি তা সঠিক হয় তা জানান। এটি আমার সমস্ত মামলার জন্য কাজ করছে বলে মনে হচ্ছে:

#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

সম্ভবত খুব সুস্পষ্ট উপায়ে নিউলাইন চরিত্রটি সরানোর পদক্ষেপগুলি:

  1. হেডার NAMEব্যবহার করে স্ট্রিংয়ের দৈর্ঘ্য নির্ধারণ করুন । নোট যে সমাপ্তি গণনা করে না ।strlen()string.hstrlen()\0
size_t sl = strlen(NAME);

  1. দেখুন যদি স্ট্রিংটি শুরু হয় বা কেবল একটি \0অক্ষর (খালি স্ট্রিং) দিয়ে থাকে। এই ক্ষেত্রে slহবে 0যেহেতু strlen()আমি doesn't উপরে বলেন গণনা \0এবং এটি প্রথম সংঘটন এ স্টপ:
if(sl == 0)
{
   // Skip the newline replacement process.
}

  1. সঠিক স্ট্রিংয়ের শেষ অক্ষরটি একটি নতুন লাইন চরিত্র কিনা তা পরীক্ষা করুন '\n'। যদি এটি হয় তবে \nএকটি দিয়ে প্রতিস্থাপন করুন \0। নোট করুন যে সূচি গণনাগুলি শুরু হয় 0তাই আমাদের করা দরকারNAME[sl - 1] :
if(NAME[sl - 1] == '\n')
{
   NAME[sl - 1] = '\0';
}

আপনি যদি কেবল fgets()স্ট্রিংয়ের অনুরোধে এন্টার টিপেন (স্ট্রিং সামগ্রীটি কেবলমাত্র একটি নতুন লাইন চরিত্রের সমন্বিত ছিল) তবে NAMEস্ট্রিংটির পরে খালি স্ট্রিং হবে।


  1. আমরা ifলজিক অপারেটরটি ব্যবহার করে কেবলমাত্র এক- স্তরে একসাথে পদক্ষেপ 2 এবং 3 একত্রিত করতে পারি &&:
if(sl > 0 && NAME[sl - 1] == '\n')
{
   NAME[sl - 1] = '\0';
}

  1. সমাপ্ত কোড:
size_t sl = strlen(NAME);
if(sl > 0 && NAME[sl - 1] == '\n')
{
   NAME[sl - 1] = '\0';
}

আপনি যদি হ্যান্ডলিং করে এই কৌশলটি ব্যবহারের জন্য কোনও ফাংশন পছন্দ করেন fgets প্রতিটি বার প্রতিবার টাইপ না করে সাধারনভাবে আউটপুট স্ট্রিংগুলি করেন, তা এখানে 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';
    }
}

আপনার প্রদত্ত উদাহরণে এটি হ'ল:

printf("Enter your Name: ");

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

নোট করুন যে ইনপুট স্ট্রিংটিতে এতে এম্বেড থাকলে এই পদ্ধতিটি কাজ করে না \0। যদি কেস হয়strlen() তবে প্রথমটি পর্যন্ত কেবলমাত্র অক্ষরের পরিমাণ ফেরত পাওয়া যাবে \0। তবে এটি বেশ সাধারণ দৃষ্টিভঙ্গি নয়, যেহেতু সর্বাধিক স্ট্রিং-রিডিং ফাংশন সাধারণত প্রথমে থামে \0এবং সেই নাল চরিত্রটি না হওয়া পর্যন্ত স্ট্রিংটি নেয়।

নিজে থেকে প্রশ্ন বাদে। ডবল negations যে আপনার কোড unclearer করা এড়াতে চেষ্টা করুন: if (!(fgets(Name, sizeof Name, stdin) != NULL) {}। আপনি সহজভাবে করতে পারেন if (fgets(Name, sizeof Name, stdin) == NULL) {}


আপনি কেন এটি করতে চান তা নিশ্চিত নয়। নিউলাইনগুলি সরানোর বিন্দুটি স্ট্রিংগুলি বাতিল করতে নয়; এটি নিউলাইনগুলি সরিয়ে ফেলা হয়। একটি প্রতিস্থাপন করা হচ্ছে \nএকটি সঙ্গে \0শেষ একটি স্ট্রিং এর "সরানো হচ্ছে" সম্পর্কে newline এর একটি উপায়। তবে \nএকটি স্ট্রিংয়ের মধ্যে অক্ষরগুলি প্রতিস্থাপন করা স্ট্রিংকে মৌলিকভাবে পরিবর্তন করে। ইচ্ছাকৃত একাধিক নিউলাইন চরিত্রের সাথে স্ট্রিং থাকা অস্বাভাবিক কিছু নয় এবং এটি কার্যকরভাবে এই স্ট্রিংগুলির শেষগুলি কেটে ফেলবে। এই জাতীয় নিউলাইনগুলি সরাতে , অ্যারের সামগ্রীগুলি ওভার-রাইটিংয়ের জন্য বাম দিকে সরিয়ে নেওয়া উচিত \n
প্রাক্তন নিহিলো

@ এক্সনিহিলো কেউ কীভাবে একের সাথে একাধিক নিউলাইন দিয়ে স্ট্রিং ইনপুট করতে পারে fgets()?
রবার্টস মনিকা সেলিওকে সমর্থন করে

ঠিক আছে, আপনি একাধিক কল দ্বারা প্রাপ্ত স্ট্রিংগুলি সংযুক্ত করতে পারেন fgets()। তবে আমি আপনার আপত্তি বুঝতে পারি না: একাধিক নিউলাইন হ্যান্ডেল করার জন্য আপনি একমাত্র প্রস্তাব কোড।
প্রাক্তন নিহিলো

@ এক্সনিহিলো আপনি ঠিকই আছেন, আমি কৌশলটি উড়িয়ে দেব। আমি পছন্দসই ফলাফল পাওয়ার জন্য খুব কঠোর কিন্তু সম্ভাব্য উপায় যুক্ত করতে চেয়েছিলাম।
রবার্টস মনিকা সেলিওকে সমর্থন করে

@ এক্সনিহিলো আমার উত্তরটিকে পুরোপুরি সম্পাদনা করেছে এবং strlenসদৃশ ইত্যাদি ব্যবহার করে মূল পদ্ধতির অনুসরণ করেছে নকল না হওয়ার জন্য যুক্তিযুক্তকরণ : ১. পদক্ষেপের মাধ্যমে কোডটির ব্যাখ্যা। ২. ফাংশন এবং প্রসঙ্গ ভিত্তিক সমাধান হিসাবে সরবরাহ করা। ৩. দ্বিগুণ অস্বীকারের অভিব্যক্তি এড়াতে ইঙ্গিত।
রবার্টস মোনিকা সেলিওকে

0

টিম Čএমন একটি লাইনার fgets এর কল দ্বারা প্রাপ্ত স্ট্রিংগুলির জন্য আশ্চর্যজনক, কারণ আপনি জানেন যে এগুলি শেষে একটি একক নিউলাইন রয়েছে।

আপনি যদি অন্য কোনও প্রসঙ্গে থাকেন এবং একাধিক নিউলাইন থাকতে পারে এমন স্ট্রিংগুলি পরিচালনা করতে চান, আপনি স্ট্রান্সপিএন খুঁজছেন হতে পারে। এটি পসিক্স নয়, অর্থাত আপনি এটি সমস্ত ইউনিটগুলিতে খুঁজে পাবেন না। আমি নিজের প্রয়োজনে একটি লিখেছি।

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

সি-তে পার্ল চম্প সমতুল্য সন্ধানকারীদের জন্য, আমি মনে করি এটি এটি (চম্প কেবল পেছনের নতুন লাইনটি সরিয়ে দেয়)।

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

1
"কারণ আপনি জানেন যে এগুলি শেষে একটি নতুন লাইন রয়েছে" " -> এটি তখনও কাজ করে যখন না থাকে '\n'(বা স্ট্রিংটি থাকে "")।
chux -

আপনার প্রথম মন্তব্য chux এর প্রতিক্রিয়া হিসাবে, আমার উত্তর এটি সংরক্ষণ করে। strrcspnযখন নেই তখন আমাকে পুনরায় স্থাপন করতে হবে \n
ফিলিপ এ

এর goto end;পরিবর্তে কেন ব্যবহার করবেন return len;?
chqrlie

@ chqrlie আমার এই অপ্রয়োজনীয় 2-স্তরের লুপ থেকে বেরিয়ে আসার দরকার ছিল। ক্ষতি হয়েছে। গোটো না কেন?
ফিলিপ এ।

gotoআপনার কোডে আপনার দুটি ধরণের রয়েছে : একটি অকেজো 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

0

যদি ব্যবহার 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যদিও উপেক্ষিত করা উচিত নয়।


-1

নীচে ফাংশনটি আমি গিথুবগুলিতে রক্ষণ করছি স্ট্রিং প্রসেসিং লাইব্রেরির একটি অংশ। এটি স্ট্রিং থেকে অযাচিত অক্ষরগুলি সরিয়ে দেয় এবং ঠিক আপনি কী চান

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

ধন্যবাদ @ Chqrlie! আপনার পরামর্শগুলি প্রতিফলিত করার জন্য কোড আপডেট করেছে ..... স্ট্যান্ডার্ড ম্যানিপুলেশন লাইব্রেরি তৈরির লক্ষ্যে কোনও স্ট্যান্ডার্ড লাইব্রেরি ফাংশন ব্যবহার না করে জাস্টস্ট্রিং একটি মজাদার প্রকল্প হিসাবে শুরু হয়েছে, তাই আমি ব্যবহার করিনিstrchr
fnisi

1
" কোনও স্ট্যান্ডার্ড লাইব্রেরির ফাংশন ব্যবহার না করে স্ট্রিং ম্যানিপুলেশন লাইব্রেরি " লেখা একটি দুর্দান্ত অনুশীলন, তবে কেন অন্য লোকেরা এটি ব্যবহার করতে বলবে? যদি কিছু হয় তবে এটি কোনও স্ট্যান্ডার্ড লাইব্রেরির চেয়ে ধীর এবং কম পরীক্ষিত হতে চলেছে।
মেলপোমেন

প্রশ্নটি যা জিজ্ঞাসা করে তার থেকে এটি একটি আলাদা কাজ করছে। এটি সম্ভবত একমাত্র নতুন লাইন থেকে মুক্তি পেতে ব্যবহার করা যেতে পারে তবে এটি ওভারকিলের মতো মনে হয়।
জোনাথন লেফলার

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

আপনার এটি করা উচিত। এই কোডটি মূলত স্ট্রিংটির মধ্য দিয়ে লুপ হয় যতক্ষণ না এটি '\ n' সন্ধান করে। এটি খুঁজে পাওয়া গেলে '\ n' নাল চরিত্রের টার্মিনেটর দ্বারা প্রতিস্থাপন করা হবে '\ 0'

নোট করুন যে আপনি এই লাইনে স্ট্রিং না করে অক্ষরগুলি তুলনা করছেন, তারপরে আরআরসিএমপি () ব্যবহার করার দরকার নেই:

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

যেহেতু আপনি একক উদ্ধৃতি এবং ডাবল উদ্ধৃতি ব্যবহার করবেন না। এখানে প্রায় একক উদ্ধৃতি চিহ্ন বনাম একটি লিঙ্ক যদি আপনি আরো জানতে চান


2
আপনার কোডটির ফর্ম্যাটটি ব্যাখ্যা এবং সম্পাদনা করা ভাল হয়।
আনহ ফাম

সাধারণত বেনাম কোডের কয়েকটি সারি পোস্ট করার পরিবর্তে কোনও সমাধান ব্যাখ্যা করা ভাল। আপনি কীভাবে আমি একটি ভাল উত্তর লিখতে পারি এবং পুরোপুরি কোড ভিত্তিক উত্তরগুলিও ব্যাখ্যা করতে পারি
ম্যাসিমিলিয়ানো ক্রাউস

1
আমি দুঃখিত এটি এখানে আমার প্রথম অবদান ছিল। আমি এটা ঠিক করব. প্রতিক্রিয়াটির জন্য ধন্যবাদ
ম্যাথিয়াস মার্টিনস জেরেনিমো

3
অপ্রয়োজনীয়: বহুবার for(int i = 0; i < strlen(Name); i++ )কল করবে strlen(Name)(লুপ পরিবর্তনগুলি Name[]) সুতরাং দৈর্ঘ্যের সাথে N, এটি একটি O(N*N)সমাধান। strlen(Name)ও (এন) `সমাধান সরবরাহ করার জন্য কেবলমাত্র 1 টি কল করতে হবে। এর int iপরিবর্তে কেন ব্যবহার করা হচ্ছে তা অস্পষ্ট size_t i। বিবেচনা করুনfor(size_t i = 0; i < Name[i]; i++ )
chux - মনিকা

@ chux আরও পছন্দfor (size_t i = 0; Name[i]; i++) { if (Name[i] == '\n') { Name[i] = '\0'; break; } }
মেলপোমেন

-1

আর একবার চেষ্টা কর:

        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)উপচে পড়তে পারে: strlenফিরে আসে size_tনা int। অদ্ভুত if (len>0) if (...)শর্তের কী আছে ? আপনি কি জানেন না &&? আপনি যদি সিআর / এলএফ-এর একাধিক পেছনের উদাহরণ সরিয়ে ফেলছেন তবে কেন নিজেকে 5-এ সীমাবদ্ধ রাখুন? কেন তাদের সব সরাবেন না? intযখন ফাংশনটি সর্বদা ফিরে আসে তখন কেন ফিরতি টাইপ থাকে 0? শুধু ফিরে আসবে না কেন void?
মেলপোমেন
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.