এই 1988 সি কোডটিতে কী ভুল?


94

আমি "দ্য সি প্রোগ্রামিং ল্যাঙ্গুয়েজ" (কে ও আর) বইটি থেকে এই টুকরা কোডটি সংকলনের চেষ্টা করছি। এটি ইউনিক্স প্রোগ্রামের খালি হাড়ের সংস্করণ wc:

#include <stdio.h>

#define IN   1;     /* inside a word */
#define OUT  0;     /* outside a word */

/* count lines, words and characters in input */
main()
{
    int c, nl, nw, nc, state;

    state = OUT;
    nl = nw = nc = 0;
    while ((c = getchar()) != EOF) {
        ++nc;
        if (c == '\n')
            ++nl;
        if (c == ' ' || c == '\n' || c == '\t')
            state = OUT;
        else if (state == OUT) {
            state = IN;
            ++nw;
        }
    }
    printf("%d %d %d\n", nl, nw, nc);
}

এবং আমি নিম্নলিখিত ত্রুটি পাচ্ছি:

$ gcc wc.c 
wc.c: In function ‘main’:
wc.c:18: error: ‘else’ without a previous ‘if’
wc.c:18: error: expected ‘)’ before ‘;’ token

এই বইয়ের ২ য় সংস্করণটি 1988 সালের এবং আমি সি তে বেশ নতুন Maybe

আমি আধুনিক সি কোডটিতে mainফাংশনের একটি আলাদা ব্যবহার দেখেছি :

int main()
{
    /* code */
    return 0;
}

এটি কি নতুন মান বা আমি এখনও কোনও টাইপ-কম প্রধান ব্যবহার করতে পারি?


4
একটি উত্তর না, কিন্তু আরো ঘনিষ্ঠভাবে তাকান কোডের অন্য টুকরা, || c = '\t')। এটি কি এই লাইনের অন্যান্য কোডের মতোই বলে মনে হচ্ছে?
user7116

58
ডিবাগিং + টাইপো প্রশ্নের জন্য 32 টি আপভোট ?!
অরবিট

37
@ তোমালাকগেরিট'কাল: আপনি জানেন, পুরানো জিনিসগুলির মূল্য বেশি (ওয়াইন, পেইন্টিংস, সি কোড)
সেরজিও টুলেন্টসেভ

16
@ কেসার: আমি আমার মতামত প্রকাশের জন্য আমার অধিকারের মধ্যে আছি এবং এটি সেন্সর না করার জন্য আমি আপনাকে ধন্যবাদ জানাব। যেমনটি ঘটে, হ্যাঁ, এটি আপনার কোডটি ডিবাগ করার জন্য এবং আপনার টাইপোগ্রাফিক ত্রুটিগুলি সমাধান করার জন্য কোনও ওয়েবসাইট নয়, এটি "স্থানীয়করণ" সমস্যাগুলি যা অন্য কাউকে কখনও সাহায্য করবে না। এটি প্রোগ্রামিং ভাষা সম্পর্কিত প্রশ্নের জন্য একটি ওয়েবসাইট , আপনার জন্য আপনার বুনিয়াদি ডিবাগিং এবং রেফারেন্স কাজ করার জন্য নয়। দক্ষতার স্তরটি সম্পূর্ণ অপ্রাসঙ্গিক। এফএকিউ এবং সম্ভবত এই মেটা প্রশ্নটি পড়ুন
28-18

11
@ তোমালাকগেরিট'কাল অবশ্যই আপনি আপনার মতামত প্রকাশ করতে পারেন এবং আমি আপনার মতামত সীমাবদ্ধ করতে চাইছি না বিধিবদ্ধ হওয়া সত্ত্বেও। আমি ইতিমধ্যে FAQ পড়েছি। আমি একজন উত্সাহী প্রোগ্রামার যে সত্যিকারের সমস্যার মুখোমুখি হয়েছি
সিজার

উত্তর:


