Advertisement
If you have a new account but are having problems posting or verifying your account, please email us on hello@boards.ie for help. Thanks :)
Hello all! Please ensure that you are posting a new thread or question in the appropriate forum. The Feedback forum is overwhelmed with questions that are having to be moved elsewhere. If you need help to verify your account contact hello@boards.ie

Program to read numbers from a file and say if they are prime

Options
  • 11-11-2011 12:39pm
    #1
    Closed Accounts Posts: 95 ✭✭


    This program is designed to read a list of numbers from a file and then decide if they are prime or not.

    I think one issue may be that its not reading the numbers correctly. Is it reading them as characters and I have to do that weird maths converting them from chars to ints.

    Is my logic even remotely correct?
    #include<stdio.h> 
    int main()
    {
    FILE *fp;
    int numbers[6];
    int count=0;
    char fname[80];
    printf("Please enter the name of the file you wish to print: ");
    gets(fname);
    fp=fopen (fname, "r");
    printf("The contents of the file <%s> are:\n", fname);
    	while (count<6)
    	{
    	fgets:("%d", numbers [count]);
    	count++;
    	}
    count=0;
    int isprime=2;
    	while(count<6)
    	{ while(isprime<=numbers[count])
    	if(numbers[count]%isprime==0)
    	break;
    	isprime++;
    	if(isprime==numbers[count])
    	printf("\n%d is Prime",numbers);
    	count++;
    	}
    
    
    return 0;
    }
    

    Why is C so hard :(:(:(:(:(:(:(:(:(:(


Comments

  • Registered Users Posts: 669 ✭✭✭whatstherush


    Have you tried debugging it so you can follow your logic. If you don't know how to debug(I know no one in my course ever showed me) let me know and I'll try and give you a crash course.
    P.s. haven't a clue if your code is right, haven't used C in years.


  • Closed Accounts Posts: 95 ✭✭The Crab


    Have you tried debugging it so you can follow your logic. If you don't know how to debug(I know no one in my course ever showed me) let me know and I'll try and give you a crash course.
    P.s. haven't a clue if your code is right, haven't used C in years.

    No, they didn't show us how to debug? Is it easy?


  • Registered Users Posts: 669 ✭✭✭whatstherush


    The Crab wrote: »
    No, they didn't show us how to debug? Is it easy?
    Like everything, yes once you know how.

    So basically debugging allows you to step through each line of code, and examine the route your code takes and see what variables change to as you progress through the code.

    Now some of this might be different depending on the IDE(what you are using to compile/develop the program), but I think the shortcuts are fairly standard across IDE's.

    First thing to do is set a break point.
    You can do this by clicking in the left hand margin just to the left of your code.
    You should see a red dot appear. This signifies where the debugger will stop when its running your code. I would suggest the first printf line in your sample.

    Next you need to run your code in debug mode. Usually there is a green forward arrow icon along the top somewhere, this should kick you off in debug mode. F5 is usually the shortcut.

    Next you should see the line you put the break point on highlighted in yellow.
    You should also see some new windows at the bottom of your IDE such as Locals and Watch. The locals window should contain all the variables you declared in your program as fp, numbers, count etc..

    You can now start stepping through your code.
    There are three types of step you can do, step over, step into, step out.
    For your example all we need is step over. There should be a step over icon somewhere along the top of you ide, if you can't find it hover over each icon and the tool tip should tell you. F10 is usually the shortcut.

    So when you hit the step over button/F10 you should see the yellow highlighting move to the next line. Keep pressing stepping over and you should see the path through you code. Keep an eye on the locals window to see how the values in your variables change.

    Hope this helps, if you don't get it, definitely get a tutor or someone to give ya quick example cause it will save you years of heart ache.


  • Closed Accounts Posts: 95 ✭✭The Crab


    Like everything, yes once you know how.

    So basically debugging allows you to step through each line of code, and examine the route your code takes and see what variables change to as you progress through the code.

    Now some of this might be different depending on the IDE(what you are using to compile/develop the program), but I think the shortcuts are fairly standard across IDE's.

    First thing to do is set a break point.
    You can do this by clicking in the left hand margin just to the left of your code.
    You should see a red dot appear. This signifies where the debugger will stop when its running your code. I would suggest the first printf line in your sample.

    Next you need to run your code in debug mode. Usually there is a green forward arrow icon along the top somewhere, this should kick you off in debug mode. F5 is usually the shortcut.

    Next you should see the line you put the break point on highlighted in yellow.
    You should also see some new windows at the button of your IDE such as Locals and Watch. The locals window should contain all the variables you declared in your program as fp, numbers, count etc..

    You can now start stepping through your code.
    There are three types of step you can do, step over, step into, step out.
    For your example all we need is step over. There should be a step over icon somewhere along the top of you ide, if you can't find it hover over each icon and the tool tip should tell you. F10 is usually the shortcut.

    So when you hit the step over button/F10 you should see the yellow highlighting move to the next line. Keep pressing stepping over and you should see the path through you code. Keep an eye on the locals window to see how the values in your variables change.

    Hope this helps, if you don't get it, definitely get a tutor or someone to give ya quick example cause it will save you years of heart ache.

    Thanks, I'll have a check. Can't vouch for my lecturer showing me though, he doesn't really like to help too much. But with a bit of self-effort and your advice I hope to be able to figure it out.


  • Registered Users Posts: 1,226 ✭✭✭carveone


    Why is C so hard :(:(:(:(:(:(:(:(:(:(

    The C you've done so far is pretty straightforward, you haven't hit any subtleties yet. When writing any program you are better off deciding how the program should flow logically and then writing the code to match. A lot of algorithms are written in a kind of pseudocode where it's obvious what's going on but the code isn't valid.

    For example, the old "Data Structures and Algorithms" book is written in a Pascal like form but it's trivial to write the C to match.

    Looking at your code for a second....

    First, don't use the gets() call - it's the call of Satan it really is. Just don't head down that path now and you won't have to regret it later! It's not a big deal now. I'm referring to lack of boundary checks:

    You expect the input "foo". The user types "supercalifragalisticexpealidocious". Bang!

    You can use "fgets(buffer, 80, stdin);" instead, where 80 is the size of your buffer.
    fgets:("%d", numbers [count]);
    

    You're mixing all sorts of calls together on that one. Either use fscanf or fgets, not both! fscanf is a little complex to use if you have input that isn't precise - I have a tendency to use fgets(string, length, stream), and then clean up the line and pass it to strtol().

    Have a go at using fscanf() first and see can you output the numbers you've read in. That's the hard bit. THEN figure out if they're prime.

    You should be able to use something like:

    fscanf (fp, "%d", &result);

    Note the & before result. That's your introduction to pointers (evil laugh).

    Have a go...


  • Advertisement
  • Registered Users Posts: 1,226 ✭✭✭carveone


    I should add that fscanf gives me a headache sometimes when it comes to the line feed at the end of each line. So fscanf(fp, "%d", &result); will work for the first number and then the next read is spaces or a line feed and it'll fall over. Pain in the face.

    I've a tendency to use fgets, check that, then use sscanf to scan it. At least I don't go mad that way :)

    Get in the habit of using #defines, that way you don't have to remember what number you used where:
    #define LINE_MAX 80
    
    char line[LINE_MAX];
    ...
    while (fgets(line, LINE_MAX, fp) != NULL)
    {
        ret = sscanf(line, "%d", &result);
    
        if (ret != 1) /* ie: 1 integer read successfully */
            .... oops ...
    
        printf("Read an integer: %d\n", result);
    }
    
    Have a go with that ....


  • Registered Users Posts: 2,024 ✭✭✭Colonel Panic


    I know #defines are common in C, but I hate seeing them! In your .c file, you could do something like this...
    int const kLineMax = 80;
    


  • Registered Users Posts: 1,226 ✭✭✭carveone


    Or "const int" even!

    Or enum which is practically the same as #define with extra semantics. It's a common alternative to #define for int.

    enum { LINE_MAX = 80 };

    Note that C is not C++. A "const int" is not a "constant integer expression" in C, as it would be in C++. So you can't use it in some places (e.g. a case statement).

    Subtle, huh. C is a razor sharp language like that. Easy to cut yourself :)


  • Registered Users Posts: 2,024 ✭✭✭Colonel Panic


    I'd better get a plaster!

    The int const is just a habit I have, tend to read the type from right to left!


  • Registered Users Posts: 1,226 ✭✭✭carveone


    I always need to scratch my head a bit on those!

    I wasn't correcting you there, just being a little puzzled at the different usage. Which is right of course.

    const int and int const are the same but put in a * and things change.

    const char * and all that.

    The OP must be pretty confused at this point :p

    Edit: Before you say it: const char *p, char const *p are exactly the same. I obviously need caffeine.


  • Advertisement
  • Registered Users Posts: 2,024 ✭✭✭Colonel Panic


    No worries, there's definitely a lot of subtle things about C that are easy to forget! I learned something new today regarding the const keyword in C!

    C is still worth learning OP! :D


  • Registered Users Posts: 1,226 ✭✭✭carveone


    As did I!

    I didn't know that you could go "int const" and it reads better that way I guess. I learned C a long long time ago in a galaxy far far away and am a bit set in my ways now.

    Just in case the OP is totally confused, the original point was that in C++ you can do this (I think!):
    const int n = 5;
    int a[n];
    

    In C you cannot. You have to use a define or an enum.


  • Registered Users Posts: 1,922 ✭✭✭fergalr


    The Crab wrote: »
    This program is designed to read a list of numbers from a file and then decide if they are prime or not.

    I think one issue may be that its not reading the numbers correctly. Is it reading them as characters and I have to do that weird maths converting them from chars to ints.

    Is my logic even remotely correct?
    #include<stdio.h> 
    int main()
    {
    FILE *fp;
    int numbers[6];
    int count=0;
    char fname[80];
    printf("Please enter the name of the file you wish to print: ");
    gets(fname);
    fp=fopen (fname, "r");
    printf("The contents of the file <%s> are:\n", fname);
    	while (count<6)
    	{
    	fgets:("%d", numbers [count]);
    	count++;
    	}
    count=0;
    int isprime=2;
    	while(count<6)
    	{ while(isprime<=numbers[count])
    	if(numbers[count]%isprime==0)
    	break;
    	isprime++;
    	if(isprime==numbers[count])
    	printf("\n%d is Prime",numbers);
    	count++;
    	}
    
    
    return 0;
    }
    

    Why is C so hard :(:(:(:(:(:(:(:(:(:(

    Does that code even terminate?
    while(isprime<=numbers[count])
    	if(numbers[count]%isprime==0)
    	break;
    
    Unless "numbers[count]%isprime" is 0, that code is going to run forever, right? It looks like you've forgot to add braces, for the body of that while loop?

    You need to go slower.
    Test each piece, and make sure each piece does what you think, before adding complexity.

    Make your code neat, and nicely formatted.
    Given variables names that make sense.
    'isprime' is a bad name for that variable. What does that variable do? Why dont you name it, according to what it does?
    Indent your code so that the structure of the code is obvious from looking at it.
    Write down the algorithm in english first, then in something like the code, and then eventually, write it, piece by piece, in C, testing each piece.

    You must move in a careful and disciplined manner, or it'll be very hard to manage the complexity.


  • Registered Users Posts: 1,922 ✭✭✭fergalr


    I know #defines are common in C, but I hate seeing them! In your .c file, you could do something like this...
    int const kLineMax = 80;
    

    Why? Surely defines are completely appropriate to these sort of small size mathematical C programs?


  • Registered Users Posts: 1,922 ✭✭✭fergalr


    Have you tried debugging it so you can follow your logic. If you don't know how to debug(I know no one in my course ever showed me) let me know and I'll try and give you a crash course.
    P.s. haven't a clue if your code is right, haven't used C in years.
    The Crab wrote: »
    No, they didn't show us how to debug? Is it easy?

    I disagree with 'whatstherush' here.
    I don't think you should go near a debugger.

    I think using a debugger will just encourage you to write code without understanding, up front, what the code does.

    It can be beneficial to use a debugger to see how the program traces through the code; but only if you've first got a simple, clean, mental model of what specific coding constructs do.

    I think you should spend your time writing and testing smaller parts of your program, piece by piece, being confident that when you add the pieces together, that they'll work.

    I think debuggers are a tool better kept for more advanced use; if you start using them too soon, you can get into the habit of writing programs by band-aiding the bits that don't do what you think; whereas you should be focusing on trying to structure them correctly from the start.


  • Registered Users Posts: 669 ✭✭✭whatstherush


    fergalr wrote: »
    I think using a debugger will just encourage you to write code without understanding, up front, what the code does.
    Funny cause thats exactly what the Crab has done without ever going near a debugger.


  • Closed Accounts Posts: 95 ✭✭The Crab


    I don't disagree with either of you. The intense level of work on this module is doing just that, making us attempt stuff that we don't have a clue about. Shame, because my other modules are really good. At this stage I'm kind of resolved to try to do my best and if I can at least pass then that's great, then teach it to myself once the course is finished.


  • Registered Users Posts: 2,024 ✭✭✭Colonel Panic


    There's always going to be a large degree of teaching yourself with programming. While a lot of it is about algorithms and language syntax, it's really up to you to "get it" and I don't think it's something that can be fully taught, regardless of the quality of a course and lecturers or lack thereof.

    Keep at it, and learn how to debug, nothing can beat stepping through code to actually *get* stuff.


  • Registered Users Posts: 7,231 ✭✭✭Fad


    The Crab wrote: »
    I don't disagree with either of you. The intense level of work on this module is doing just that, making us attempt stuff that we don't have a clue about. Shame, because my other modules are really good. At this stage I'm kind of resolved to try to do my best and if I can at least pass then that's great, then teach it to myself once the course is finished.

    Wait til you get to 3rd year (I'm assuming you're in UCD from comments you've made), you'll laugh at your current workload. I have about 3 modules with that amount of work <3, one of them with very heavy theory.

    (I have heard that that particular lecturer is kinda awful, but getting a book will help)


  • Closed Accounts Posts: 95 ✭✭The Crab


    Fad wrote: »
    Wait til you get to 3rd year (I'm assuming you're in UCD from comments you've made), you'll laugh at your current workload. I have about 3 modules with that amount of work <3, one of them with very heavy theory.

    (I have heard that that particular lecturer is kinda awful, but getting a book will help)

    I sent you a pm just to check your thoughts on one or two things.


  • Advertisement
  • Registered Users Posts: 9,579 ✭✭✭Webmonkey


    Fad wrote: »
    Wait til you get to 3rd year (I'm assuming you're in UCD from comments you've made), you'll laugh at your current workload. I have about 3 modules with that amount of work <3, one of them with very heavy theory.

    (I have heard that that particular lecturer is kinda awful, but getting a book will help)
    Wait until you are in 4th year :D... wait until you are in industry with deadlines :pac:


  • Registered Users Posts: 7,231 ✭✭✭Fad


    Webmonkey wrote: »
    Wait until you are in 4th year :D... wait until you are in industry with deadlines :pac:

    Oh I'm under no illusion, although industry wont be as bad, I sleep, I eat, and I go to college, little or no craic is had..... (In or out of college, my life revolves around it entirely atm)


  • Registered Users Posts: 1,311 ✭✭✭Procasinator


    I've pretty-printed your code. If you get into the habit of having a consistent indention method for blocks, you'll be able to spot bugs much quicker.
    #include<stdio.h>
    int main()
    {
        FILE *fp;
        int numbers[6];
        int count=0;
        char fname[80];
        printf("Please enter the name of the file you wish to print: ");
        gets(fname);
        fp=fopen (fname, "r");
        printf("The contents of the file <%s> are:\n", fname);
        while (count<6)
        {
            fgets:("%d", numbers [count]);
            count++;
        }
        count=0;
        int isprime=2;
        while(count<6)
        { while(isprime<=numbers[count])
            if(numbers[count]%isprime==0)
            break;
            isprime++;
            if(isprime==numbers[count])
            printf("\n%d is Prime",numbers);
            count++;
        }
        
        
        return 0;
    }
    

    I assume fgets:( is meant to be fgets(.

    As mentioned by fergalr too, this while:
    while(isprime<=numbers[count])
            if(numbers[count]%isprime==0)
            break;
    

    Is going to cause pain as it will be infinite in all cases but where the number is divisible. Let's fix those 2 issues, and use some more braces and newlines:
    #include<stdio.h>
    int main()
    {
        FILE *fp;
        int numbers[6];
        int count=0;
        char fname[80];
        printf("Please enter the name of the file you wish to print: ");
        gets(fname);
        fp=fopen (fname, "r");
        printf("The contents of the file <%s> are:\n", fname);
        while (count<6)
        {
            fgets("%d", numbers [count]);
            count++;
        }
        count=0;
        int isprime=2;
        while(count<6)
        { 
    		while(isprime<=numbers[count])
    		{
    			if(numbers[count]%isprime==0)
    			{
    				break;
    			}
    			
    			isprime++;
    			if(isprime==numbers[count])
    			printf("\n%d is Prime",numbers);
    		}
    		count++;
        }
        
        
        return 0;
    }
    

    That looks a bit better. But it still won't work.

    There are 2 problems I can see straight away. I won't tell you the fix, but I'll explain the weird behaviour.

    if (isprime == numbers[count]) currently will never evaluate to true, as for the cases where it would be true, it never gets executed. Hint: x % x == 0. As in, 2 % 2 == 0.

    If I have the following numbers { 6, 5, 4, 7, 3, 2}, 6 will have 6 iterations of the inner while (where the prime is checked). 5, 4, 6, 3, and 2 will have 0 iterations. 7 will get one check, but due mention of above, will not be marked as a prime. Hint: what will isprime be set to when the inner-while finishes the first time, and when it enters for the next count.

    There are some optimisations you could do too (no need to loop up to n, for instance), but we'll leave them out for the moment.

    (Note: Haven't tried compiling and running your code, so it's all mind-debugging. There could be more or less problems than I've listed).


  • Registered Users Posts: 1,922 ✭✭✭fergalr


    The Crab wrote: »
    I don't disagree with either of you. The intense level of work on this module is doing just that, making us attempt stuff that we don't have a clue about.

    This is a personal opinion, but a lot of best college courses I did, made me attempt stuff I didn't have a clue about.
    They taught me how to start from knowing almost nothing about a problem, and manage to get to a stage where I could solve the problem. Probably the most valuable set of skills I learned in college, despite being very intimidating at the time.

    I understand that won't seem like very helpful advice at the moment, but I just wanted to say that its not necessary a waste of your time, even though it might feel tough at the moment.
    The Crab wrote: »
    Shame, because my other modules are really good. At this stage I'm kind of resolved to try to do my best and if I can at least pass then that's great, then teach it to myself once the course is finished.

    I want to give you what I think is an important piece of advice, here: thats often a very wrong decision to make, in a programming course.

    I think I know why you'd be tempted to say that you'll teach it to yourself, afterwards - if you are doing a programming course, and fall behind, it gets very hard to catch up with the material. Each piece builds on the last piece, and if the earlier pieces are ropey, it starts to get tough. Too many different things going on, too many separate parts to keep track of...

    There's a big temptation at that point, to just try and muddle through assignments - to sort of bodge things together, not really understanding whats going on, and try and come back afterwards and sort it out.

    But that's almost never the right answer.
    If you are getting stuck, its almost always better to go back a few chapters, and get comfortable with the basics, before moving on.

    The program you are trying to write, there, is quite a complex program, for a beginner.

    You have several different loops, that don't quite do what you intend, and a lot of different things going on.

    So, I'd say, back up a bit. Take each small construct that you use, and look at it separately. Play with it, and get them working in isolation, before trying to put them together.


    So, for example, don't start off by reading a list of numbers from a file, and telling whether each is prime.

    Start off by writing a program that reads a list of numbers from a file, and prints them out.

    Once you've that working properly, and understood, then write a separate program that tells you whether a single number is prime or not.

    Once its working, and you've understood it properly, then maybe put them together.


    Even writing a program that tells whether a number is prime or not, might be too big to start with. Maybe you even want to break it down further.


    Programming is all about breaking things down into little bits, that we can understand properly, and then putting those bits together.

    Don't try to do too much, too soon. Walk before you can run.

    If you are falling behind at your course, I would generally advise you to still focus on getting the fundamentals down, and working up to whatever the current assignment is.

    This might take a lot of time - maybe many evenings and weekends, playing with the fundamental pieces of programming syntax, until they become second nature.

    But thats the only way to do it.


  • Registered Users Posts: 1,226 ✭✭✭carveone


    fergalr wrote: »
    Why? Surely defines are completely appropriate to these sort of small size mathematical C programs?

    Probably true, however an enum can be useful when using a debugger. At least under the first C IDE I used (Turbo C 2.01!) the debugger would display the symbol at well as the value. Pretty useful that. I have no clue what most people use these days. I use printf and command line compilers.
    I think debuggers are a tool better kept for more advanced use; if you start using them too soon, you can get into the habit of writing programs by band-aiding the bits that don't do what you think;

    That's very true. The tendency is to fix it so something happens rather than look at the flow.

    But having said that an IDE debugger (rather than something like GDB) is terribly useful just to see what on earth is going on. Being able to see the values actually change as you step through is pretty instructive and makes you see what's happening as the program runs..
    So, I'd say, back up a bit. Take each small construct that you use, and look at it separately.....Start off by writing a program that reads a list of numbers from a file, and prints them out.

    Absolutely. That's what I was trying to say in my post a few days ago. Get each bit working before proceeding to the next part. My next thought was going to be:
    "write a separate program that tells you whether a single number is prime or not"
    but fergalr has just said that. It's exactly what most programmers do. If I'm uncertain about something I'll knock up a 6 line program just to find out. If it's a complex subroutine, I'll knock up a wrapper program solely to test the subroutine.

    Very very few professionals can just open a file and start typing and expect 10 disparate steps to all work together first time. The lower level you go, the harder that gets. Doing it in assembly language is undoable. I've written 100 lines of assembly that worked first time, but the previous step was 40 lines of pseudocode and previous to that, 20 lines of "what I'm doing".

    PS: Putting variable declarations/definitions anywhere in the code is not allowed in C. They must be at the top of an enclosing block. Just so you know :p


Advertisement