আমি সি তে কনস্ট্যান্ট / আক্ষরিক স্ট্রিংগুলি কীভাবে সংযুক্ত করতে পারি?


346

আমি সি-তে কাজ করছি, এবং আমাকে কয়েকটি জিনিস একত্র করতে হবে।

এই মুহূর্তে আমার কাছে এটি রয়েছে:

message = strcat("TEXT ", var);

message2 = strcat(strcat("TEXT ", foo), strcat(" TEXT ", bar));

এখন যদি আপনার সি এর অভিজ্ঞতা থাকে তবে আমি নিশ্চিত যে আপনি এটি বুঝতে পেরেছেন যে আপনি এটি চালনার চেষ্টা করার সময় এটি আপনাকে একটি সেগমেন্টেশন ত্রুটি দেয়। তাহলে আমি কীভাবে এটিকে ঘিরে কাজ করব?


6
আমি আপনাকে পরামর্শ দিতে চাই যে আপনি স্ট্রিকাটের পরিবর্তে স্ট্রলক্যাট ব্যবহার করুন! gratisoft.us/todd/papers/strlcpy.html
activout.se

3
আমি সেই পরামর্শটি পুনরায় বলতে চাই। স্ট্রাক্যাট বাফার ওভারফ্লো শোষণের জন্য দুর্বলতা সৃষ্টি করে। কেউ আপনার প্রোগ্রামের ডেটা দিতে পারে যার কারণে এটি স্বেচ্ছাচারিত কোড কার্যকর করে।
ব্রায়ান

উত্তর:


388

সি তে, "স্ট্রিংস" কেবল সরল charঅ্যারে are অতএব, আপনি অন্যান্য "স্ট্রিং" দিয়ে সরাসরি তাদের সাথে সংযুক্ত করতে পারবেন না।

আপনি strcatফাংশনটি ব্যবহার করতে পারেন , যা দ্বারা নির্দেশিত স্ট্রিংয়ের শেষে নির্দেশিত srcস্ট্রিং যুক্ত করে dest:

char *strcat(char *dest, const char *src);

এখানে সিপিপ্লসপ্লাস ডটকমের একটি উদাহরণ রয়েছে :

char str[80];
strcpy(str, "these ");
strcat(str, "strings ");
strcat(str, "are ");
strcat(str, "concatenated.");

প্রথম প্যারামিটারের জন্য আপনাকে গন্তব্য বাফারটি সরবরাহ করতে হবে। গন্তব্য বাফার অবশ্যই একটি চর অ্যারে বাফার হতে হবে। উদাহরণ:char buffer[1024];

নিশ্চিত করুন যে প্রথম প্যারামিটারে আপনি যা অনুলিপি করার চেষ্টা করছেন সেটি সঞ্চয় করার জন্য পর্যাপ্ত জায়গা রয়েছে। যদি আপনার কাছে উপলভ্য থাকে তবে এই জাতীয় ফাংশনগুলি ব্যবহার করা নিরাপদ: strcpy_sএবং strcat_sযেখানে আপনাকে স্পষ্টভাবে গন্তব্য বাফারের আকার নির্দিষ্ট করতে হবে।

দ্রষ্টব্য : একটি স্ট্রিং আক্ষরিক বাফার হিসাবে ব্যবহার করা যায় না, কারণ এটি ধ্রুবক। সুতরাং, আপনাকে সর্বদা বাফারের জন্য একটি চর অ্যারে বরাদ্দ করতে হবে।

এর রিটার্ন মানটি strcatসহজেই উপেক্ষা করা যেতে পারে, এটি কেবলমাত্র একই পয়েন্টারটিকে প্রথম আর্গুমেন্ট হিসাবে পাস হিসাবে প্রদান করে। এটি সুবিধার জন্য এখানে রয়েছে এবং আপনাকে কোডের এক লাইনে কলগুলি শৃঙ্খলাবদ্ধ করতে দেয়:

strcat(strcat(str, foo), bar);

সুতরাং আপনার সমস্যাটি নিম্নলিখিত হিসাবে সমাধান করা যেতে পারে:

