Array item assignment gives unexpected results - c

Background: I have an exercise which asks me to create a function which compares 2 int arrays using the backtracking technique. The function should return 0 if the arrays are different and 1 if they are the same. The size of the arrays, the method of filling them and the output of the program are not specified in the question so I took the liberty of working them out my own way.
By using a for I made a simple fill function which fills out the two arrays in a simple way so if the user inputs s the result should be
A[0]=B[0]=0
A[1]=B[1]=1
...
A[50]=B[50]=50
and if he inputs d it should be the same but
B[i]=A[i]+1
The problem:
Instead of A[0]=0 it ends up being A[0]=50 (and A[0]=51 in the d case) which makes the whole function return 0 in every case. I have tried numerous things, but I can't get it to work properly
Here's the code:
#include <stdio.h>
#include <stdlib.h>
void fill(int a, int A[],int B[])
{
int i,j;
if (a)
{
for(i=0;i<=50;i++)
{
A[i]=i;
B[i]=A[i];
}
}
else
{
for(i=0;i<=50;i++)
{
A[i]=i;
B[i]=i+1;
}
}
A[0]=0;
for (j=0;j<=50;j++)
printf("\nka %d %d %d",j, A[j],B[j]); //the purpose of this is to check the state of the two arrays after filling them, it's how I spotted the problem, it will be deleted in the final form
}
int compare(int i, int A[],int B[])
{
int a,b;
a=A[i];
b=B[i];
printf("j %d %d\n", a,b);
if (B[i+1]!='\0')
{
if (A[i]==B[i])
{
compare (i+1,A,B);
}
else
{
return 0;
}
}
else
return 1;
}
int main()
{
int A[50], B[50], i=0;
char s;
printf("Do you want the arrays to be the same or different?\n");
printf("Input 's' or 'd': ");
scanf("%c", &s);
switch(s)
{
case 's':
case 'S':
fill(1,A,B);
break;
case 'd':
case 'D':
fill(0,A,B);
break;
default:
printf("Sorry incorrect input, please input 's' or 'd'");
return 0;
break;
}
if (compare(i,A,B))
printf("They are the same");
else
printf("They are different");
return 0;
}

You need to correct your both the functions fill and compare. In function fill you are accessing arrays out of bounds which will invoke undefined behavior. Loop should be iterated from 0 to 50 (excluding 50)
for(i=0;i<50;i++) { ... }
The function compare should be like
// Pass the size of array to the function.
int compare(int i, int A[],int B[], int n)
{
if (i != n)
{
if (A[i]==B[i])
{
return compare (i+1, A, B, n);
}
else
{
return 0;
}
}
else
return 1;
}

The issue is in the for loop. It is looping for 51 elements.
for (i=0;i<=50;i++)
It should loop for 50 elements
for (i=0;i<50;i++)
Similarly for the loop for j, in the fill function.
There is also an issue in the compare function. The exit check is
if (B[i+1]!='\0')
This means that the input array must have the last element as '\0'. Which is not happening in your input array.
You have to either pass strings to this function, or modify this function to take care of the general array case.

Related

How to copy a multidimensional array to another without knowing the exact amount of rows in C?