247

আপনার সমস্যাটি আপনার প্রিপ্রসেসর সংজ্ঞা সহ IN এবং OUT:

#define IN   1;     /* inside a word */
#define OUT  0;     /* outside a word */

এইগুলির প্রতিটিতে কীভাবে আপনার পিছনের অর্ধেকলন রয়েছে তা লক্ষ্য করুন। প্রিপ্রোসেসর যখন এগুলি প্রসারিত করে, তখন আপনার কোডটি মোটামুটি দেখতে পাবেন:

    if (c == ' ' || c == '\n' || c == '\t')
        state = 0;; /* <--PROBLEM #1 */
    else if (state == 0;) { /* <--PROBLEM #2 */
        state = 1;;

যে দ্বিতীয় সেমিকোলন কারণ elseif ম্যাচ হিসাবে পূর্বের কোনও কারণ নেই কারণ আপনি ব্রেস ব্যবহার করছেন না। সুতরাং, এর প্রাক প্রসেসর সংজ্ঞা থেকে সেমিকোলন অপসারণ INএবংOUT

এখানে পাঠটি শিখলাম is প্রিপ্রসেসর স্টেটমেন্টগুলির একটি সেমিকোলন দিয়ে শেষ করতে হবে না।

এছাড়াও, আপনার সর্বদা ব্রেস ব্যবহার করা উচিত!

    if (c == ' ' || c == '\n' || c == '\t') {
        state = OUT;
    } else if (state == OUT) {
        state = IN;
        ++nw;
    }

উপরের কোডটিতে কোনও ঝুলন্ত- elseঅস্পষ্টতা নেই ।


8
স্পষ্টতার জন্য, সমস্যাটি ব্যবধান নয়, এটি সেমিকোলন। প্রিপ্রসেসর স্টেটমেন্টে আপনার এগুলির দরকার নেই।
ড্যান

@ স্পষ্টতার জন্য ড্যান ধন্যবাদ! আর সেমিকোলনস আসলেই সমস্যা ছিল! ধন্যবাদ বন্ধুরা!
সিজার

4
@ কেসার: আপনাকে স্বাগতম। ব্র্যাকিং পরামর্শটি আশা করি ভবিষ্যতে আপনাকে সমস্যা থেকে দূরে রাখবে, অবশ্যই আমাকে সহায়তা করেছে!
user7116

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

7
"তাদের দরকার নেই"! = "তাদের থাকা উচিত নয়"। প্রাক্তন সর্বদা সত্য; পরবর্তীটি প্রাসঙ্গিক-নির্ভর এবং এই দৃশ্যে আরও প্রাসঙ্গিক বিষয়।
27:41

63

এই কোডটি নিয়ে মূল সমস্যাটি এটি নয় কে ওআরআর থেকে কোড । এতে ম্যাক্রোস সংজ্ঞাগুলির পরে সেমিকোলনস অন্তর্ভুক্ত রয়েছে, যা বইটিতে উপস্থিত ছিল না, যা অন্যরা যেমন বোঝায় তার অর্থের পরিবর্তনকে নির্দেশ করে।

কোডটি বোঝার চেষ্টায় পরিবর্তন করার পরিবর্তে, আপনি যতক্ষণ না বুঝতে পেরেছেন ততক্ষণ এটিকে একা রেখে দেওয়া উচিত। আপনি যে কোডটি বোঝেন সেটিকে আপনি নিরাপদে পরিবর্তন করতে পারবেন।

এটি সম্ভবত আপনার পক্ষে একটি টাইপো ছিল, তবে প্রোগ্রামিং করার সময় এটি বিশদটি বোঝার এবং মনোযোগ দেওয়ার প্রয়োজনকে চিত্রিত করে।


9
আপনার পরামর্শ কারও কাছে প্রোগ্রাম শিখার পক্ষে মারাত্মকভাবে গঠনমূলক নয়। কোডিং সংশোধন করা ঠিক কীভাবে আপনি প্রোগ্রামিংয়ের বিশদটি বোঝেন।
user7116

12
@ সিকসলেটটারে পরিবর্তনগুলি: এবং এটি করার সময়, আপনার কী পরিবর্তন হয়েছে তা আপনার জানা উচিত এবং খুব কম পরিবর্তনই সম্ভব করা উচিত make ওপি যদি ইচ্ছাকৃতভাবে পরিবর্তনগুলি করত এবং যতটা সম্ভব কম পরিবর্তন করত, তবে সম্ভবত তিনি এই প্রশ্নটি জিজ্ঞাসা করতেন না, কারণ এটি কী তা ঘটছিল তা স্পষ্ট হয়ে যেত। তিনি কোনও ত্রুটি না করেই আইএন এর জন্য ম্যাক্রো পরিবর্তন করে দিতেন এবং তারপরে দুটি ত্রুটি সহ OUT এর জন্য ম্যাক্রো পরিবর্তন করতেন, যার মধ্যে দ্বিতীয়টি হ'ল সেমিকোলন সম্পর্কে অভিযোগ করেছিলেন যা তিনি সবে যুক্ত করেছিলেন।
jmoreno

5
দেখে মনে হচ্ছে প্রিপ্রোসেসর নির্দেশিকা রেখার শেষে আপনি যদি সেমিকোলনটি যুক্ত করার ভুল না করেন তবে আপনি সম্ভবত এটি জানেন না যে আপনি সেগুলি অন্তর্ভুক্ত করবেন না। আপনি এটিকে ফেস ভ্যালুতে নিতে পারেন, আপনি প্রচুর কোড পড়তে পারেন এবং খেয়াল করতে পারেন যে তারা কখনই সেখানে নেই। অথবা, ওপি এগুলিকে অন্তর্ভুক্ত করে বিশৃঙ্খলা করতে পারে, "উদ্ভট" ত্রুটি সম্পর্কে জিজ্ঞাসা করতে পারে এবং এটি জানতে পারে: উফ, প্রিপ্রসেসর নির্দেশিকাগুলির জন্য কোনও সেমিকোলন প্রয়োজন নেই! এটি প্রোগ্রামিং, ভীত সোজা কোনও পর্ব নয়।
user7116

14
@ সিকসলেটটারে পরিবর্তনগুলি: হ্যাঁ, তবে কোডটি কার্যকর না হলে স্পষ্টতই প্রথম পদক্ষেপটি হ'ল "ওহ, ঠিক আছে, তাহলে সি এর উদ্ভাবক দ্বারা একটি বইয়ে লিখিত কোড থেকে আমি কোনও কারণ ছাড়াই যা পরিবর্তন করেছি, সম্ভবত এটি ছিল ইস্যু। আমি তখন এটিকে পূর্বাবস্থায় ফিরিয়ে আনব। "
হালকা ঘোড়দৌড়


34

ম্যাক্রোগুলির পরে কোনও সেমিকোলন হওয়া উচিত নয়,

#define IN   1     /* inside a word */
#define OUT  0     /* outside a word */

এবং এটি সম্ভবত হওয়া উচিত

if (c == ' ' || c == '\n' || c == '\t')

ধন্যবাদ, সেমিকোলনগুলি সমস্যা ছিল। ২ য় এক টাইপ ছিল!
César

21
পরবর্তী সময় দয়া করে সরাসরি আপনার পাঠ্য সম্পাদক থেকে আপনি সঠিক কোডটি ব্যবহার করুন paste
27:41

@ তোমালাকগ্রেট'কাল ভাল আমি করিনি এবং করবো, তবে কীভাবে পেলেন?
একমাচ

4
@ একম্যাচ: আপনি বলেছিলেন যে ;এটি একটি টাইপো যা সমস্যাটিকে প্রভাবিত করে না, যার অর্থ আপনি আসলে যে কোডটি ব্যবহার করেছিলেন তার চেয়ে আপনার প্রশ্নের মধ্যে একটি টাইপো ।
হালকাতা রেস

24

আইএন এবং আউট এর সংজ্ঞাগুলি দেখতে এইরকম হওয়া উচিত:

#define IN   1     /* inside a word  */
#define OUT  0     /* outside a word */

সেমিকোলনগুলি সমস্যা তৈরি করছিল! ব্যাখ্যাটি সহজ: IN এবং OUT উভয়ই প্রিপ্রোসেসর নির্দেশিকা, মূলত সংকলক IN এর সমস্ত উপস্থিতি 1 এবং OUT এর সমস্ত উপস্থিতি সোর্স কোডের সাথে 0 দিয়ে প্রতিস্থাপন করবে।

যেহেতু মূল কোডটিতে 1 এবং 0 এর পরে একটি সেমিকোলন ছিল, যখন আইএন এবং আউট কোডটিতে প্রতিস্থাপন হয়ে উঠেছে, সংখ্যার পরে অতিরিক্ত সেমিকোলনটি অবৈধ কোড তৈরি করেছে, উদাহরণস্বরূপ এই লাইন:

else if (state == OUT)

এই মত দেখতে শেষ হয়েছে:

else if (state == 0;)

তবে আপনি যা চেয়েছিলেন তা হ'ল:

else if (state == 0)

সমাধান: মূল সংজ্ঞাতে সংখ্যার পরে সেমিকোলনটি সরিয়ে ফেলুন।


8

আপনি যেমন দেখছেন ম্যাক্রোতে সমস্যা ছিল।

প্রাক প্রসেসিংয়ের পরে থামার জন্য জিসিসির বিকল্প রয়েছে (-E) প্রাক-প্রক্রিয়াজাতকরণের ফলাফল দেখতে এই বিকল্পটি কার্যকর। আপনি যদি সি / সি ++-তে বড় কোড বেসের সাথে কাজ করে থাকেন তবে প্রযুক্তিটি একটি গুরুত্বপূর্ণ। সাধারণত মেকফাইলগুলির প্রাক-প্রক্রিয়াজাতকরণের পরে থামার লক্ষ্য থাকবে।

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


7

ঠিক কোনও সমস্যা নয়, তবে ঘোষণাটিও main()তারিখযুক্ত, এটি এমন কিছু হওয়া উচিত like

int main(int argc, char** argv) {
    ...
    return 0;
}

সংকলক ডাব্লু / ওয়ান ফাংশনের জন্য একটি পূর্ববর্তী ফেরতের মান ধরে নেবে, এবং আমি নিশ্চিত যে সংকলক / লিঙ্কারটি আর্গ / আর্গভের ঘোষণার অভাব এবং রিটার্ন মানের অভাবকে ঘিরে কাজ করবে তবে তাদের সেখানে থাকা উচিত।


4
এটি একটি ভাল বই - আমি জানি যতদূর সি তে বইয়ের মধ্যে কেবল দুটির মধ্যে একটি। আমি নিশ্চিত যে নতুন সংস্করণগুলি এএনএসআই সি অনুসারে (সম্ভবত সি 99 এএনএসআই সি পূর্ববর্তী)। সি-তে বইয়ের অন্যান্য মূল্যবান হ'ল পিটার ভ্যান ডার লিন্ডেনের বিশেষজ্ঞ সি প্রোগ্রামিং ডিপ সি সিক্রেটস।
বিল

আমি বলেন, এটি ছিল না। আমি কেবল মন্তব্য করেছিলাম যে আজকে যেভাবে জিনিসগুলি করা হচ্ছে তার সাথে সামঞ্জস্য আনতে, সেই মূলটি পরিবর্তন করা উচিত।
বিল

4

কোড ব্লকগুলির চারপাশে সুস্পষ্ট ধনুর্বন্ধনী যুক্ত করার চেষ্টা করুন। কে & R এর শৈলী দ্ব্যর্থক হতে পারে।

18 লাইনটি দেখুন The সংকলকটি সমস্যাটি কোথায় তা আপনাকে বলছে।

    if (c == '\n') {
        ++nl;
    }
    if (c == ' ' || c == '\n' || c == '\t') { // You're missing an "=" here; should be "=="
        state = OUT;
    }
    else if (state == OUT) {
        state = IN;
        ++nw;
    }

4
ধন্যবাদ! আসলে, কোডটি দ্বিতীয়টিতে ধনুর্বন্ধনী ছাড়া কাজ করেছিল যদি :)
সিজার