char *foo = "foo";
char *bar = "bar";
char str[80];
strcpy(str, "TEXT ");
strcat(str, foo);
strcat(str, bar);

66
দয়া করে "আপনি কি খুব যত্নবান হন ..." রাখবেন? এটি যথেষ্ট চাপ দেওয়া যাবে না। স্ট্রাইক্যাট, আরআরসিপি এবং স্প্রিন্টফের অপব্যবহার হ'ল অস্থির / অনিরাপদ সফ্টওয়্যার।
প্লিথ

12
সতর্কতা: লিখিত হিসাবে, এই কোডটি আপনার কোডে বাফার ওভারফ্লো শোষণের জন্য একটি বিশাল, ফাঁক গর্ত ছেড়ে দেবে।
ব্রায়ান

11
উপরের উদাহরণে কোনও বাফার ওভারফ্লো শোষণ সম্ভব নয়। এবং হ্যাঁ আমি সাধারণভাবে সম্মত হই আমি ফু ও বারের নির্ধারিত স্ট্রিং দৈর্ঘ্যের জন্য উপরের উদাহরণটি ব্যবহার করব না।
ব্রায়ান আর বন্ডি

13
@ এসসিহোডেলিয়া: এছাড়াও ভুলে যাবেন না যে কাঁটাচামচের চেয়ে চামচগুলি আরও ভাল! সুতরাং সর্বদা একটি চামচ ব্যবহার নিশ্চিত করুন!
ব্রায়ান আর বন্ডি

20
দ্বিতীয় ডলম্যানের কাছে জোয়েল স্পলস্কি ইস্যু নিয়ে বেশ বিস্তৃত নিবন্ধ লিখেছেন । বাধ্যতামূলক পড়া উচিত। ;-)
পিটার.স্লিজিক

247

strcatসি কোড ব্যবহার করা থেকে বিরত থাকুন। সবচেয়ে পরিষ্কার এবং সবচেয়ে গুরুত্বপূর্ণ, সবচেয়ে নিরাপদ উপায়টি হ'ল snprintf:

char buf[256];
snprintf(buf, sizeof buf, "%s%s%s%s", str1, str2, str3, str4);

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


3
চেকার্স, তিনি আকারের যুক্তির "বুফ" এর আশেপাশে প্রথম বন্ধনী সম্পর্কে কথা বলছিলেন। যুক্তিটি যদি একটি অভিব্যক্তি হয় তবে তাদের প্রয়োজন হয় না। তবে কেন আপনি নিম্নচাপে রয়েছেন তা আমি বুঝতে পারি না। আমি মনে করি আপনার উত্তরটি সর্বোত্তম, যদিও এটি সি 99 রয়েছে। (সম্ভবত এ কারণেই তারা একমত নয়! ল্যামার!) +1
জোহানেস স্কাউব -

4
মাপের () কেবল চর বুফের জন্য এখানে কাজ করে [...]। চর * বুফ = ম্যালোক (...) এর জন্য নয়। অ্যারে এবং পয়েন্টারগুলির মধ্যে অনেক পার্থক্য নেই, তবে এটি তাদের মধ্যে একটি!
মিঃআর

2
এছাড়াও, তিনি কনকেন্টেশন করার চেষ্টা করছেন। ব্যবহার করে প্রতিযোগিতা snprintf()হ'ল বিগ নম্বর নং।
লিওনার্দো হেরেরা

5
@ মিঃরি: পয়েন্টার এবং অ্যারেগুলির মধ্যে পার্থক্যগুলি বিশাল এবং সম্পূর্ণ! এটি কীভাবে আপনি তাদের ব্যবহার করেন যা সর্বদা পৃথক হয় না in এছাড়াও, পয়েন্টার এবং গতিশীল বরাদ্দ সত্যই অরথোগোনাল ধারণা।
অরবিট Light ই