So my program is basically built to get game scores, and track w/l/t, etc. What I am needed to do is to arrange the scores in ascending order based off of the opponent's scores.
So to do that I decided to bubble sort, but when I do that and print it, the first pair [0][0], and [0][1] come out with big negative numbers, which is what I'm guessing is their reference then after that the rest print correctly. I've googled around and couldn't find anything about this so I was wanting to copy the original array into a copy and try sorting with that one.
#include <stdio.h>
#include <stdlib.h>
#define _CRT_SECURE_NO_WARNINGS //doesn't work
#define FLUSH myFlush()
#define GAMES 50
void titleDisplay(int);
void menuOptions();
void gameResults(int *counter, int team[][2], int); // records games from user input
void showRecord(int counter, int team[][2]); // shows current record
void displayResultFromGamesWon(int counter, int team[][2]);
void displayAllResults(int counter, int team[][2]); // shows all results ordered by opp score.
char getChoice();
void myFlush();
int main() {
//const int GAMES = 50; - program doesn't read this as a const when used to create arr.
const int MAX_GAMES = 50;
int userTeam[GAMES][2]; // array column 0 is user score, column 1 is opp score
int gameCounter = 0;
char userChoice;
do {
system("clear");
titleDisplay(1);
menuOptions();
userChoice = getChoice();
switch (userChoice) {
case 'a': case 'A':
gameResults(&gameCounter, userTeam, MAX_GAMES);
break;
case 'b': case 'B':
showRecord(gameCounter, userTeam);
break;
case 'c': case 'C':
displayResultFromGamesWon(gameCounter, userTeam);
break;
case 'd': case 'D':
displayAllResults(gameCounter, userTeam);
break;
case 'e': case 'E':
printf("Bye bye.\n");
system("pause");
break;
default:
printf("Invalid selection, choose again!\n");
system("pause");
break;
}//end switch
} while (userChoice != 'e' && userChoice != 'E');
return 0;
}
Here's where I sort and print:
//function definition
void displayAllResults(int counter, int team[][2]) {
int i;
int temp, temp2 = 0;
system("clear");
if (counter == 0) {
printf("\n\n\tYou haven't played any games yet.\n\n\n");
}
else {
titleDisplay(4);
printf("\t (Arranged by Opponent score low to high)\n\n");
printf("\tUser Score\t\t\tOpponent Score\n");
printf("\t----------\t\t\t--------------\n");
//begin bubble sorting
for (int x = 0; x < counter; x++) {
for (int y = x + 1; y < counter; y++) {
if (team[x][0] > team[y][0]) {
temp = team[x][1];
temp2 = team[x][0];
team[x][0] = team[y][0];
team[x][1] = team[y][1];
team[y][0] = temp2;
team[y][1] = temp;
}//end if
}
}//end bubble sort
for (i = 0; i < counter; i++) {
printf("\t%-8i\t\t\t%-11i\n", team[i][0], team[i][1]);
}//end for
}//end else
system("pause");
}//end function
I've tried declaring a variable of 'int sortedArray = team[counter][2];' in the displayAllResults function but that gave memory problems, and failed when I tried to access that variable. I tried memcpy, but either I didn't implement correctly or that doesn't work either.
Is it even possible to copy a 2D array like this to another one?
There are two ways to copy an array to another:
1-Using sizeof(array) and dividing it to size of one element of the array, in this case it is a pointer.
2- The best way is, to have a variable which will show you the length of the array.
I think you made an implementational mistake. I couldn't understand what you are doing. What is 5 for?
In any case, do have a variable for the length of the array.

Compare an int with double array