5
+1 শুধু অস্পষ্ট নয় কিছুটা বিপজ্জনক। পরে (যদি) আপনি যখন আপনার ifব্লকে একটি লাইন যুক্ত করেন, আপনি যদি বন্ধনীগুলি যুক্ত করতে ভুলে যান কারণ আপনার ব্লকটি এখন এক লাইনের বেশি, তবে ত্রুটিটি ডিবাগ করতে কিছুটা সময় নিতে পারে ...
The111

8
@ দ্য 111 আমার সাথে কখনও হয়নি। আমি এখনও বিশ্বাস করি না যে এটি একটি আসল সমস্যা। আমি এক দশকেরও বেশি সময় ধরে ব্রেস-কম স্টাইল ব্যবহার করে আসছি, কোনও ব্লকের দেহের প্রসারণ করার সময় আমি কখনও ধনুর্বন্ধনী যুক্ত করতে ভুলিনি।
কনরাড রুডলফ

4
@ দ্য ১১১: এক্ষেত্রে এটি কয়েকজন এসও অবদানকারীকে কয়েক মিনিট সময় নিয়েছিল: পি এবং আপনি যদি এমন কোনও প্রোগ্রামার হন যে কোনও ধারাতে বিবৃতি যুক্ত করতে সক্ষম হয় ifএবং ব্রেসগুলি আপডেট করতে "ভুলে" যায় তবে ভাল, আপনি না খুব ভাল প্রোগ্রামার।
অরবিটে লাইটনেস রেস