34
আমার পোষা প্রাণীগুলির মধ্যে একটি হ'ল @ ইউনুইন্ডের মতো লোক যারা sizeof(x)এবং এর মধ্যে অর্থহীন পার্থক্যের জন্য জোর দেয় sizeof x। প্রথম বন্ধনী চিহ্নিতকরণ সর্বদা কাজ করে এবং অপরিবর্তিত স্বরলিপি কেবল কখনও কখনও কাজ করে, তাই সর্বদা প্রথম বন্ধনীরূপী স্বরলিপি ব্যবহার করুন; এটি মনে রাখা সহজ নিয়ম এবং নিরাপদ। এটি একটি ধর্মীয় যুক্তিতে জড়িয়ে পড়ে - যারা এর আগে আপত্তি জানায় তাদের সাথে আমি আলোচনায় জড়িত ছিলাম - তবে 'সর্বদা ব্যবহৃত প্রথম বন্ধনীর ব্যবহার' এর সরলতা এগুলি ব্যবহার না করার জন্য কোনও যোগ্যতার চেয়েও বেশি (আইএমএনএসএইচও, অবশ্যই)। এটি ভারসাম্যের জন্য উপস্থাপন করা হয়েছে।
জোনাথন লেফলার

24

ভাবেন, স্ট্র এন সিপি (), টিআর এন বিড়াল (), বা এস এন প্রিন্টফ () ব্যবহার করুন ।
আপনার বাফার স্পেসকে ছাড়িয়ে যাওয়ার পরে মেমরির অনুসরণে যা কিছু ট্র্যাশ হয়ে যাবে!
(এবং অনুগ্রহপূর্ব নাল '\ 0' অক্ষরের জন্য স্থানটির অনুমতি দেওয়ার কথা মনে রাখবেন!)


3
NULL চরিত্রের জন্য কেবল আপনার স্থানের অনুমতি দেওয়ার কথা মনে রাখা উচিত নয়, আপনাকে NULL চরিত্রটি যুক্ত করার কথা মনে রাখতে হবে । strncpy এবং strncat এটি আপনার জন্য করবেন না।
গ্রিম পেরো

উহ? strncpy () এবং strncat () অবশ্যই সমাপ্তি চরিত্রটি যুক্ত করুন। আসলে, তারা অনেক বেশি যুক্ত করে। বাফারে কমপক্ষে যতক্ষণ জায়গা বাকি আছে, যা এই কলগুলির সাথে একটি বিশাল ফাঁদ। প্রস্তাবিত নয়।
বিনোদন

3
@ অউইন্ড, আমার মনে হয় গ্র্যামির পয়েন্টটি হ'ল বাফার যদি খুব ছোট হয় তবে স্ট্রান্সকিপি বা স্ট্র্যাঙ্ক্যাট সমাপ্তি ' termin 0' যুক্ত করবে না
কুইনমার্স

2
snprintf ভাল, strncpy / strncat সবচেয়ে খারাপ সম্ভাব্য প্রস্তাবনা, strlcpy / strlcat আরও ভাল।
রবার্ট গ্যাম্বল

9
ব্যবহার করবেন না strncpy()। এটা না একটি "নিরাপদ" সংস্করণ strcpy()। লক্ষ্য বর্ণের অ্যারের অকারণে অতিরিক্ত '\0'অক্ষরগুলির সাথে প্যাড করা যেতে পারে বা আরও খারাপ হতে পারে, এটি নির্বিঘ্নে ছেড়ে দেওয়া যেতে পারে (অর্থাত্ একটি স্ট্রিং নয়)। (এটি এমন একটি ডেটা স্ট্রাকচারের সাথে ব্যবহারের জন্য ডিজাইন করা হয়েছিল যা খুব কমই ব্যবহৃত হয়, একটি অক্ষর অ্যারে শূন্য বা তার বেশি '\0'অক্ষরের সাথে শেষ পর্যন্ত প্যাড করে ))
কিথ থম্পসন

22

সংকলনের সময় স্ট্রিংগুলিও সংক্ষিপ্ত করা যেতে পারে।

#define SCHEMA "test"
#define TABLE  "data"

const char *table = SCHEMA "." TABLE ; // note no + or . or anything
const char *qry =               // include comments in a string
    " SELECT * "                // get all fields
    " FROM " SCHEMA "." TABLE   /* the table */
    " WHERE x = 1 "             /* the filter */ 
                ;

