I am trying to make a code where a user has 5 tries to guess a number and if any of the 3 series of numbers within Winning_order then both of the for loops will break. The usersInputs stores the users inputs to be compared with Winning_order. So for example, if the number 1,2,3 or 1,2,4,5,3 is inputted by the user the loop will print There is a Correlation and the for loops will stop. If the input is 7,8,9,3,2 since no 3 numbers are present within the Winning_order the loops will just stop. There is a problem with the match_arrays function and I do not know how to go about stopping the nested for loops if the if statement is valid.
Checking if the function has a correlation
int match_arrays(int *arr1, int *arr2, int len) {
for (int p = 0; p < len; p++) {
if (arr1[p] != arr2[p]) {
return 0;
}
}
return 1;
}
main() function
int main(void)
{
int Winning_order[3][3] = {{1,2,3}, {1,4,7}, {2,5,8}};
int input = 0;
int usersInputs[5] = {0};
for (int i = 0; i <= 4; i++){
printf("\nPlayer input: ");
scanf("%d", &input);
usersInputs[i] = input;
for (int p = 0; p < 5; p++) {
if (match_arrays(usersInputs, Winning_order[p], 3)) {printf("There's a Corelation");}
}}
return 0;
}
There are different ways of approaching breaking a double loop (or to generalize: a nested loop), this solution is not the optimal, the best, or the recommended, but it works. I fixed the indentation and some naming issues, but I won't fix anything else.
This is a working snippet:
#include <stdio.h>
int match_arrays(int *arr1, int *arr2, int len) {
for (int p = 0; p < len; p++) {
if (arr1[p] != arr2[p]) {
return 0;
}
}
return 1;
}
int main(void) {
int winning_order[3][3] = {{1,2,3}, {1,4,7}, {2,5,8}};
int input = 0;
int users_inputs[5] = {0};
for (int i, break_i = 0; !break_i && i < 5; i++){
printf("\nPlayer input: ");
scanf("%d", &input);
users_inputs[i] = input;
for (int p = 0; p < 3; p++) {
if (match_arrays(users_inputs, winning_order[p], 3)) {
printf("There's a Corelation\n");
break_i = 1;
break;
}
}
}
return 0;
}
I made this easy for you to understand. I added a new flag to the outer for loop called break_i with an initial falsy value. Simultaneously, I added a short circuit && operation to the for loop.
Inside your inner loop, I added a break_i = 1 statement that will make the outer loop stop. Immediately after that, I use the break statement to break the inner loop.
P.S.: I also fixed the index out of bounds pointed out by #kaylum. You may want to use a macro or sizeof() next time, but that's beyond the scope of your question.
Related
Hello I am trying to print something like this with 2d array.
Note that when user enters the same number, character should be printed above existing char.
EXPECTED RESULTS:
Input 1: 3 //user1 inputs 3
****
****
**x*
Input 2: 1 //user2 inputs 1
****
****
y*x*
Input 3: 1 //user1 inputs 1
****
x***
y*x*
current results:
enter first: 3
3***
***
**x
enter second: 1
1******
******
xx****
enter first: 2
2*********
*********
***xxx***
But keeping printed values on its previous places.
The problem is that they don't get printed in right order. And also it seems that I haven't done the best job with 2d array which is dynamically allocated.
Here is something what I've tried:
#include <stdio.h>
#include <stdlib.h>
int num(int term)
{
int number1;
int number2;
if(term==1)
{
scanf("%d", &number1);
return number1;
}
if (term==2)
{
scanf("%d", &number2);
return number2;
}
return 0;
}
void function(int a, int b, int result[], int size)
{
int i = 0;
int j = 0;
int desired_num = 0;
int count = 0;
int *arr[a];
for (i = 0; i < a; i++)
arr[i] = (int *)malloc(a * sizeof(int));
for (i = 0; i < a; i++)
for (j = 0; j < b; j++)
arr[i][j] = ++count;
for (i = 0; i < a; i++)
{
for (j = 0; j < b; j++)
{
for (int counter = 0; counter < size; counter++)
{
if (arr[i][j] == arr[a - 1][result[counter] - 1])
{
arr[i][j] = desired_num;
}
if (arr[i][j] == desired_num)
{
printf("%s", "x");
}
else
{
printf("*");
}
}
}
printf("\n");
}
}
int main()
{
int counter = 1;
int i = 0;
int given_number;
int array[20];
for (;;)
{
if (counter % 2 != 0)
{
printf("enter first: ");
given_number = num(1);
printf("%d", given_number);
}
else
{
printf("enter second: ");
given_number = num(2);
printf("%d", given_number);
}
array[i] = given_number;
function(3, 3, array, counter);
counter++;
}
return 0;
}
array[i] = given_number;
i is never changed from the value of 0. You are only ever overwriting the first element of array each iteration. The other 19 elements remain in an indeterminate state.
counter and array are passed to function, as size and result respectively:
This means as size is incremented, it is used as a bounds for accessing elements of result; elements that contain indeterminate values.
for (int counter = 0; counter < size; counter++)
{
if (arr[i][j] == arr[a - 1][result[counter] - 1])
This will surely lead to Undefined Behaviour as those indeterminate values are used to index arr, effectively accessing random memory offsets. This fact alone makes it hard to reason about the output you are seeing, as really anything is valid.
While perfectly valid, the variable-length array of dynamic allocations is a somewhat perplexing choice, especially considering you fail to free the memory allocated by malloc when you are done with it.
int *arr[a];
for (i = 0; i < a; i++)
arr[i] = (int *)malloc(a * sizeof(int));
int arr[a][b]; would work, given a and b are not stack-crushingly large values (or non-positive). You are, or would be, bounded by the size of array in main anyway.
The triply nested loop is confused at best. There is only logic for printing the x and * characters, so you obviously will never see a y.
For each element of arr, you iterate through each element of result. If the current element of arr equals the value of the column selected by the current value of result ([result[counter] - 1]) in the last row (arr[a - 1]) you print x, otherwise *.
Again UB from utilizing indeterminate values of result, but you can see you are printing a * b * size characters, plus newlines, each iteration.
This is severely flawed.
Some other things of note:
The two branches of the if .. else statement in the num function do the exact same thing, just with different identifiers.
The two branches of the if .. else statement in main are identical, other than the first printf in each, and the integer value passed to num, which have the same effect.
This means the only thing that needs to branch is the printf argument.
A generic function for getting an integer would work fine
int get_num(void)
{
int n;
if (1 != scanf("%d", &n)) {
fprintf(stderr, "Could not read input.\n");
exit(EXIT_FAILURE);
}
return n;
}
for use inside main
if (counter % 2 == 0)
printf("enter first: ");
else
printf("enter second: ");
given_number = get_num();
A small issue: printf("%d", given_number); is muddling the output slightly.
There is no reason to repeatedly generate the array. Initialize an array in main to serve as the state of the program. Over time, fill it with the users' selections, and simply print the array each iteration.
Make sure to always check the return value of scanf is the expected number of conversions, and ensure the integers provided by the users will not access invalid memory.
Here is a cursory example.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define EMPTY '*'
#define PLAYER_ONE 'X'
#define PLAYER_TWO 'O'
int get_num(void)
{
int n;
if (1 != scanf("%d", &n)) {
fprintf(stderr, "Could not read input.\n");
exit(EXIT_FAILURE);
}
return n;
}
int main(void)
{
const size_t rows = 6;
const size_t cols = 7;
char board[rows][cols + 1];
memset(board, EMPTY, sizeof board);
/* our rows are now strings */
for (size_t i = 0; i < rows; i++) {
board[i][cols] = '\0';
puts(board[i]);
}
unsigned char turn = 1;
while (1) {
printf("Player %s, Enter column #(1-%zu): ",
turn & 1 ? "One" : "Two", rows);
int input = get_num();
if (1 > input || input > cols) {
printf("Invalid column [%d]. Try again...\n", input);
continue;
}
size_t sel = input - 1;
if (board[0][sel] != EMPTY) {
printf("Column [%d] is full! Try again...\n", input);
continue;
}
size_t n = rows;
while (n--) {
if (board[n][sel] == EMPTY) {
board[n][sel] = turn & 1 ? PLAYER_ONE : PLAYER_TWO;
break;
}
}
for (size_t i = 0; i < rows; i++)
puts(board[i]);
turn ^= 1
}
}
I am successful in identifying prime and composite from an array. But my qsort function seem to not have any effect when I print the output. I need the primes to be ascending and composite to be descending. When I run the code, it does not sort the output, though it identifies primes and composites.
#include <stdio.h>
#include <stdlib.h>
int compare_Asc(const void *a_void, const void *b_void) {
int a = *(int *)a_void;
int b = *(int *)b_void;
return a - b;
}
int compare_Desc(const void *a_void, const void *b_void) {
int a = *(int *)a_void;
int b = *(int *)b_void;
return b - a;
}
int main() {
int i = 0, n, x, p, c, z, w, j = 0, k = 0, cmpst, null;
int prm;
int prime[50], composite[50], input[50];
printf("How many inputs are you be working with?\nNote: 50 Maximum Inputs\n");
scanf("%d", &n);
printf("Enter the numbers.\n", n);
for (i = 0; i < n; i++) {
scanf("%d", &input[i]);;
}
for (i = 0; i < n; i++) {
if (input[i] % 2 != 0) {
prime[p++] = input[i];
prm = p;
} else
if (input[i] >= 2 && input[i] % 2 == 0) {
composite[c++] = input[i];
cmpst = c;
}
}
printf("Prime Numbers:");
qsort(prime, prm, sizeof(int), compare_Asc);
for (i = 0; i < p; i++) {
printf("%d", prime[p]);
}
printf("Composite Numbers:");
qsort(composite, cmpst, sizeof(int), compare_Desc);
for (i = 0; i < c; i++) {
printf("%d", composite[c]);
}
return 0;
}
There are some major issues, in the posted code, worth mentioning.
Variables
Declaring all the variables at the beginning of the scope, instead of just before where they are used, can hide bugs.
Uninitialized variables, are an even worse source of errors, because their values are indeterminated.
int i=0, n, x, p, c, z, w, j=0, k=0, cmpst, null;
// ^ ^ ^^^^ ?
// ... Later, in the code:
prime[p++] = input[i];
// ^^^ What value is incremented?
// Where is [p++]? Is it inside the prime array?
A correct initialization would prevent undefined behavior.
int p = 0, c = 0;
int composite[50], input[50];
for(int i = 0; i < n ; ++i) {
if ( is_prime(input[i]) ) { // <-- More on this, later.
prime[p++] = input[i];
}
else {
composite[c++] = input[i];
}
}
Loops
This happens a couple of times, just because the code itself is duplicated (another code smell):
for(i=0;i<p;i++){
// ^^^^^^^^^^^ We want to iterate over [0, p).
printf("%d",prime[p]);
// ^ But this always prints the element one past the end
}
Even if it's just a simple loop, it could be a good idea to write a (testable and reusable) function
void print_arr(size_t n, int arr[n])
{
for (size_t i = 0; i < n; ++i) {
printf("%d ", arr[i]);
} // ^
putchar('\n');
}
// ... Later, in main:
print_arr(p, prime);
print_arr(c, composite);
Primes or composite
I am successful in identifying prime and composite from an array
Well, no. Not with this code, I'm sorry.
if (input[i]%2 != 0) { // Those are ALL the ODD numbers!
prime[p++]=input[i];
}
else if(input[i]>=2 && input[i]%2==0){ // Those are the EVEN numbers greater than 0
composite[c++]=input[i];
}
// What about 0 and the even numbers less than 0?
Not all the odd numbers are prime number (it's a little more complicated than that) and 2 itself is a prime, not a composite.
It's unclear to me if this is a terminology issue or if the snippet is only a placeholder for a proper algorithm. In any case, there are multiple examples of primality test functions in SE sites (I'm quite confident some are posted almost every day).
Overflow risk
See chux - Reinstate Monica's comment:
return a-b; risks overflow when a, b are large int values.
Consider return (a > b) - (a < b); for a full range solution.
Single letter variables names are to be avoided... except for i, j and k used in for() loops only.
You're not updating the index of the arrays c and p as the numbers are being printed out. The arrays are being sorted fine.
In the code below I also remove redundant variables, and rename n to input_count, c to compo_count and p to prime_count.
#include <stdio.h>
#include <stdlib.h>
int compare_Asc(const void *a_void, const void *b_void)
{
int a = *(int *) a_void;
int b = *(int *) b_void;
return a - b;
}
int compare_Desc(const void *a_void, const void *b_void)
{
int a = *(int *) a_void;
int b = *(int *) b_void;
return b - a;
}
int main ()
{
int i = 0;
int input_count = 0;
int prime_count = 0;
int compo_count = 0;
int prime[50];
int composite[50];
int input[50];
printf("How many inputs are you be working with?\nNote: 50 Maximum Inputs\n");
scanf("%d", &input_count);
printf("Enter the %d numbers.\n", input_count);
for (i = 0; i < input_count; i++)
{
scanf("%d", &input[i]);
}
for (i = 0; i < input_count; i++)
{
if (input[i] % 2 != 0)
{
prime[prime_count] = input[i];
prime_count += 1;
}
else if (input[i] >= 2 && input[i] % 2 == 0)
{
composite[compo_count] = input[i];
compo_count += 1;
}
}
printf("Prime Numbers:");
qsort(prime, prime_count, sizeof(int), compare_Asc);
for (i = 0; i < prime_count; i++)
{
printf("%d ", prime[i]); // <<-- HERE, not [p]
}
printf( "\n" );
printf ("Composite Numbers:");
qsort(composite, compo_count, sizeof(int), compare_Desc);
for (i = 0; i < compo_count; i++)
{
printf("%d", composite[i]); // <<-- HERE, not [c]
}
printf( "\n" );
return 0;
}
#include <stdio.h>
#include <cs50.h>
#include <math.h>
int * get_digs(long card, int digs, int idigs[]);
int main()
{
long card = get_long("Number: ");
int digs = ceil(log10(card));
int idigs[digs];
get_digs(card, digs, &idigs[digs]);
for(int k = 0; k == digs; k++) // This loop is to check if the program is doing what I'm
{ // asking it to do.
printf("%i", idigs[k]);
}
}
int * get_digs(long cd, int dg, int idg[])
{
int j = dg;
int dig = 0;
for(int i = 0; i == dg; i++)
{
dig = floor(cd / pow(10, j));
j--;
idg[i] = dig % 10;
}
return 0;
}
This program is supposed to take an input from the user, let's say a credit card, get its digits and store them on an array. The program compiles, but it doesn't even print the for loop on the main function... It just asks for input. What am I doing wrong?
The second expression in a for loop's control block is a condition for iterating, not for breaking from the loop. Thus, this for loop ...
for(int k = 0; k == digs; k++)
... executes the loop body only if k is equal to digs, and that will be true the first time the condition is checked only if digs is zero, which you (reasonably) do not expect to be the case. Furthermore, unless k were also modified inside the loop body, which it isn't in your code, the body would never execute more than once. It's similar in effect, then, to if (k == digs), and of course the loop body is not executed even once.
The standard idiom for what you are trying to do uses a < expression in the condition:
for (int k = 0; k < digs; k++)
I need to this function in C that takes a tab of strings and its length as parameters. It's supposed to erase empty tab blocks (just like Ruby's Array.compact) and return the new tab's size :
int strtab_compact(char **tab, int length)
{
...
}
for example if I have :
tab[0] = "foo";
tab[1] = 0; // nul
tab[2] = "bar";
tab[3] = 0;
tab[4] = "baz";
i = strtab_compact(tab, 5) // tab should = ["foo"]["bar"]["baz"] and i = 3
I am just starting C (it's my second week) and I have the following piece of code but I'm totally stuck :
int strtab_compact(char **tab, int length)
{
int i;
int index;
iterations = 0;
i = 0;
// First iteration to get how many valid entries we've got
while (i < length)
{
if (tab[i])
index++;
i++;
}
// I'll need a second iteration to reorganize the tab and I have no idea how to delete the remaining slots
i = 0;
while (...)
{
...
}
return (index);
}
You don't need two iterations, but you need two iterator indices: i iterates over the array and index advances only when you find a non-null string. The length of the compact array is then the value of index after iteration:
int strtab_compact(char **tab, int length)
{
int index = 0;
int i;
for (i = 0; i < length; i++) {
if (tab[i]) tab[index++] = tab[i];
}
return index;
}
Because you delete only NULL entries, you don't have to worry about freeing memory for the deleted strings, if they are allocated on the heap. (In your example they aren't. I just wanted to mention that you have to take care what happens to the elements you delete, because access to them will be lost after compacting.)
int strtab_compact(char **tab, int length){
int i, index;
for(index = i = 0; i < length; ++i){
if(tab[i] != NULL)
tab[index++] = tab[i];
}
for(i = index; i < length; ++i)
tab[i] = NULL;
return index;
}
I have to write a function that will return true if every integer in the array is unique (different). So, I've tried correcting my for loops/my if statement and I've tried running the tests that I wrote. But, the test for a string with an integer appearing more than once still fails. I've reviewed my code but I still can't find the problem.
#include "in.h"
int in(int input[], int size)
{
for (int i = 0; i < size - 1; i++)
{
for (int j = i + 1; j < size; j++)
{
if (input[i] == input[j])
{
return 0;
}
}
}
return 1;
}
Here are my test cases:
#include "in.h"
#include "checkit.h"
void in_tests(void)
{
int input[3] = {2, 4, 5};
int answer;
answer = in(input, 3);
checkit_int(answer, 1);
int input1[4] = {1, 3, 4, 1};
int answer1;
answer1 = in(input1, 4);
checkit_int(answer, 0);
}
int main()
{
in_tests();
return 0;
}
without sort, an O(n2):
j begins with i+1.
int IsDiff(int array[], int count)
{
int i,j;
for (i=0; i<count; i++)
{
for (j=i+1;j<count;j++)
{
if (array[i] == array[j])
return 0;
}
}
return 1;
}
If space is not an issue, then we can have a O(n) solution using a hashtable. Start storing each element of the array in a hashtable. While inserting elements, make a check to see if it already present in the hashtable ( which takes O(1) time.) If the element is already present, then return false immediately, else iterate until the end of array and return true.
actually, thats not why your function doesn't work. the main reason is because currently you are checking if any pair DONT match, which would be great if you wanted to see if all the elements matched, but you want to do the opposite, so you want to check the opposite, if any pair DOES match. so first change your if to be
if(input[i] == input[j]) return false;
if one pair is equal then you know that your test has already failed so there is no need to check the remaining pairs, just return false there and then.
the only other thing to do is to sort out your loops so that you only iterate over each pair once and don't compare a value against it's self. to do that change the for loops to be:
for(int i =0; i<size-1; i++)
for(int j=i+1; j<size; j++)
then if you make it to the end of the function, it means no pair as matched, so just return true;
O(n^2) as well.. but I added this function that makes the code more understandable...
int unique(int input[], int value,int size){
int times=0;
for (int i = 0; i < size; i++)
{
if(input[i]==value){
times++;
if(times==2)
return 0;
}
}
return 1;
}
int in(int input[], int size)
{
int x, answer;
for (int i = 0; i < size; i++)
{
if(!unique(input,input[i],size))
return 0;
}
return 1;
}
You are very close, try this:
#include "in.h"
int in(int input[], int size)
{
int answer = 1;
for (int i = 0; i < size-1; i++)
{
for (int j = i+1; j < size; j++) //check everything above your current
//value because you have already checked
//below it.
{
if (input[i] == input[j])
{
answer = 0; //If any are not unique you
break; //should exit immediately to save time
}
}
if (answer == 0)
break
}
return answer;
}
Thinking about the problem
let's say you have an array like this: int array[] = { 3, 1, 4, 8, 2, 6, 7, 7, 9, 6 };
if you start with the first element you need to compare to the rest of the elements in the set ; so 3 needs to be compared to 1, 4, 3... etc.
if 3 is unique you need to now go to 1 and look at the remaining elements, but next time around you don't need to worry about the 3 ; so your value under consideration (let's call that V) needs to be each of, array[0] to array[N-1] where N is the size of array (in our case 10);
But if we imagine ourselves in the middle of the array, we'll notice that we have already compared previous elements to the current element when the previous element was the value under consideration. So we can ignore any elements "behind" us; which means comparison has to start the each time with the INDEX of current value under consideration (let's call that k) and compare it to values starting with the NEXT index and going to the end of the array ; so pseudo-code for our array of 10 it would look like this:
int is_a_set(int array[])
{
for ( k = 0; k < 10-1 ; k++ ) { /* value under consideration */
v = array[k];
for ( m = k+1 ; m < 10; m++ ) { /* compared to the remaining array starting
* starting from the next element */
if ( v == array[m] ) { /* we found a value that matches, no need to
* to continue going, we can return from this function
*/
return true;
}
}
}
return false;
}
now you can use something like:
if ( is_a_set(my_array) ) {
}
You should be able to use this to figure the rest of your code out :-)
NOTE: a collection with unique elements is called a set so I named the function is_a_set
HINTS: convert size of the array (10) into a parameter or a variable of some sort
Here's my attempt at it (very simple and inefficient though):
#include <stdio.h>
int uniq_int(int arr [], int size)
{
int i, j;
for (i = 0; i < size; i++)
for (j = i + 1; j < size; j++)
if (arr[i] == arr[j])
return 0;
return 1;
}
int main()
{
int arr [] = {1, 2, 4, 3, 5};
(uniq_int(arr, 5)) ? printf("Unique!\n") : printf("Not...\n");
/* the above can be written more traditionally like this:
if (uniq_int(arr, 5) != 0)
{
printf("Unique!\n");
}
else
{
printf("Not...\n");
}
*/
return 0;
}
This will compare every member of the array against the rest, starting from the first
and comparing it against the next one and so on until the end of the inner loop.
Then we start the outer loop again but this time we compare the second element of the array against the ones after it.
As soon as a match is found the function will return and there won't be a need to compare the other elements. Otherwise the outer loop will go on until the last element and once that's reached it will exit and return 1, meaning every member is unique.
It has a complexity of O(n^2) as the set is processed twice for each member in the worst case.