সি-তে কোনও ফাংশন থেকে আমি কীভাবে একাধিক মান ফিরিয়ে দেব?


89

আমার যদি এমন কোনও ফাংশন থাকে যা ফলাফল intএবং ফলাফল তৈরি করে string, আমি কীভাবে উভয়কে একটি ফাংশন থেকে ফিরিয়ে দেব?

যতদূর আমি বলতে পারি আমি কেবল একটি জিনিস ফিরতে পারি, ফাংশন নামের আগের ধরণ অনুসারে।


7
দ্বারা stringকি আপনি কি বোঝাতে চেয়েছেন "আমি সি ++ ব্যবহার করছি এবং এই হল std::stringবর্গ" বা "আমি সি ব্যবহার করছি এবং এই একটি হল char *পয়েন্টার বা char[]অ্যারে।"
ক্রিস লুটজ

ভাল, আমার বিশেষ ক্ষেত্রে, এটি দুটি অন্তর্নিহিত ছিল: একটি যা আমি তুলনা করছি তার 'স্কোর' এর জন্য, এবং একটি সর্বোচ্চ সংখ্যক স্কোর যেখানে পাওয়া গেছে তার 'সূচক' এর জন্য। আমি আরও সাধারণ ক্ষেত্রে এখানে একটি স্ট্রিং উদাহরণ ব্যবহার করতে চেয়েছিলাম
টনি স্টার্ক

রেফারেন্স দিয়ে স্ট্রিং পাস করুন এবং পূর্বাবস্থায় ফিরে দিন। দ্রুততম উপায়। কোন স্ট্রাক্টের প্রয়োজন নেই।
স্টিফান স্টেইগার

4
কোনও ফাংশন যা 2 টি ফলাফল একের বেশি কাজ করে না? চাচা বব কী বলতেন?
ডানকান

উত্তর:


124

আমি জানি না আপনার stringকী, তবে আমি ধরে নেব যে এটি নিজের স্মৃতি পরিচালনা করে।

আপনার দুটি সমাধান রয়েছে:

1: structআপনার প্রয়োজনীয় সমস্ত ধরণের সমন্বিত এমন একটি ফেরৎ দিন।

2: মানগুলি পাস করার জন্য পয়েন্টার ব্যবহার করুন।

আপনি কোনটি বেছে বেছে বেছে বেছে বেছে বেছে বেছে বেছে বেছে বেছে বেছে বেছে বেছে বেছে বেছে বেছে বেছে বেছে বেছে বেছে বেছে বেছে বেছে বেছে বেছে কোনটি বেছে বেছে ব্যবহার করেন।


7
আমি মনে করি এটি রিটার্নের মানগুলির সাথে কতটা সম্পর্কিত on যদি intটি একটি ত্রুটি কোড হয় এবং স্ট্রিংটির ফলাফল হয় তবে এগুলি একটি স্ট্রাক্টে একসাথে রাখা উচিত নয়। এটা ঠিক নির্বোধ। সেক্ষেত্রে আমি ইনটটি ফিরিয়ে দেব এবং স্ট্রিংটি দৈর্ঘ্যের জন্য char *এবং একটি হিসাবে প্রেরণ করব size_tযদি না এটি ফাংশনটির নিজস্ব স্ট্রিং এবং / অথবা ফিরে আসার জন্য বরাদ্দ দেওয়া একেবারে জরুরী NULL
ক্রিস লুটজ

@ ক্রিস আমি আপনার সাথে পুরোপুরি একমত, তবে তার প্রয়োজনীয় ভেরিয়েবলগুলির ব্যবহারের শব্দার্থবিজ্ঞানের সম্পর্কে আমার কোনও ধারণা নেই।
ট্র্যাভিস গোকেল

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