15

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

#include <stdio.h>
#include <string.h>

void example(const char *header, const char **words, size_t num_words)
{
    size_t message_len = strlen(header) + 1; /* + 1 for terminating NULL */
    char *message = (char*) malloc(message_len);
    strncat(message, header, message_len);

    for(int i = 0; i < num_words; ++i)
    {
       message_len += 1 + strlen(words[i]); /* 1 + for separator ';' */
       message = (char*) realloc(message, message_len);
       strncat(strncat(message, ";", message_len), words[i], message_len);
    }

    puts(message);

    free(message);
}

এটি একটি অন্তহীন লুপে শেষ হবে যখন num_words>INT_MAX, সম্ভবত আপনার size_tজন্য ব্যবহার করা উচিতi
12431234123412341234123

5

আউটপুট বাফারটি শুরু করতে ভুলবেন না। স্ট্রাইক্যাটের প্রথম আর্গুমেন্ট অবশ্যই একটি নাল টার্মিনেটেড স্ট্রিং হতে পারে ফলাফলের স্ট্রিংয়ের জন্য অতিরিক্ত অতিরিক্ত স্থান বরাদ্দ করা:

char out[1024] = ""; // must be initialized
strcat( out, null_terminated_string ); 
// null_terminated_string has less than 1023 chars

4

লোকেদের নির্দেশিত স্ট্রিং হ্যান্ডলিংয়ের অনেক উন্নতি হয়েছে। সুতরাং আপনি সি স্টাইলের স্ট্রিংয়ের পরিবর্তে কীভাবে সি ++ স্ট্রিং লাইব্রেরি ব্যবহার করবেন তা শিখতে চাইতে পারেন। তবে এখানে খাঁটি সি তে একটি সমাধান রয়েছে

#include <string.h>
#include <stdio.h>
#include <stdlib.h>

void appendToHello(const char *s) {
    const char *const hello = "hello ";

    const size_t sLength     = strlen(s);
    const size_t helloLength = strlen(hello);
    const size_t totalLength = sLength + helloLength;

    char *const strBuf = malloc(totalLength + 1);
    if (strBuf == NULL) {
        fprintf(stderr, "malloc failed\n");
        exit(EXIT_FAILURE);
    }

    strcpy(strBuf, hello);
    strcpy(strBuf + helloLength, s);

    puts(strBuf);

    free(strBuf);

}

int main (void) {
    appendToHello("blah blah");
    return 0;
}

এটি সঠিক / নিরাপদ কিনা তা আমি নিশ্চিত নই তবে এই মুহূর্তে এএনএসআই সি-তে আরও ভাল করার উপায় খুঁজে পাই না could


<string.h>সি ++ স্টাইল। আপনি চান "string.h"। আপনি দুবারও গণনা করুন strlen(s1), যার দরকার নেই। দীর্ঘ s3হতে হবে totalLenght+1
হাঁস Mooing

4
@ মুভিংডাক: "string.h"বাজে কথা।
sbi

আমি কিছুক্ষণ সি-স্টাইলের স্ট্রিং ব্যবহার করিনি। নির্ধারিত সংস্করণ পোস্ট করতে নির্দ্বিধায়।
নিলস

4
@ মুভিংডাক: এটি ভুল। #include <string.h>সঠিক সি। স্ট্যান্ডার্ড এবং সিস্টেমের শিরোলেখগুলির জন্য কোণ বন্ধনী ব্যবহার করুন (সহ <string.h>), আপনার প্রোগ্রামের অংশ হিসাবে শিরোনামগুলির জন্য উদ্ধৃতি চিহ্নগুলি। ( #include "string.h"যদি সেই নামে আপনার নিজের শিরোনামের ফাইল না থাকে তবে কাজ হবে <string.h>) তবে যেভাবেই ব্যবহার করুন )
কীথ থম্পসন

