এই উত্তরে আমি ধরে নিচ্ছি যে আপনি পাঠ্যের লাইনগুলি পড়ছেন এবং ব্যাখ্যা করছেন । সম্ভবত আপনি ব্যবহারকারীকে অনুরোধ করছেন, যিনি কিছু টাইপ করছেন এবং রিটার্নটিকে হিট করছেন। অথবা সম্ভবত আপনি কোনও প্রকারের ডেটা ফাইল থেকে কাঠামোগত পাঠ্যের লাইনগুলি পড়ছেন।
আপনি যেহেতু পাঠ্যের লাইনগুলি পড়ছেন, তাই আপনার কোডটি একটি লাইব্রেরি ফাংশনটির চারপাশে সংগঠিত করা বোধগম্য হয় যা ভালভাবে পাঠ্যের একটি লাইন পড়ে। স্ট্যান্ডার্ড ফাংশনটি হ'ল fgets()
, যদিও অন্য রয়েছে (সহ getline
)। এবং তারপরে পরবর্তী পদক্ষেপটি হ'ল পাঠ্যের লাইনটি কোনওভাবে ব্যাখ্যা করা।
fgets
পাঠ্যের একটি লাইন পড়তে কল করার জন্য এখানে প্রাথমিক রেসিপি :
char line[512];
printf("type something:\n");
fgets(line, 512, stdin);
printf("you typed: %s", line);
এটি কেবল পাঠ্যের এক লাইনে পড়ে এবং এটি আবার ছাপে। লিখিত হিসাবে এটির বেশ কয়েকটি সীমাবদ্ধতা রয়েছে যা আমরা এক মিনিটের মধ্যেই পেয়ে যাব। এটির একটি খুব দুর্দান্ত বৈশিষ্ট্য রয়েছে: 512 নম্বরটি আমরা দ্বিতীয় যুক্তি হিসাবে পাস করেছি আমরা যে fgets
অ্যারে পড়তে line
বলছি তার আকার
fgets
। এই বাস্তবতা - যে fgets
এটি পড়ার কতটুকু অনুমতি আমরা বলতে পারি - এর অর্থ হ'ল আমরা নিশ্চিত হতে পারি যে fgets
এটিতে বেশি কিছু পড়ে আরে উপচে পড়বে না।
সুতরাং এখন আমরা কীভাবে টেক্সটের একটি লাইন পড়তে জানি, তবে কী যদি আমরা সত্যিই একটি পূর্ণসংখ্যার, বা ভাসমান-পয়েন্ট নম্বর, বা একটি একক অক্ষর, বা একটি শব্দটি পড়তে চাইতাম? (অর্থাৎ, কি যদি
scanf
কল আমরা উন্নত করতে চেষ্টা করছেন একটি বিন্যাসে সুনির্দিষ্টভাবে উল্লেখ করা ব্যবহার ছিল %d
, %f
, %c
বা, %s
?)
পাঠ্যগুলির একটি লাইন - একটি স্ট্রিং - এই যে কোনও একটি বিষয় হিসাবে এটি ব্যাখ্যা করা সহজ। একটি পূর্ণসংখ্যা সবচেয়ে সহজ (যদিও অপূর্ণ) পথ একে ডাকতে কি করতে একটি স্ট্রিং রূপান্তর করতে, atoi()
। একটি ভাসমান-পয়েন্ট নম্বর রূপান্তর করতে, আছে atof()
। (এবং আরও ভাল উপায় রয়েছে, যেমনটি আমরা এক মিনিটের মধ্যে দেখতে পাব)) এখানে একটি খুব সহজ উদাহরণ রয়েছে:
printf("type an integer:\n");
fgets(line, 512, stdin);
int i = atoi(line);
printf("type a floating-point number:\n");
fgets(line, 512, stdin);
float f = atof(line);
printf("you typed %d and %f\n", i, f);
আপনি যদি ব্যবহারকারীকে একটি অক্ষর টাইপ করতে চান (সম্ভবত y
বা
n
হ্যাঁ / কোনও প্রতিক্রিয়া হিসাবে), আপনি আক্ষরিকভাবে কেবল লাইনের প্রথম অক্ষরটি ধরে নিতে পারেন:
printf("type a character:\n");
fgets(line, 512, stdin);
char c = line[0];
printf("you typed %c\n", c);
(এটি অবশ্যই ব্যবহারকারী একাধিক-চরিত্রের প্রতিক্রিয়া টাইপ করে এমন সম্ভাবনা উপেক্ষা করে; এটি টাইপ করা কোনও অতিরিক্ত অক্ষর চুপচাপ উপেক্ষা করে))
অবশেষে, আপনি যদি ইনপুট লাইনের চিকিত্সা করতে চান তবে ব্যবহারকারীর স্পষ্টভাবে স্পেস না থাকা একটি স্ট্রিং টাইপ করতে চাইলে
hello world!
স্ট্রিংটি "hello"
অন্য কোনও কিছু অনুসরণ করেছিল (যা scanf
ফর্ম্যাটটি এটিই %s
করত), ভাল, সেই ক্ষেত্রে আমি কিছুটা ফাইব্বড করেছিলাম, লাইনটিকে সেভাবে পুনরায় ব্যাখ্যা করা এত সহজ নয়, সুতরাং, তার উত্তরটি প্রশ্নের অংশটি কিছুটা অপেক্ষা করতে হবে।
তবে প্রথমে আমি তিনটি জিনিস ফিরে যেতে চাই I
(1) আমরা কল করছি
fgets(line, 512, stdin);
অ্যারেতে পড়তে line
, এবং যেখানে 512 অ্যারের আকার line
তাই fgets
এটি প্রবাহিত করতে না জানে। তবে এটি নিশ্চিত করতে যে 512 সঠিক নম্বর (বিশেষত, কেউ আকার পরিবর্তন করার জন্য প্রোগ্রামটি টুইট করেছে কিনা তা খতিয়ে দেখার জন্য), আপনাকে যেখানে line
ঘোষণা করা হয়েছিল সেখানে ফিরে যেতে হবে । এটি একটি উপদ্রব, সুতরাং আকারগুলি সিঙ্কে রাখার জন্য আরও দুটি আরও ভাল উপায়। আপনি (ক) আকারের জন্য একটি নাম তৈরি করতে প্রিপ্রসেসর ব্যবহার করতে পারেন:
#define MAXLINE 512
char line[MAXLINE];
fgets(line, MAXLINE, stdin);
অথবা, (খ) সি এর sizeof
অপারেটর ব্যবহার করুন :
fgets(line, sizeof(line), stdin);
(২) দ্বিতীয় সমস্যাটি হ'ল আমরা ত্রুটির জন্য যাচাই করিনি। আপনি যখন ইনপুটটি পড়ছেন, আপনার সর্বদা ত্রুটির সম্ভাবনা যাচাই করা উচিত । যদি কোনও কারণে fgets
আপনি পাঠ্যর রেখাটি পড়তে না চাইতে পারেন তবে এটি নাল পয়েন্টারটি ফিরিয়ে দিয়ে বোঝায়। সুতরাং আমাদের মত জিনিস করা উচিত ছিল
printf("type something:\n");
if(fgets(line, 512, stdin) == NULL) {
printf("Well, never mind, then.\n");
exit(1);
}
শেষ fgets
অবধি , এখানে একটি সমস্যা আছে যে পাঠ্যগুলির একটি লাইন পড়ার জন্য,
অক্ষরগুলি পড়ে এবং আপনার অ্যারে পূরণ করে যতক্ষণ না এটি \n
লাইনটি বন্ধ করে এমন অক্ষর খুঁজে না পায় এবং এটি \n
অক্ষরটি আপনার অ্যারেতেও পূরণ করে । আপনি যদি আমাদের আগের উদাহরণটি সামান্য পরিবর্তন করেন তবে আপনি এটি দেখতে পারেন:
printf("you typed: \"%s\"\n", line);
আমি যদি এটি চালিয়ে থাকি এবং যখন আমাকে জিজ্ঞাসা করে তখন "স্টিভ" টাইপ করুন, এটি প্রিন্ট করে
you typed: "Steve
"
যে "
দ্বিতীয় লাইন উপর কারণ স্ট্রিং এটা পড়তে এবং ফিরে মুদ্রিত আউট আসলে ছিল "Steve\n"
।
কখনও কখনও সেই অতিরিক্ত নিউলাইনটি কোনও ব্যাপার না (যেমনটি আমরা যখন ফোন করেছি
atoi
বা atof
যেহেতু তারা উভয়ই সংখ্যার পরে কোনও অতিরিক্ত অ-সংখ্যাসূচক ইনপুট উপেক্ষা করে) তবে মাঝে মাঝে এটি অনেকটাই গুরুত্বপূর্ণ। তাই প্রায়শই আমরা সেই নতুন লাইনটি বন্ধ করতে চাই। এটি করার বিভিন্ন উপায় রয়েছে যা আমি এক মিনিটেই পেয়ে যাব। (আমি জানি আমি এটি অনেক কিছু বলেছি But তবে আমি প্রতিশ্রুতি দিয়েছি those সমস্ত জিনিস আবার ফিরে পাব))
এই মুহুর্তে, আপনি চিন্তা হতে পারে: "আমার মনে হল তুমি বলেছিলে scanf
কোন ভাল ছিল, এবং এই অন্যান্য উপায় এত ভাল হবে কিন্তু। fgets
একটি উত্পাত মত চেহারা শুরু হয় কলিং। scanf
ছিল এত সহজ আমি এটা ব্যবহার করা চালিয়ে যাবে না? "
অবশ্যই, আপনি চাইলে ব্যবহার চালিয়ে scanf
যেতে পারেন। (এবং সত্যিকারের
সরল জিনিসের জন্য, কিছু উপায়ে এটি সহজ) প্রত্যাশা করেনি, বা যখন আপনি আরও জটিল কিছু করতে এটি কীভাবে ব্যবহার করতে পারেন তা বুঝতে পারেন না। এবং আসুন fgets
আসল উপদ্রবগুলি একবার দেখে নিই :
আপনাকে সর্বদা অ্যারের আকার নির্দিষ্ট করতে হবে। ঠিক আছে, অবশ্যই এটি কোনও উপদ্রব নয় - এটি একটি বৈশিষ্ট্য, কারণ বাফার ওভারফ্লো একটি সত্যই খারাপ জিনিস।
আপনাকে ফেরতের মানটি পরীক্ষা করতে হবে। প্রকৃতপক্ষে, এটি একটি ধোয়া, কারণ scanf
সঠিকভাবে ব্যবহার করতে গেলে আপনাকে এর রিটার্নের মানটিও পরীক্ষা করতে হবে।
আপনাকে \n
পিছনে খুলে ফেলতে হবে। এটি, আমি স্বীকার করি, একটি সত্য উপদ্রব। আমি চাই যে কোনও স্ট্যান্ডার্ড ফাংশন ছিল আমি আপনাকে এটি চিহ্নিত করতে পারতাম যে এই সামান্য সমস্যা ছিল না। (দয়া করে কেউই সামনে আনবেন না gets
)) তবে scanf's
১ different টি ভিন্ন উপদ্রবের তুলনায় আমি যে fgets
কোনও দিনের এই উপদ্রবটি গ্রহণ করব ।
তাহলে আপনি কীভাবে নতুন লাইনের স্ট্রিপ করবেন ? তিনটি উপায়:
(ক) সুস্পষ্ট উপায়:
char *p = strchr(line, '\n');
if(p != NULL) *p = '\0';
(খ) কৌতুকপূর্ণ এবং কমপ্যাক্ট উপায়:
strtok(line, "\n");
দুর্ভাগ্যক্রমে এটি সর্বদা কাজ করে না।
(গ) আরেকটি কমপ্যাক্ট এবং হালকা অস্পষ্ট উপায়:
line[strcspn(line, "\n")] = '\0';
এর অসম্পূর্ণতা: এবং এখন যে যে ভাবে বাইরে, আমরা ফিরে অন্য জিনিস আমি উপর এড়ানো পেতে পারেন atoi()
এবং atof()
। এগুলির সাথে সমস্যা হ'ল এগুলি আপনাকে সাফল্য বা ব্যর্থতার সাফল্যের কোনও কার্যকর ইঙ্গিত দেয় না: তারা চুপচাপ অনুন্নত সংখ্যাসূচক ইনপুটটি উপেক্ষা করে এবং তারা যদি চূড়ান্তভাবে 0 সংখ্যার ইনপুট না থাকে তবে 0 করে ফিরে আসে। পছন্দের বিকল্পগুলি - যার কয়েকটি অন্যান্য সুবিধাও রয়েছে - strtol
এবং তা strtod
।
strtol
এছাড়াও আপনাকে 10 ব্যতীত একটি বেস ব্যবহার করতে দেয় যার অর্থ আপনি (অন্যান্য জিনিসের মধ্যে) এর সাথে %o
বা এর %x
সাথে পেতে পারেনscanf
। তবে কীভাবে এই ফাংশনগুলি সঠিকভাবে ব্যবহার করতে হবে তা দেখানো একটি গল্প এবং এটি ইতিমধ্যে একটি সুন্দর খণ্ডিত গল্পে রূপান্তরিত হওয়া থেকে খুব বেশি বিচ্যুতি হবে, তাই আমি এখন সেগুলি সম্পর্কে আরও কিছু বলব না।
বাকি মূল বিবরণ সংক্রান্ত উদ্বেগ ইনপুটটি আপনি সম্ভবত একটি একক সংখ্যা বা চরিত্রের চেয়ে জটিল যেটিকে বিশ্লেষণের চেষ্টা করছেন। আপনি যদি দুটি সংখ্যা, বা একাধিক শ্বেত স্পেস-পৃথক শব্দ, বা নির্দিষ্ট ফ্রেমিং বিরামচিহ্ন যুক্ত একটি লাইন পড়তে চান? এটিই জিনিসগুলি আকর্ষণীয় হয়ে উঠেছে scanf
, এবং আপনি যদি জিনিসগুলি ব্যবহার করার চেষ্টা করছেন তবে জিনিসগুলি সম্ভবত জটিল হয়ে উঠছিল এবং যেখানে এখন আরও অনেক বিকল্প রয়েছে যে আপনি পরিষ্কারভাবে একটি পাঠ্য ব্যবহার করে পাঠ্য পাঠ করেছেন fgets
, যদিও এই সমস্ত বিকল্পগুলির সম্পূর্ণ গল্প সম্ভবত কোনও বই পূরণ করতে পারে, তাই আমরা কেবল এখানে পৃষ্ঠটি স্ক্র্যাচ করতে সক্ষম হব।
আমার প্রিয় কৌশলটি হ'ল স্পেস-স্পেস-বিচ্ছিন্ন "শব্দের" বিভক্ত করা, তারপরে প্রতিটি "শব্দ" দিয়ে আরও কিছু করা। এটি করার জন্য একটি প্রধান স্ট্যান্ডার্ড ফাংশন
strtok
(এটিতে এর সমস্যাগুলিও রয়েছে এবং এটি সম্পূর্ণ পৃথক আলোচনাকেও রেট দেয়)। আমার নিজস্ব পছন্দগুলি প্রতিটি ভাঙা-বিচ্ছিন্ন "শব্দ" -এর জন্য পয়েন্টারগুলির একটি অ্যারে তৈরির জন্য একটি উত্সর্গীকৃত ফাংশন, আমি এই কোর্স নোটগুলিতে বর্ণনা করি এমন একটি ফাংশন
। যে কোনও হারে, একবার আপনি "শব্দ" পেয়ে গেলে আপনি প্রতিটিটিকে আরও প্রক্রিয়া করতে পারেন, সম্ভবত
আমরা ইতিমধ্যে দেখেছি একই atoi
/ atof
/ strtol
/ strtod
ফাংশনগুলির সাথে।
স্ববিরোধী মনে হলেও এটা, যদিও আমরা figuring আউট কিভাবে থেকে দূরে সরাতে সময় ও শ্রম এখান থেকে ন্যায্য পরিমাণ খরচ করে থাকেন scanf
আমরা শুধু সঙ্গে পড়া লেখার লাইন দিয়ে মোকাবেলা করতে আরেকটি চমৎকার উপায়
fgets
এটা পাস হয় sscanf
। এইভাবে, আপনি বেশিরভাগ সুবিধার সাথে শেষ করেন scanf
তবে বেশিরভাগ অসুবিধা ছাড়াই।
যদি আপনার ইনপুট সিনট্যাক্সটি বিশেষ জটিল হয় তবে এটি পার্স করার জন্য একটি "রেজিএক্সএক্স" লাইব্রেরি ব্যবহার করা উপযুক্ত হবে।
অবশেষে, আপনি যে উপযুক্ত অ্যাডহক পার্সিং সলিউশনগুলির জন্য উপযুক্ত তা ব্যবহার করতে পারেন । আপনি char *
যে অক্ষরের প্রত্যাশা করেছেন তার জন্য পয়েন্টার চেক করে আপনি একবারে একটি অক্ষরেখার মধ্য দিয়ে যেতে
পারেন। অথবা আপনি ফাংশন ব্যবহার করে নির্দিষ্ট অক্ষরের জন্য অনুসন্ধান করতে পারেন পছন্দ strchr
বা strrchr
, বা strspn
বা strcspn
বা strpbrk
। অথবা আমরা পূর্বে যে এড়িয়ে গেছি strtol
বা
strtod
ফাংশনগুলি ব্যবহার করে ডিজিটাল অক্ষরের গোষ্ঠীগুলি বিশ্লেষণ / রূপান্তর করতে এবং এড়িয়ে যেতে পারি।
স্পষ্টতই আরও অনেক কিছু বলা যেতে পারে, তবে আশা করি এই ভূমিকা আপনাকে শুরু করবে।
(r = sscanf("1 2 junk", "%d%d", &x, &y)) != 2
অনুভূমিক অ-সংখ্যাযুক্ত পাঠ্যকে খারাপ হিসাবে সনাক্ত করে না।