@ BobVicktor: সি এর রেফারেন্স সিমানটিকস মোটেই নেই (এটি সি ++ এর সাথে একচেটিয়া), তাই সবকিছুই একটি মান। দুটি পয়েন্টার সলিউশন (# 2) পয়েন্টারগুলির অনুলিপিগুলিকে কোনও ফাংশনে প্রেরণ করছে, যা getPairতারপরে অবনমিত হয় । আপনি যা করছেন তার উপর নির্ভর করে (ওপি কখনই এটি কোনও সি প্রশ্ন হিসাবে স্পষ্ট করে না), বরাদ্দটি উদ্বেগের বিষয় হতে পারে তবে এটি সাধারণত সি ++ জমিতে হয় না (রিটার্ন ভ্যালু অপ্টিমাইজেশন এই সমস্তটি সংরক্ষণ করে) এবং সি জমিতে ডেটা অনুলিপি সাধারণত স্পষ্টভাবে ঘটে (মাধ্যমে strncpyবা যাই হোক না কেন)।
ট্র্যাভিস গোকেল

@ ট্র্যাভিস গোকেল সংশোধন করার জন্য ধন্যবাদ। আমি পয়েন্টারগুলি ব্যবহার করা হচ্ছে সেই বিষয়টি উল্লেখ করছি, সুতরাং এটি মানগুলি অনুলিপি করছে না, যা ইতিমধ্যে বরাদ্দ ছিল তা ভাগ করে নিচ্ছে। তবে আপনি ঠিক বলেছেন যে সি-তে পাস-বাই-রেফারেন্সটি যথাযথভাবে বলা হয় না এবং জ্ঞানের অন্যান্য দুর্দান্ত নটগুলির জন্যও ধন্যবাদ। আমি ভাষা সম্পর্কে এই ছোট জিনিস শিখতে পছন্দ করি। :)
আরটিএয়ারস্টন

10

Option 1: ইনট এবং স্ট্রিং সহ স্ট্রাক্ট ঘোষণা করুন এবং স্ট্রাক ভেরিয়েবলটি ফিরিয়ে দিন।

Option 2: আপনি দুটির মধ্যে একটিকে পয়েন্টারের মাধ্যমে পাস করতে পারেন এবং পয়েন্টারের মাধ্যমে প্রকৃত প্যারামিটারে পরিবর্তন করতে পারেন এবং অন্যটিকে যথারীতি ফিরে আসতে পারেন:

বা

Option 3: অপশনটির অনুরূপ ২. আপনি উভয়ই পয়েন্টারের মাধ্যমে পাস করতে পারেন এবং ফাংশন থেকে কিছুই ফিরিয়ে দিতে পারেন:


বিকল্প 2 সম্পর্কিত, আপনার স্ট্রিংয়ের দৈর্ঘ্যেও পাস করা উচিত। int fun(char *param, size_t len)
ক্রিস লুটজ

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

7

যেহেতু আপনার ফলাফলের ধরণগুলির মধ্যে একটি স্ট্রিং (এবং আপনি সি ব্যবহার করছেন, সি ++ নয়), সুতরাং আমি পয়েন্টারগুলিকে আউটপুট পরামিতি হিসাবে পাস করার পরামর্শ দিই। ব্যবহার:

এবং এটিকে কল করুন:

সাধারণভাবে, কলিং ফাংশনে বরাদ্দ করতে পছন্দ করুন , ফাংশনের ভিতরেই নয়, যাতে আপনি বিভিন্ন বরাদ্দের কৌশল হিসাবে যতটা সম্ভব উন্মুক্ত হতে পারেন।


6

দুটি ভিন্ন পন্থা:

  1. পয়েন্টার দ্বারা আপনার রিটার্ন মানগুলি পাস করুন, এবং ফাংশনের ভিতরে সেগুলি সংশোধন করুন। আপনি আপনার ফাংশনটিকে অকার্যকর হিসাবে ঘোষণা করেছেন, তবে এটি পয়েন্টার হিসাবে পাস করা মানগুলির মধ্য দিয়ে ফিরে আসছে।
  2. এমন একটি কাঠামো নির্ধারণ করুন যা আপনার ফেরতের মানকে একত্রিত করে।