নোট করুন যে এটি C99- নির্দিষ্ট বৈশিষ্ট্যগুলির উপর নির্ভর করে: ডিক্লেয়ারেশন এবং স্টেটমেন্টগুলি মিশ্রণ করে এবং পরিবর্তনশীল-দৈর্ঘ্যের অ্যারে (ভিএলএস)। এও নোট করুন যে ভিএলএগুলি বরাদ্দ ব্যর্থতাগুলি সনাক্ত বা পরিচালনা করার জন্য কোনও ব্যবস্থা সরবরাহ করে না; যদি ভিএলএ বরাদ্দ করার মতো পর্যাপ্ত জায়গা না থাকে তবে আপনার প্রোগ্রামের আচরণটি সংজ্ঞায়িত।
কিথ থম্পসন

4

স্ট্রিং লিটারালগুলি সংশোধন করার চেষ্টা করা অপরিজ্ঞাত আচরণ, যা এরকম কিছু:

strcat ("Hello, ", name);

করতে চেষ্টা করবে। এটি nameস্ট্রিংকে আক্ষরিকের শেষে স্ট্রিংয়ের উপর চাপ দেওয়ার চেষ্টা করবে "Hello, "যা ভালভাবে সংজ্ঞায়িত হয়নি।

এটি কিছু চেষ্টা করুন। আপনি যা করার চেষ্টা করছেন বলে মনে হয় তা তা অর্জন করে:

char message[1000];
strcpy (message, "TEXT ");
strcat (message, var);

এই একটি বাফার এলাকায় সৃষ্টি হয় পরিবর্তন করা এবং তারপর কপি উভয় স্ট্রিং আক্ষরিক এবং এটি অন্যান্য পাঠ্য অনুমোদিত। বাফার ওভারফ্লোগুলি সম্পর্কে কেবল সাবধান হন। আপনি যদি ইনপুট ডেটা নিয়ন্ত্রণ করেন (বা এটি আগে পরীক্ষা করে দেখুন) তবে আমার মতো স্থির দৈর্ঘ্যের বাফারগুলি ব্যবহার করা ভাল।

অন্যথায়, আপনি এটি হ্যান্ডেল করতে পারবেন তা নিশ্চিত করার জন্য আপনার গাদা থেকে পর্যাপ্ত মেমরি বরাদ্দ করার মতো প্রশমন কৌশলগুলি ব্যবহার করা উচিত। অন্য কথায়, এর মতো কিছু:

const static char TEXT[] = "TEXT ";

// Make *sure* you have enough space.

char *message = malloc (sizeof(TEXT) + strlen(var) + 1);
if (message == NULL)
     handleOutOfMemoryIntelligently();
strcpy (message, TEXT);
strcat (message, var);

// Need to free message at some point after you're done with it.

4
যদি var / foo / বারে 1000 এর বেশি অক্ষর থাকে তবে কি হবে? > :)
জিও

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

7
@ পাক্সাদিয়াবলো: তবে আপনি এমনকি এটির উল্লেখও করেন নি, যেখানে এমন প্রশ্নের উত্তর দেওয়ার প্রয়োজন হবে বলে তার উত্তরে। এটি আপনার উত্তরকে বিপজ্জনক করে তোলে । এই কোডটি কেন ওপি-র মূল কোডের চেয়ে ভাল তা আপনি ব্যাখ্যা করেন নি, এটি "আপনার মূল হিসাবে একই ফলাফল অর্জন করে" (তাহলে কী হবে? মূলটিটি ভেঙে গেছে !), তাই উত্তর এছাড়াও অসম্পূর্ণ
অরবিট Light ই

আশাবাদ হিসাবে আপনার উদ্বেগের সমাধান করেছেন, @PreferencesBean, যদিও আদর্শের চেয়ে কম সময়োচিত পদ্ধতিতে :-) উত্তরটি নিয়ে আপনার এখনও সমস্যা আছে কিনা তা আমাকে জানান, এবং আমি আরও উন্নতি করব।
paxdiablo

3

স্ট্রাইক্যাট () এর প্রথম আর্গুমেন্টকে সংক্ষিপ্ত স্ট্রিংয়ের জন্য পর্যাপ্ত স্থান রাখতে সক্ষম হওয়া দরকার। ফলস্বরূপ পর্যাপ্ত স্থান সহ একটি বাফার বরাদ্দ করুন।