3

একটি সহজ উপায় হ'ল প্রত্যেকটির জন্য {like এর মতো বন্ধনী ব্যবহার করা ifএবং else:

if (c == '\n'){
    ++nl;
}
if (c == ' ' || c == '\n' || c == '\t')
{
    state = OUT;
}
else if (state == OUT) {
    state = IN;
    ++nw;
}

2

অন্যান্য উত্তরগুলি নির্দেশিত হিসাবে, সমস্যাটি রয়েছে #defineএবং সেমিকোলনে রয়েছে। এই সমস্যাগুলি হ্রাস করতে আমি সর্বদা সংখ্যার ধ্রুবককে একটি হিসাবে সংজ্ঞায়িত করতে পছন্দ করি const int:

const int IN = 1;
const int OUT = 0;

এইভাবে আপনি অনেক সমস্যা এবং সম্ভাব্য সমস্যা থেকে মুক্তি পাবেন। এটি মাত্র দুটি জিনিস দ্বারা সীমাবদ্ধ:

  1. আপনার সংকলকটি সমর্থন করতে পারে const- যা 1988 সালে সাধারণত সত্য ছিল না, তবে এখন এটি সমস্ত ব্যবহৃত ব্যবহৃত সংকলক দ্বারা সমর্থিত। (এএফআইকে constসি ++ থেকে "ধার করা" হয়েছে))

  2. আপনি এই ধ্রুবকগুলিকে কিছু বিশেষ জায়গায় ব্যবহার করতে পারবেন না যেখানে আপনার স্ট্রিংয়ের মতো ধ্রুবক প্রয়োজন। তবে আমি মনে করি আপনার প্রোগ্রামটি সে ক্ষেত্রে নয়।


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