আমি মনে করি যে # 1 যা চলছে সে সম্পর্কে এটি আরও কিছুটা স্পষ্ট, যদিও আপনার কাছে অনেকগুলি ফেরতের মান থাকলে এটি ক্লান্তিকর হতে পারে। সেক্ষেত্রে বিকল্প # 2 মোটামুটিভাবে ভালভাবে কাজ করে, যদিও এই উদ্দেশ্যে বিশেষায়িত স্ট্রাক্ট তৈরির সাথে কিছু মানসিক ওভারহেড জড়িত রয়েছে।


4
সি এর রেফারেন্স নেই ;-), যদিও পোস্টারটি ব্যবহার করা হয়েছে string, এটি সি ++ ধরে নেওয়া নিরাপদ হতে পারে ...
ট্র্যাভিস গোকেল

পুরোপুরি ভুলে গেছি যে সম্পর্কে! পয়েন্টারগুলি ব্যবহার করার জন্য আমি আমার উত্তরটি পরিবর্তন করেছি, তবে আমি স্পষ্টতই দীর্ঘকাল ধরে সি ++ জমিতে রয়েছি। :)
জেমস থম্পসন

6

একটি কাঠামো তৈরি করুন এবং ভিতরে দুটি মান সেট করুন এবং স্ট্রাক ভেরিয়েবলটি ফিরিয়ে দিন।

char *আপনার প্রোগ্রামের জন্য আপনাকে স্থান বরাদ্দ করতে হবে।


3

আপনার ফাংশন পরামিতি হিসাবে পয়েন্টার ব্যবহার করুন। তারপরে তাদের একাধিক মান ফেরত দিতে ব্যবহার করুন।


2

ফাংশন প্রসঙ্গে পরামিতি পাস করে।

উদাহরণ:

এছাড়াও গ্লোবাল ভেরিয়েবল ব্যবহার করে তবে এটি প্রস্তাবিত নয়।

উদাহরণ:


4
void main(void)ওহ কিভাবে জ্বলছে!
ক্রিস লুটজ

আপনি কি বোঝাতে চেয়েছেন? @ ক্রিস লুটজ
বদর

6
mainএকটি স্থিতি কোড ফেরত দেওয়ার কথা। * নিক্সের অধীনে, এটি হিসাবে ঘোষণা করা আরও স্বাভাবিক usual int main(int argc, char *argv[])আমি বিশ্বাস করি উইন্ডোজের অনুরূপ কনভেনশন রয়েছে।
ডানকান

2

একটি পদ্ধতির ম্যাক্রো ব্যবহার করা হয়। এটি একটি শিরোনাম ফাইলে রাখুনmultitype.h

এটি একটি ফাংশন থেকে চারটি ভেরিয়েবলের কাছে ফিরে আসা এবং চারটি ভেরিয়েবলের জন্য তাদের নির্ধারণ করা সম্ভব করে। উদাহরণ হিসাবে, আপনি এগুলি এগুলি ব্যবহার করতে পারেন:

এটি এটি প্রিন্ট করে:

সমাধানটি পোর্টেবল হিসাবে কার্যকর নাও হতে পারে কারণ এর জন্য ভের্যাডিক ম্যাক্রোগুলির জন্য এবং পরে-বিবৃতি পরিবর্তনশীল ঘোষণার জন্য C99 বা তার পরে প্রয়োজন। তবে আমি মনে করি এটি এখানে পোস্ট করা যথেষ্ট আকর্ষণীয় ছিল। আরেকটি সমস্যা হ'ল সংকলকটি যদি আপনাকে ভুল মান নির্ধারণ করে তবে আপনাকে সতর্ক করবে না, তাই আপনাকে সতর্কতা অবলম্বন করতে হবে।

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


4
একটি বৃহত্তর পোর্টেবিলিটি সমস্যা হ'ল __typeof__
এমএম

টাইপফের পরিবর্তে, আপনি সম্ভবত মাপের ব্যবহার করতে পারেন। রিটার্ন মানগুলির আকার পান এবং এগুলি সমস্ত সংরক্ষণ করার জন্য যথেষ্ট বড় অ্যারে বরাদ্দ করুন। তারপরে আপনি এটি ফেরত দিতে পারেন।
ক্লাস এস
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.