char bigEnough[64] = "";

strcat(bigEnough, "TEXT");
strcat(bigEnough, foo);

/* and so on */

strcat () দ্বিতীয় যুক্তিটি প্রথম যুক্তির সাথে একত্রিত করবে এবং ফলাফলটিকে প্রথম যুক্তিতে সংরক্ষণ করবে, প্রত্যাবর্তিত চরটি কেবল এই প্রথম যুক্তি, এবং কেবল আপনার সুবিধার জন্য।

প্রথম এবং দ্বিতীয় যুক্তির সাথে মিলিতভাবে নতুন বরাদ্দ স্ট্রিং পাবেন না, যা আমি আপনার কোডের উপর ভিত্তি করে প্রত্যাশা করেছিলাম।


3

সীমিত বাফার আকার না রেখে এটি করার সর্বোত্তম উপায় হ'ল অ্যাসপ্রিন্টফ ()

char* concat(const char* str1, const char* str2)
{
    char* result;
    asprintf(&result, "%s%s", str1, str2);
    return result;
}

2
আপনার ফিরে আসা উচিত char *, না const char *। ফেরতের মানটি পাস করতে হবে free
প্রতি জোহানসন

দুর্ভাগ্যক্রমে asprintfকেবল একটি জিএনইউ এক্সটেনশন।
কলমারিয়াস

3

আপনার যদি সি তে অভিজ্ঞতা থাকে তবে আপনি লক্ষ্য করবেন যে স্ট্রিংগুলি কেবল চর অ্যারে যেখানে শেষ অক্ষরটি নাল অক্ষর।

এখন কিছুটা অসুবিধাগ্রস্থ হওয়ায় কিছু যুক্ত করার জন্য আপনাকে শেষ চরিত্রটি খুঁজতে হবে। strcatআপনার জন্য এটি করতে হবে।

সুতরাং strcat শূন্য চরিত্রের জন্য প্রথম যুক্তির মাধ্যমে অনুসন্ধান করে। তারপরে এটি দ্বিতীয় আর্গুমেন্টের সামগ্রীর সাথে এটি প্রতিস্থাপন করবে (যতক্ষণ না এটি শূন্য হয়ে যায়)।

এখন আসুন আপনার কোডটি দিয়ে যান:

message = strcat("TEXT " + var);

এখানে আপনি "পাঠ্য" পাঠ্যটিতে পয়েন্টারে কিছু যুক্ত করছেন ("টেক্সট" এর ধরণটি কনস্ট চর * A একটি পয়েন্টার))।

এটি সাধারণত কাজ করবে না। "পাঠ্য" অ্যারে পরিবর্তন করেও এটি কাজ করবে না কারণ এটি সাধারণত ধ্রুবক বিভাগে রাখা হয়।

message2 = strcat(strcat("TEXT ", foo), strcat(" TEXT ", bar));

আপনি আরও স্থির পাঠ্যগুলিকে সংশোধন করার চেষ্টা করছেন তা বাদে এটি আরও ভাল কাজ করতে পারে। strcat ফলাফলের জন্য নতুন মেমরি বরাদ্দ করছে না।

পরিবর্তে আমি এই জাতীয় কিছু করার প্রস্তাব দেব:

sprintf(message2, "TEXT %s TEXT %s", foo, bar);

এর ডকুমেন্টেশন পড়ুন sprintfএর বিকল্পগুলির জন্য চেক করতে ।

এবং এখন একটি গুরুত্বপূর্ণ বিষয়:

নিশ্চিত হয়ে নিন যে বাফারটিতে পাঠ্য এবং নাল অক্ষরটি ধারণ করার জন্য পর্যাপ্ত জায়গা রয়েছে। কয়েকটি ফাংশন রয়েছে যা আপনাকে সহায়তা করতে পারে, যেমন, স্ট্র্যাঙ্ক্যাট এবং প্রিন্টফের বিশেষ সংস্করণ যা আপনার জন্য বাফার বরাদ্দ করে। বাফারের আকার নিশ্চিত না করা স্মৃতি দুর্নীতি এবং দূরবর্তীভাবে শোষণযোগ্য বাগগুলিতে নিয়ে যাবে।


