I was just wondering why my code doesn't work. Yes I know that it's easy to find answers online but I just wanted to delve in why the things I do doesn't function well rather than simply getting answers.
#include <stdio.h>
int main() {
int i;
int j;
printf("all prime numbers between 1 and 100\n");
for (i = 2; i <= 100; ++i) {
if (i % !i != 0 && i>0 ) {
printf("%d ", i);
}
}
}
As you have noticed yourself, there are tons of example code for this out there, so there's little point for me in showing how to calculate primes. So instead, I show how to debug your code. In this case I'd doe something like this:
for (i = 2; i <= 100; ++i) {
printf("i: %d !i: %d\n", i, !i);
printf("i \% !i != 0: ", i % !i != 0);
if (i % !i != 0 && i>0 ) {
printf("%d ", i);
}
}
The exact printouts is something that you have to find out for yourself. But start with individual values, and then look at more complicated expressions. Also, use parenthesis whenever unsure. I don't know exactly how the expression in your if statement is parsed. I can think of several possibilities. Like:
((i % !i) != 0) && (i>0)
(i % (!i != 0)) && (i>0)
(i % !i) != (0 && i>0)
The point here is that your code does not work, and you have a very messy expression that is hard to understand exactly what it does. So use parenthesis.
Another thing you should do with that expression is to motivate each part with words. Can you explain why you have i>0? Because that's always true, to it's completely pointless. Instead of asking why it doesn't work. Try to explain to yourself why it should work. Get more and more detailed until you find something that you cannot explain. Then you probably have your bug there.
The definition of a prime is that it is an integer strictly greater than one, and is not divisible by any other integers than itself and and one. So now it's your job to explain how i % !i != 0 && i>0 should be able to check if i is an integer or not. And take explicit examples. For instance, if i is 5, describe the process when i % !i != 0 && i>0 checks if it is divisible by 2. Then explain how it checks for divisibility by 3.
The very simple question to your answer why it does not work is because the algorithm is wrong. :)
Related
I've stumbled upon an interesting problem while preparing for my exam, and I'm unsure as to whether I've solved it or not. I will provide the text of the problem, as well as my code:
void charAlloc(){
char *arrPtr;
arrPtr = malloc(sizeof(char)*100);
int i;
for (i=0; i<101; i++){
if (*(arrPtr+i) % 5 == 0){
*(arrPtr + i) = 'a';
}
if (*(arrPtr+i) % 3 && *(arrPtr+i) % 7 != 0 && *(arrPtr+i) / 2 != 0){
*(arrPtr+i) = 'b';
}
else{
*(arrPtr+i) = 'c';
}
}
free(arrPtr);
}
Since it's a void function there isn't really a way to check if it's doing what it's supposed to in this case, so I thought I'd ask here. I do sometimes struggle with pointers so it's quite possible I maybe messed up something there. There's no errors or warnings in the compiler.
Question has been answered in the comments. Firstly, instead of going through the loop for 101 times, it should iterate 100 times: for(i=0; i<100; i++).
The next mistake was in the if branches within the loop. What *(arrPtr+i) does is it selects the value stored at that address.
This is not the value of the index, but rather a garbage value appointed to the heap.
What I should've done instead is checked for the values of i, and assign the values given in the problem to *(arrPtr+i).
There was another mistake pointed out within the if branches. In the second if conditional, for assigning value 'b' to certain indexes, the testing statements are incorrect. They stated:
if (*(arrPtr+i) % 3 && *(arrPtr+i) % 7 != 0 && *(arrPtr+i) / 2 != 0)
Which is incorrect in several parts. The first condition is not even finished, it should say if (*(arrPtr+i) % 3 == 0, and the last condition does not check properly if the number is divisible by two. *(arrPtr+i) % 2 != 0 would be the proper way to do that.
With all this combined, the final result should be something like this:
void charAlloc(){
char *arrPtr;
arrPtr = malloc(sizeof(char)*100);
int i;
for (i=0; i<100; i++){
if (i % 5 == 0){
*(arrPtr+i) = 'a';}
else if (i % 3 == 0 && (i % 7 != 0) && (i % 2 !=0)){
*(arrPtr+i) = 'b';}
else {
*(arrPtr+i) = 'c';}
}
free(arrPtr);
}
I'd like to thank all the commenters for helping me understand this problem and I hope other programmers with issues similar to mine can find this useful.
Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 1 year ago.
Improve this question
So I am running into an issue that I can't seem to fix. I want to display the factor and the power that it is raised to(basically prime factor decomposition), I had done this in python but for some reason I can't implement this in C and this is what I came up with
#include<stdio.h>
#include<math.h>
int main()
{
int i = 2, p, c, n;
scanf("%d", n);
while (n > 9)
{
p = 0;
c = 1;
while (n % i == 0)
{
for (int d = 2; d <= i / 2 + 1; d++)
if (i % d == 0 && i % 2 != 0)
c = 0;
if (c == 1)
{
p = p + 1;
n = n / i;
}
if (p != 0)
{
printf("%d %d", i, p);
printf("\n");
}
i = i + 1;
}
}
return 0;
}
Problem #1 (although it's not your main problem) is that you're missing a pointer in your scanf call:
scanf("%d", n);
That needs to be
scanf("%d", &n);
(My compiler warned me about this right away. Not sure why yours didn't.)
Problem #2 is that while (n > 9) is just totally wrong. I think you want while (n > 1).
Problem #3 is that the i = i + 1 step is misplaced. You need to do that whether or not i was a factor, so it needs to be at the end of the outermost loop.
And then problem #4 is the code that starts with
for (int d = 2; d <= i / 2 + 1; d++)
It looks like you're trying to check whether i is prime, although you're doing it too late: you're already inside the if where you test whether i is a factor of n. Also you don't have a proper loop to count how many times i is a factor of n.
It turns out, though, that you don't actually need to test whether i is prime, so let's leave the primality-testing step out for a moment and see what happens.
Here's the first fixed version:
#include <stdio.h>
int main()
{
int i = 2, p, n;
scanf("%d", &n);
while (n > 1)
{
if (n % i == 0) /* if i is a factor */
{
p = 0;
while (n % i == 0) /* count how many times i is a factor */
{
n /= i;
p++;
}
printf("%d %d\n", i, p);
}
i++;
}
return 0;
}
And this works! It tries every possible value of i, which is pretty inefficient, but due to the properties of prime factorization, it's okay. It tries them in order, so it will always have weeded out all lower prime factors first, so none of the non-prime i's will make it through to get printed as a factor.
To do what I guess you were trying to do, we have to rearrange the code. The basic algorithm is: for each i, if it's prime, see how many times it divides the running n.
#include <stdio.h>
int main()
{
int i = 2, p, c, n;
scanf("%d", &n);
while (n > 1)
{
/* see if i is prime */
c = 1;
for (int d = 2; d <= i / 2 + 1; d++)
if (i % d == 0 && i % 2 != 0)
{
c = 0;
break;
}
if (c == 1) /* if i is prime */
{
p = 0;
while (n % i == 0) /* count how many times i is a factor */
{
p = p + 1;
n = n / i;
}
if (p != 0)
printf("%d %d\n", i, p);
}
i = i + 1;
}
return 0;
}
The primality test is still pretty crude (that line if (i % d == 0 && i % 2 != 0) is fishy), but it seems to work. I suspect it's still wasteful, though: if you're generating all possible trial divisors to factorize n, there's probably a better way than running a full primality test on each i, from scratch.
One popular shortcut is to have i run through 2,3,5,7,9,11,13,... (that is, 2 plus all the odd numbers). Building on that idea, I once wrote some code that uses a more complicated sequence of increments so that it ends up using 2, 3, 5, and then every odd number that isn't a multiple of 3 or 5. I suspect (but I haven't measured) that wastefully using some number of non-prime trial divisors i might end up being less wasteful than positively confirming that each trial divisor is strictly prime.
But if you really care about efficiency, you'll have to abandon this obvious but still rather brute-force technique of blindly trying all the trial divisors, and move to something more sophisticated like elliptic curve factorization. What we're doing here is trial division, which as Wikipedia notes is "the most laborious but easiest to understand of the integer factorization algorithms".
Been trying to write program for displaying prime numbers and just wanted to know if there is much difference between the following two algorithms.
1,
#include <stdio.h>
#define MAXNUMB 100000
int main(void){
int flag;
long i,j=MAXNUMB;
printf ("The Prime Numbers up to %ld are:\n 2\n", j);
for(i=3 ; i<=MAXNUMB; i = i+2){
j = 3; //only difference is in this line
flag = 0;
while((j*j <= i) && flag == 0){
if(i%j == 0){
flag = 1;
}
j++;
}
if (flag == 0){
printf("%8ld\n",i);
}
}
}
2,
#include <stdio.h>
#define MAXNUMB 100000
int main(void){
int flag;
long i,j=MAXNUMB;
printf ("The Prime Numbers up to %ld are:\n 2\n", j);
for(i=3 ; i<=MAXNUMB; i = i+2){
j = 2; //again this is the only different line
flag = 0;
while((j*j <= i) && flag == 0){
if(i%j == 0){
flag = 1;
}
j++;
}
if (flag == 0){
printf("%8ld\n",i);
}
}
}
It seems to me that both work but im not sure, maybe someone can shed some light.
Also, any general tips for someone starting to code, that apply for all programmers?
Thanks!
They both have the same output because you're skipping over even numbers with i = i + 2 and starting the loop with i = 3. So the i % j == 0 condition will never be true when j = 2.
To me it seems like they have the same output but i cant check every number
Wrap your approaches into separate functions, return the results in an array and then compare both arrays.
You can very quickly see the time it takes for these to complete with the built in time function for GNU/Linux or Cygwin. Using the G++ compiler, it takes around 0.109s to run the first snippet and around 0.141s to run the second one. So I guess it depends on what your definition of "more efficient" is. Note: I did not check for the accuracy of the results, just running the programs as they are.
As for general programming tips, you have access to boundless information on the internet, just search up programming tips. One could write an entire book on "tips" for a beginning programmer. Here is a good example.
I am very new to programming in general, so please bear with my lack of knowledge.
I have spent a couple of hours now on exercise 1-13. I finally decided to look up the answer, which I found at this link https://github.com/ccpalettes/the-c-programming-language-second-edition-solutions/blob/master/Chapter1/Exercise%201-13/word_length.c .
Because I didn't want to copy it completely for the sake of learning, I tried to understand the code and then remake it. (This resulted in almost a complete copy, but I understand it better than I would have otherwise.)
This is what I have so far:
#include <stdio.h>
#define IN 1
#define OUT 0
#define LARGEST 10
main()
{
int c, state, l, i, j;
int length[LARGEST + 1];
for (i = 0; i <= LARGEST; ++i)
length[i] = 0;
state = OUT;
while ((c = getchar()) != EOF) {
if ((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z')) {
if (state == OUT) {
l = 0;
state = IN;
}
++l;
}
else
if (state == IN) {
if (l <= LARGEST)
++length[l - 1];
//minus 1 because the nth term of an array is actually array[n-1]
else //if (l > LARGEST)
++length[LARGEST];
state = OUT;
}
if (c == EOF)
break;
}
for (i = 0; i <= LARGEST; ++i) {
if (i != LARGEST) //because array[10] refers to the 11th spot
printf("\t %2d |", i + 1); //plus one because 1st is array [0]
//this actually results in 1-10 because the 0-9 plus one makes the highest 10
else
printf("\t>%2d |", LARGEST);
for (j = 0; j < length[i]; ++j)
putchar('x');
putchar('\n');
}
return 0;
}
Please ignore my comments. They were meant for me, so that I could explain the program to myself.
I am having two issues that I just can't figure out, and they're driving me crazy:
The output always accounts for one word less than in the input, meaning "my name is not bob" results in:
...
2 |xx
3 |x
4 |x
...
Also, I don't understand what is going on at the end of the program. Specifically, I don't understand here why the variable j is being used:
for (j = 0; j < length[i]; ++j)
putchar('x');
Thanks so much for your help, and I'm sorry if this is too beginner for the community.
Well, trying to sum up all the answers since the question is not closed.
First, we need to correct the main() line:
int main(void) {
...
return 0;
}
The int is necessary because you return a value at the end of the function, and the void means that the function doesn't receive any arguments.
I've copied your code and executed on my machine (Ubuntu 12.04) and it worked perfectly. Could you present some examples to generate the error?
As everybody said, j is just a variable to traverse the vector. length[i] is a vector that holds, in each position i the number of words with length i. For instance, if position 3 has a value of 4, e.g. length[3] = 4, it means that there are 4 words
with length 3.
Finally, if I may, I'd like to give you a tip. It is good practice choosing meaningful names for your variables. The code you linked here helped me to understand what the program should do. Variable names such, length, or defines IN, OUT or LARGEST are too vague.
I hope this gather all answers until now and helped you even more.
folks,
I am adding a logic expression in the for loop and it is not behaving as I expected. Could you shine some light on me? Thanks very much.
The following code works fine
for (i=0;i<N;++i)
if (a[i] == 1){
....
}
and I tried to write it this way, it seems the for loop is fully skipped.
for (i=0;i<N && a[i]==1;++i){
....
}
What is wrong with the 2nd way?
The loop continues while the condition is true. Remember that a for-loop for(A; B; C) can be replaced with [conceptually]:
A;
while(B)
{
...
C;
}
So, you have:
i = 0;
while(i < N && a[i] == 1)
{
...
i++;
}
So, if at the first instance a[i] is not 1, then you never enter the loop, and just go to whatever comes after. It's probably not what you wanted to do, which is why it's not doing what you wanted... ;)
This code:
for (i=0;i<N;++i)
if (a[i] == 1){
Means, increment i, starting from 0, keep going until it's greater than or equal to N, for each element in a[] check to see if it's equal to 1
This code however:
while(i < N && a[i] == 1)
Says loop as long as i is less than N and a[i] is equal to 1. So as soon as either of those condtions is false it will break from the loop.
You never enter the loop if a[0] != 1. That's a condition for your for loop to be executed just like how i < N is too.