I'm trying to learn C and I want to make a program that compares the number I type with the numbers in my array. The only problem is that It doesn't actually do that. Even if I type a number that is from that array it shows that the number is not from that array.
#include <stdio.h>
void getMark(int findMark, double crswk1[]);
void changePartMark(double crswk1[], int findMark);
int main()
{
int findMark;
double crswk1[10]={67, 77, 80, 40};
getMark(findMark, crswk1);
changePartMark(crswk1, findMark);
}
void getMark(int findMark, double crswk1[])
{
printf("Enter the mark you want to change: ");
scanf("%d", &findMark);
}
void changePartMark(double crswk1[], int findMark)
{
int i;
if(findMark == crswk1[i])
{
printf("It is equal");
}
else
{
printf("It is not equal");
}
}
The number you're reading in is never getting back to findMark in your main function.
void getMark(int findMark, double crswk1[])
{
printf("Enter the mark you want to change: ");
scanf("%d", &findMark);
}
This function is saving a value in the local parameter findMark. Because all parameters in C are passed by value, changes to this local variable are not reflected in the caller, so findMark in main never changes.
You need to change this function to take the address of an `int
void getMark(int *findMark, double crswk1[])
{
printf("Enter the mark you want to change: ");
scanf("%d", findMark);
}
Then you call this function from main like this:
getMark(&findMark, crswk1);
By passing in the address of findMark, the function can write to that address.
Also, your changePartMark function doesn't search through the entire array. It only looks at index i. But even that is a problem because you never set i.
You need to loop through the array to check your value against each element in the array.
int i;
for (i=0; i<4 i++) {
if(findMark == crswk1[i])
{
printf("It is equal");
}
else
{
printf("It is not equal");
}
}
Two main issues:
First, the number you enter is never passed back. When you write
void getMark(int findMark, double crswk1[]) {
printf("Enter the mark you want to change: ");
scanf("%d", &findMark);
}
then you read in the value in a local copy findMark, not in the one used by the caller. BTW: crswk1 is not used; So I'd suggest to write
int getMark() {
int findMark = 0;
printf("Enter the mark you want to change: ");
scanf("%d", &findMark);
return findMark;
}
Second, your void changePartMark(double crswk1[], int findMark) lacks a loop, and i is not initialized. Code could look like the following:
void changePartMark(double crswk1[], int findMark)
{
for (int i=0; i<4; i++) {
if(findMark == crswk1[i])
{
printf("It is equal");
}
else
{
printf("It is not equal");
}
}
}

Program to remove the duplicate elements from an array in c

I've tried to write a program that removes the duplicate values from an array. I've partly managed to do so since my program is able to remove any ONE of the numbers which are repeated TWICE in the array. So the problem is that if a number is repeated thrice only one of the number is removed, i.e. the other two is still left in the array, also if more than one number is repeated even then only the number which comes first in the array is removed. I really cannot understand what's wrong with my code and why is it unable to remove numbers that are repeated more than two times. I've already surfed through the internet regarding this issue and though I got different ways to remove the duplicate elements, I still don't know what's wrong with my code.
#include <stdio.h>
#include <stdlib.h>
int dup(int [],int);
int main()
{
int i,n,index,a[20];
printf("Enter n value \n");
scanf("%d",&n);
printf("Enter array values \n");
for(i=0;i<n;++i)
scanf("%d",&a[i]);
for(i=0;i<n;++i)
{
index=dup(a,n);
if(index==-1)
{
printf("No duplicate elements");
break;
}
else
{
a[index]=0;
for(i=index;i<n;i++)
a[i]=a[i+1];
n-=1;
}
}
printf("Output: \n");
for(i=0;i<n;++i)
printf("%d\n",a[i]);
return (EXIT_SUCCESS);
}
int dup(int a[],int size)
{
int i,j,pos=-1;
for(i=0;i<size;i++)
{
for(j=i+1;j<size;j++)
{
if(a[i]==a[j])
{
pos=j;
return pos;
}
}
}
if(pos==-1)
return pos;
}
OUTPUT
Enter n value
5
Enter array values
12
24
3
12
24
Output:
12
24
3
24
It clearly fails to remove the other repeated element "24". Also if a number was repeated thrice only one of the number would be removed.
for(i=0;i<n;++i) // <-------------------------------------- for i
{
index=dup(a,n);
if(index==-1)
{
printf("No duplicate elements");
break;
}
else
{
a[index]=0;
for(i=index;i<n;i++) // <--------------------------- for i
a[i]=a[i+1];
n-=1;
}
}
You are using the same loop variable for two loops, one nested inside the other. This cannot work. Use different variables. Live demo.
The Problem seem to lie in the if condition in second loop.
for (k = j; k < size; k++) {
arr[k] = arr[k + 1];
}
Simply put this piece of code after your if condition
if(a[i]==a[j])
and it will work.
My mistake, at first glence I thought you had problem with n after running this it worked.
#include <stdio.h>
#include <stdlib.h>
int dup(int [],int);
int main()
{
int i,n,index,a[20], count;
printf("Enter n value \n");
scanf("%d",&n);
count = n;
int j;
printf("Enter array values \n");
for(i=0;i<n;++i)
scanf("%d",&a[i]);
for(i=0;i<n;++i)
{
index=dup(a,n);
if(index==-1)
{
printf("No duplicate elements");
break;
}
else
{
a[index]=0;
for(j=index;j<n;j++)
a[j]=a[j+1];
n-=1;
}
}
printf("Output: \n");
for(i=0;i<n;++i)
printf("%d\n",a[i]);
return (EXIT_SUCCESS);
}
int dup(int a[],int size)
{
int i,j,pos=-1;
for(i=0;i<size;i++)
{
for(j=i+1;j<size;j++)
{
if(a[i]==a[j])
{
pos=j;
return pos;
}
}
}
if(pos==-1)
return pos;
}
OUTPUT
Enter n value
5
Enter array values
12
24
3
12
24
Output:
12
24
3
You should name your iterator variables better so you might not confuse them in nested loops, or as you do, use the same twice in a nested loop.
This skips all variables after your first removal.
and you don't have to do this
if(pos==-1)
return pos;
skip the if as it is not necessary and if at this position posis not -1then you would have no return which would be UB I think.

Segmentation fault in C? Arrays, pointers, functions

Hi due to my lack of knowledge in C (second year in college). Compiler ate my code and built the app. But after accepting first value - numOfIntegers it stops working and debugging tells that the segmentation has been failed. SIGSEGV.
How to fix that?
There is the code:
#include <stdio.h>
#include <stdlib.h>
#include <conio.h>
/* -----------------------------------------
Program: Question 1
Author: Maggot #9
Email: maggot99999#gmail.com
ID: B00076450
Date: 16 September 2015
Purpose: Who knows?
------------------------------------------ */
void wait(int);
void controlMenu(int, int[]);
int sumOfIntegers(int, int[]);
int avgOfIntegers(int, int[]);
int prodOfIntegers(int, int[]);
int minInteger(int, int[]);
int maxInteger(int, int[]);
const char * getName (int value)
{
static char * arrayName[] = {"first","second","third", "fourth",
"fifth","sixth", "seventh", "eighth", "ninth", "tenth"};
static char badValue[] = "unknown";
if (value<10 && value>=0)
return arrayName[value];
else
return badValue;
}
int getValue(int numOfInteger)
{
int value;
wait(100);
printf("Please enter %s the value:", getName(numOfInteger));
scanf("%d",&value);
return value;
}
void prepare(int * numOfIntegers)
{
wait(300);
printf("Hey again that C stupid lang\n\n");
wait(200);
printf("Please enter how many values you want to put: ");
scanf("%d",numOfIntegers);
return;
}
void initialize(int numOfIntegers,int* arrayNum[])
{
int i;
for(i=0; i<(numOfIntegers); i++)
arrayNum[i] = getValue(i);
wait(500);
printf("\nPlease enter press any button to continue");
wait(100);
getch();
wait(600);
system("cls");
wait(200);
return;
}
int main()
{
int numOfIntegers;
prepare(&numOfIntegers);
int arrayNum[numOfIntegers];
initialize(numOfIntegers, &arrayNum[numOfIntegers]);
controlMenu(numOfIntegers, &arrayNum[numOfIntegers]);
return 0;
}
void controlMenu(int numOfIntegers, int arrayNum[])
{
int i;
char chooseNum;
printf("Please choose any of the following:\n\n1. The integers accepted\n2. The sum of the integers\n3. The average of the integers\n4. The product of the integers\n5. The smallest integer\n6. The largest integer\n0. Exit menu\n");
while(1)
{
chooseNum = getch();
switch(chooseNum)
{
case '0':
return;
case '1':
printf("\n>>> The integers are:");
for(i=0; i<(numOfIntegers); i++)
{
printf("\n>>> The %s is %d", getName((i+1)), arrayNum[i]);
}
break;
case '2':
printf("\n>>> The sum of integers is: %d", sumOfIntegers(numOfIntegers, &arrayNum[numOfIntegers]));
break;
case '3':
printf("\n>>> The average of integers is: %d", avgOfIntegers(numOfIntegers, &arrayNum[numOfIntegers]));
break;
case '4':
printf("\n>>> The product of integers is: %d", prodOfIntegers(numOfIntegers, &arrayNum[numOfIntegers]));
break;
case '5':
printf("\n>>> The smallest integer is: %d", minInteger(numOfIntegers, &arrayNum[numOfIntegers]));
break;
case '6':
printf("\n>>> The largest integer is: %d", maxInteger(numOfIntegers, &arrayNum[numOfIntegers]));
break;
default:
break;
}
printf("\n\n");
}
}
int sumOfIntegers(int numOfIntegers,int arrayNum[])
{
int sum=0;
for(int i=0; i<(numOfIntegers); i++)
sum += arrayNum[i];
return sum;
}
int avgOfIntegers(int numOfIntegers, int arrayNum[])
{
int average=0;
average = sumOfIntegers(numOfIntegers, arrayNum[numOfIntegers])/numOfIntegers;
return average;
}
int prodOfIntegers(int numOfIntegers, int arrayNum[])
{
int i,product=0;
for(i=0; i<(numOfIntegers); i++)
product *= arrayNum[i];
return product;
}
int minInteger(int numOfIntegers, int arrayNum[])
{
int i,smallest=0;
smallest = arrayNum[0];
for(i=1; i<(numOfIntegers); i++)
{
if(smallest>arrayNum[i])
smallest=arrayNum[i];
else
continue;
}
return smallest;
}
int maxInteger(int numOfIntegers, int arrayNum[])
{
int i,largest=0;
largest = arrayNum[0];
for(i=1; i<(numOfIntegers); i++)
{
if(largest<arrayNum[i])
largest=arrayNum[i];
else
continue;
}
return largest;
}
void wait(int ms)
{
Sleep(ms);
return;
}
I can see this fault in getName() which will access memory beyond the array bounds
if (value>10 || value<1)
return arrayName[value];
I believe you are using the wrong test, try
if (value <= 10 && value > 0)
return arrayName[value-1];
assuming value is in the range 1..10 as the textual array implies.
2) a fault in GetValue where you input into numOfInteger but return value, which is uninitialised.
3) in prepare the statement
scanf("%d",&numOfIntegers);
will not pass the input value back to the caller. You should have either passed a pointer to the variable, or returned the value input.
But there might be a lot else wrong. Build your program step by step, checking and trying to break it as you go (with absurd input). Pay attention to compiler warnings - the second fault I listed will generate one.
EDIT okay... let's examine function prepare which after removing noise is
void prepare(int numOfIntegers)
{
scanf("%d",&numOfIntegers);
return;
}
This inputs a value to the function parameter that was passed. This is legal, since you can use a function argument in the same way you can a local variable (perhaps subject to const qualification).
Although it's not a coding error, it does not achieve anything. 1) you usually pass an argument like this to be used by the function in some way, perhaps in its limits and/or in its prompt. 2) Altering the argument like this will not find its way back to the caller.
Here are two ways to deal with this.
A) the function returns the input value
int prepare(void)
{
int value;
scanf("%d", &value); // the address of value
return value;
}
...
int input = prepare();
printf("%d\n", input);
B) the function takes a pointer argument
void prepare(int *value)
{
scanf("%d", value); // value is already a pointer
}
...
int input;
prepare(&input);
printf("%d\n", input);

Counting arguments passed to scanf() in C

Is there any way to Count number of arguments passed to scanf() in C ? Specially, while assigning int arrays through scanf().
Example:
int array[1000], i;
for(i=0;i<1000;i++)
scanf("%d",&array[i]);
I need to count how many values are inserted by user
I don't think there's a built in way to do this, but why not just create a counter that increments when scanf returns successfully and break the loop otherwise?
int scanf_counter = 0;
int array[1000], i;
for(i=0;i<1000;i++) {
if(scanf("%d",&array[i] > 0) {
scanf_counter++;
} else {
break;
}
}
Although I'm not sure I understand your question exactly because you could always just find the size of the array by doing this
int size = sizeof(array)/sizeof(array[0])
Look the scanf() fragment carefully, thus:
include
int main()
{
double a[100000],mx=0;
int i,j,c=0;
printf("Enter as many numbers as you wish . Press Ctrl+D or any character to stop inputting :\n");
for(i=0;i<100000;i++)
{
if((scanf("%lf",&a[i]))==1)
c++;
//else break;
}
for(j=0;j<c;j++)
{
if(a[j]>mx) mx=a[j];
}
printf("You have inserted %d values and the maximum is:%g",c,mx);
return 0;
}

Resources