ধরণ "TEXT"হয় char[5], না const char* । এটি char*বেশিরভাগ প্রসঙ্গে বিবেচনা করে। পশ্চাদপটে সামঞ্জস্যতার কারণে, স্ট্রিং লিটারেলগুলি হয় না const, তবে এগুলি সংশোধন করার চেষ্টা করার ফলে অপরিবর্তিত আচরণের ফলাফল হয়। (সি ++ তে, স্ট্রিং লিটারেলগুলি হয় const))
কিথ থমসন

2

আপনি আপনার নিজস্ব ফাংশন লিখতে পারেন যা একই কাজ করে strcat()তবে এটি কোনও পরিবর্তন করে না:

#define MAX_STRING_LENGTH 1000
char *strcat_const(const char *str1,const char *str2){
    static char buffer[MAX_STRING_LENGTH];
    strncpy(buffer,str1,MAX_STRING_LENGTH);
    if(strlen(str1) < MAX_STRING_LENGTH){
        strncat(buffer,str2,MAX_STRING_LENGTH - strlen(buffer));
    }
    buffer[MAX_STRING_LENGTH - 1] = '\0';
    return buffer;
}

int main(int argc,char *argv[]){
    printf("%s",strcat_const("Hello ","world"));    //Prints "Hello world"
    return 0;
}

উভয় স্ট্রিং যদি এক সাথে 1000 টিরও বেশি লম্বা হয় তবে এটি স্ট্রিংটি 1000 টি অক্ষরে কাটবে। আপনি MAX_STRING_LENGTHআপনার প্রয়োজন অনুসারে মান পরিবর্তন করতে পারেন।


আমি বাফারকে উপচে পড়ার আগেই দেখেছি, আমি আপনাকে বরাদ্দ দেখছি strlen(str1) + strlen(str2), তবে আপনি strlen(str1) + strlen(str2) + 1অক্ষরগুলি লেখেন । সুতরাং আপনি কি সত্যিই আপনার নিজের ফাংশন লিখতে পারেন?
লিভিউ

কি দারুন! তুমি কখনই স্মৃতি মুক্ত করো না, বাজে!return buffer; free(buffer);
লিভিউ

বিটিডাব্লু, sizeof(char) == 1(এছাড়াও আরও আরও সূক্ষ্ম ত্রুটি রয়েছে ...) আপনি এখন দেখতে পাচ্ছেন যে আপনার নিজের ফাংশনটি কেন লিখতে হবে না?
লিভিউ

@ লিভিউ আমি লাইনে মেমরিটি ফ্রি করি free(buffer);
ডোনাল্ড ডাক

1
free(buffer);return buffer;কখনই মৃত্যুদন্ড কার্যকর করা হয় না, এটি একটি ডিবাগারে দেখুন;) আমি এখন দেখছি: হ্যাঁ, আপনাকে mainফাংশনে মেমরিটি মুক্ত করতে হবে
লিভিউ

1

ধরে নিই যে আপনার কাছে চর * এর পরিবর্তে [স্থির_সাইজ] রয়েছে, আপনি <<cout<<likeঅর্ডার দিয়ে ("বরং% s বিচ্ছিন্ন% s \ n", "," প্রিন্টএফের সাহায্যে একবারে এটি করার জন্য একটি একক, সৃজনশীল ম্যাক্রো ব্যবহার করতে পারেন শৈলী বিন্যাস ")। আপনি যদি এমবেডেড সিস্টেমগুলির সাথে কাজ করছেন, এই পদ্ধতিটি আপনাকে মলোক এবং বৃহত *printfপরিবারগুলির মতো কাজগুলি ছাড়ার অনুমতি দেবে snprintf()(এটি ডায়েটলিবিকেও * প্রিন্টফের বিষয়ে অভিযোগ করা থেকে বিরত রাখে)

#include <unistd.h> //for the write example
//note: you should check if offset==sizeof(buf) after use
#define strcpyALL(buf, offset, ...) do{ \
    char *bp=(char*)(buf+offset); /*so we can add to the end of a string*/ \
    const char *s, \
    *a[] = { __VA_ARGS__,NULL}, \
    **ss=a; \
    while((s=*ss++)) \
         while((*s)&&(++offset<(int)sizeof(buf))) \
            *bp++=*s++; \
    if (offset!=sizeof(buf))*bp=0; \
}while(0)

char buf[256];
int len=0;

strcpyALL(buf,len,
    "The config file is in:\n\t",getenv("HOME"),"/.config/",argv[0],"/config.rc\n"
);
if (len<sizeof(buf))
    write(1,buf,len); //outputs our message to stdout
else
    write(2,"error\n",6);

//but we can keep adding on because we kept track of the length
//this allows printf-like buffering to minimize number of syscalls to write
//set len back to 0 if you don't want this behavior
strcpyALL(buf,len,"Thanks for using ",argv[0],"!\n");
if (len<sizeof(buf))
    write(1,buf,len); //outputs both messages
else
    write(2,"error\n",6);
  • নোট 1, আপনি সাধারণত আরগভি [0] এর মতো ব্যবহার করবেন না - কেবল উদাহরণ
  • দ্রষ্টব্য 2, আপনি পূর্ণসংখ্যার স্ট্রিংয়ের ধরণে রূপান্তর করার জন্য itoa () এর মতো নন-স্ট্যান্ডার্ড ফাংশন সহ একটি চার্ট আউটপুট করে এমন কোনও ফাংশন ব্যবহার করতে পারেন।
  • নোট 3, আপনি যদি ইতিমধ্যে আপনার প্রোগ্রামের যে কোনও জায়গায় প্রিন্টফ ব্যবহার করছেন তবে স্নিপ্রিন্টফ () সানপ্রিন্ট ব্যবহার না করার কোনও কারণ নেই কারণ সংকলিত কোডটি আরও বড় হবে (তবে অন্তর্নিহিত এবং উল্লেখযোগ্যভাবে দ্রুত)


1

আপনি স্থিতিযুক্তভাবে বরাদ্দ করা ঠিকানায় স্ট্রিংটি অনুলিপি করার চেষ্টা করছেন। আপনি একটি বাফার মধ্যে বিড়াল প্রয়োজন।

বিশেষ করে:

... স্নিপ ...

গন্তব্য

Pointer to the destination array, which should contain a C string, and be large enough to contain the concatenated resulting string.

... স্নিপ ...

http://www.cplusplus.com/reference/clibrary/cstring/strcat.html

এখানে একটি উদাহরণও রয়েছে।


0

এটি আমার সমাধান ছিল

#include <stdlib.h>
#include <stdarg.h>

char *strconcat(int num_args, ...) {
    int strsize = 0;
    va_list ap;
    va_start(ap, num_args);
    for (int i = 0; i < num_args; i++) 
        strsize += strlen(va_arg(ap, char*));

    char *res = malloc(strsize+1);
    strsize = 0;
    va_start(ap, num_args);
    for (int i = 0; i < num_args; i++) {
        char *s = va_arg(ap, char*);
        strcpy(res+strsize, s);
        strsize += strlen(s);
    }
    va_end(ap);
    res[strsize] = '\0';

    return res;
}

তবে আপনাকে কতগুলি স্ট্রিং সংযুক্ত করতে চলেছে তা নির্দিষ্ট করতে হবে

char *str = strconcat(3, "testing ", "this ", "thing");

0

এর অনুরূপ কিছু চেষ্টা করুন:

#include <stdio.h>
#include <string.h>

int main(int argc, const char * argv[])
{
  // Insert code here...
  char firstname[100], secondname[100];
  printf("Enter First Name: ");
  fgets(firstname, 100, stdin);
  printf("Enter Second Name: ");
  fgets(secondname,100,stdin);
  firstname[strlen(firstname)-1]= '\0';
  printf("fullname is %s %s", firstname, secondname);

  return 0;
}
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.