I don't understand this crash - c

This is my code for solving the problem "Students Marks Sum" in Hackerrank:
(Link: https://www.hackerrank.com/challenges/students-marks-sum/problem?)
#include <string.h>
#include <math.h>
#include <stdlib.h>
//Complete the following function.
int marks_summation(int* marks, int number_of_students, char gender) {
int result = 0;
switch (gender){
case 'b':
while(marks != NULL){
result += (*marks);
marks += 2;
}
case 'g':
++marks;
while(marks != NULL){
result += (*marks);
marks += 2;
}
break;
}
return result;
}
int main() {
int number_of_students;
char gender;
int sum;
scanf("%d", &number_of_students);
int *marks = (int *) malloc(number_of_students * sizeof (int));
for (int student = 0; student < number_of_students; student++) {
scanf("%d", (marks + student));
}
scanf(" %c", &gender);
sum = marks_summation(marks, number_of_students, gender);
printf("%d", sum);
free(marks);
return 0;
}
When I move this code into an IDE (in my situation, it's DEV C/C++), it was crashed when my debug ran into my function marks_summation.
Error in line:
result += (*marks);

The problem is in your assumption that if you move out of the range of dynamically allocated memory the pointer value will change to NULL:
while(marks != NULL){
result += (*marks);
marks += 2;
}
There are a number of approaches you can pick to iterate over such array.
You can calculate the memory address that will no longer be valid to read and check at each iteration if your pointer is smaller than it:
int marks_summation(int* marks, int number_of_students, char gender) {
int result = 0;
int* marksEnd = marks + number_of_students;
switch (gender){
case 'b':
while(marks < marksEnd){
result += (*marks);
marks += 2;
}
case 'g':
++marks;
while(marks < marksEnd){
result += (*marks);
marks += 2;
}
break;
}
return result;
}

Related

Inserting a number into dynamic array in C

I am a new to C and I need to make a function that inserts a number to a 2D dynamic array depending on what is its last number in octal representation. I tried doing something like this.
Function generating an array:
void genArr(int m, int n, unsigned int** arr) {
arr = (unsigned int**)malloc(m * sizeof(unsigned int*));
for (int i = 0; i < m; i++) {
arr[i] = (unsigned int*)malloc(n * sizeof(unsigned int));
}
}
Function to insert numbers:
void insertToArr(unsigned int** arr) {
unsigned int num;
printf("Enter a number: \n");
for (int i = 0; i < 100; i++) {
scanf("%d", &num);
if (num != 0) {
switch (num % 8) {
case 0:
break;
case 1:
arr[1][i] = num;
break;
case 2:
arr[2][i] = num;
break;
case 3:
arr[3][i] = num;
break;
case 4:
arr[4][i] = num;
break;
case 5:
arr[5][i] = num;
break;
case 6:
arr[6][i] = num;
break;
case 7:
arr[7][i] = num;
break;
}
}
else if (num == 0) {
break;
}
}
}
But I keep getting exception error:
Unhandled exception at 0x00007FF630C019DE in App4.exe: 0xC0000005: Access violation reading location 0x0000000000000010.
I'm stuck and don't really know what is wrong.

sum of all the digit of a number using while-loop in C

I'm trying to solve a problem (as the title already state). I've actually learned that I can do it with modulo operator (%). But the first code that I wrote is using the while-loop, so I'm trying to finish the code.
This is the code
int main()
{
char arr[1000000];
int i = 0;
int sum = 0;
printf("type the number = ");
scanf("%s", arr);
while(arr[i] != '\0'){
sum = arr[i] + sum;
i++;
}
printf("the total number is = %d", sum);
so the problem is it's actually printing out some huge amount of number.. I guess it's because of the array is in char, can someone help me how do I changed the value into int ?
You need to substract from the digit code the code of '0'.
Here you have the both versions (I have added some logic to accept the numbers with + & - at there beginning):
int sumdigitsStr(const char *num)
{
int sum = 0;
int first = 1;
while(*num)
{
if(isdigit(*num)) {sum += *num - '0'; first = 0;}
else
if(first && (*num == '-' || *num == '+'))
{
first = 0;
num++;
continue;
}
else
{
sum = -1; break;
} //error string contains non digits
num++;
}
return sum;
}
int sumdigits(long long num)
{
int sum = 0;
do
{
sum += abs((int)(num % 10));
}while((num = num / 10));
return sum;
}
#include <stdio.h>
int main()
{
int n;
scanf("%d", &n);
int d, sum = 0;
while (n != 0)
{
d = n % 10;
sum = sum + d;
n = n / 10;
}
printf("sum of digits is : %d", sum);
return 0;
}

C switch returns default inside if/else

I have the following problem: i have two switch statements. They work perfectly when separated, but the minute I put both of them into an if/else. switch always returns the default(error). I am sorry for the difficult wording, now I have copied in the whole program so you can check it, I have tried what you said, but it didn't seem to help. So for an example, when it asks for the number, my input is 2. Then it asks for what character do I want to choose (+,-,/,*), and no matter which I write in, it gives me the default output like I have type a wrong character.
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <math.h>
void tomb_beolvas(int *szamok);
void tomb_kiir(int *szamok);
void tomb_sorrend(int *szamok);
void sorrend_kiir(int *szamok);
void kalkulator(int *szamok);
int main() {
int szamok[10];
tomb_beolvas(szamok);
tomb_kiir(szamok);
tomb_sorrend(szamok);
sorrend_kiir(szamok);
kalkulator(szamok);
return 0;
}
void tomb_beolvas(int *szamok) {
int i;
srand(time(0));
for (i = 0; i < 10; i++) {
szamok[i] = rand() % (10) + 1;
}
return;
}
void tomb_kiir(int *szamok) {
int i;
for (i = 0; i < 10; i++) {
printf("%d\n", szamok[i]);
}
return;
}
void tomb_sorrend(int *szamok) {
int i;
int a, j;
for (i = 0; i < 10; ++i) {
for (j = i + 1; j < 10; j++) {
if (szamok[i] > szamok[j]) {
a = szamok[i];
szamok[i] = szamok[j];
szamok[j] = a;
}
}
}
return;
}
void sorrend_kiir(int *szamok) {
int i;
for (i = 0; i < 10; i++) {
printf("\n%d", szamok[i]);
}
return;
}
void kalkulator(int *szamok) {
char jel;
int a, b, donto;
printf("\nKerem valassza ki milyen modon szeretne megadni az adatokat:\n"
" 1.: egyben(peldaul 5. + 8.)\n"
" 2.: kulon(peldaul + aztan 5. es 8.)\n");
scanf("%d", &donto);
if (donto == 1) {
printf("\nKerem irja be hanyadik szamokat szeretne es koze hogy milyen kalkulaciot szeretne vegezni(pl.: 5 + 8):\n");
while (scanf("%d %c %d", &a, &jel, &b)) {
switch (jel) {
case '+':
printf("%d", szamok[a-1] + szamok[b-1]);
break;
case '-':
printf("%d", szamok[a-1] - szamok[b-1]);
break;
case '*':
printf("%d", szamok[a-1] * szamok[b-1]);
break;
case '/':
printf("%d", szamok[a-1] / szamok[b-1]);
break;
}
}
} else
if (donto == 2) {
printf("Adj meg egy jelet (+, -, *, /): ");
scanf("%c", &jel);
printf("add meg hanyadik szamokkal akarsz szamolni: ");
scanf("%d %d", &a, &b);
switch (jel) {
case '+':
printf("%d + %d = %d", szamok[a], szamok[b], szamok[a] + szamok[b]);
break;
case '-':
printf("%d - %d = %d", szamok[a], szamok[b], szamok[a] - szamok[b]);
break;
case '*':
printf("%d * %d = %d", szamok[a], szamok[b], szamok[a] * szamok[b]);
break;
case '/':
printf("%d / %d = %d", szamok[a], szamok[b], szamok[a] / szamok[b]);
break;
// operator doesn't match any case constant +, -, *, /
default:
printf("Error! operator is not correct");
}
}
return;
}
There is nothing wrong with your switch statements, however:
int szamok[]={};
You can't make an empty array, you should declare it with a size:
const int size = 10;
int szamok[10];
From what I can tell, you invoked undefined behavior by accessing szamok with an out of bounds index (which is any positive number, as you got an empty array).
I'm afraid your problem is a classic scanf() issue: instead of scanf("%c", &jel); you should use
scanf(" %c", &jel); // notice the initial space before the `%c`
This skips the newline left pending after the scanf("%d", &donto);.

Segmentation fault 11 using arrays

I am a beginner with coding and I got my code to compile but when I input integers, I get segmentation fault. Please help.
The problem is: I need to first get how many students there are then the next inputs will be the marks of those students. So if inputed 3, the next inputs should be 3 marks of the 3 students. Then the input should be either g(girl) or b(boy). From there, if boy, I need to sum up all the odd marks.
THIS IS MY CODE:
#include<stdio.h>
#include<stdlib.h>
int marks_summation(int* marks, int number_of_students, char gender){
int i=0, sum=0;
int marksforGirls=0, marksforBoys=0;
char g;
for(marks = 0; *marks <= number_of_students; marks++){
if(gender == g){
do{
if(marks[i]%2 == 0){
marksforGirls = marks[i];
i++;
sum += marksforGirls;
}
} while(*marks<=number_of_students);
}
else{
do{
if(marks[i]%2 != 0){
marksforBoys = marks[i];
i++;
sum += marksforBoys;
}
} while (*marks<=number_of_students);
}
}
return 0;
}
int main(){
int i=0, number_of_students=0;
int *marks=0;
int sum=0;
char gender;
scanf("%d",&number_of_students);
marks = (int*)malloc(number_of_students * sizeof(int));
for(i=0; i<number_of_students; i++){
scanf(" %d", &marks[i]);//for every marks put in, it will go into marks
}
scanf("%c",&gender);
marks_summation(marks, number_of_students, gender);
printf("%d", sum);
free(marks);
return 0;
}
The following line is not doing what you might think it does:
for(marks = 0; *marks <= number_of_students; marks++)
I believe you'd want to use an index to access each of marks elements.
As others have pointed out, the problem is in the for loop. Besides pointers being wrong, your loop condition is also wrong. Furthermore your function doesn't return anything. Also, both of your do-while loops are infinite loops.
Try this:
int mark_sum(int *marks, int number_of_students, char gender){
int sum = 0;
for(int i = 0; i < number_of_students; ++i){
if(gender = 'g'){
if(marks[i] % 2 == 0)
sum += marks[i];
} else {
if(marks[i] % 2 != 0)
sum += marks[i];
}
}
return sum;
}
Also, in main you need to actually store the value returned by the function:
int sum = mark_sum(marks, number_of_students, gender);

Sorting an array of structs in C with pointers

I have a coding assignment for my CIS class. The assignment is to write a program the will create an array of structures that will hold information on at max 10 dogs. At the end of the program, you are supposed to sort the array of dogs by either name or size. But I am unable to code the sorting of the array of dog. I was wondering how to sort the array of dogs for later use in the main function.
Code
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
struct Dog{
char name[20];
int weight;
int age;
int ageDogYears;
char size[7];
};
typedef struct Dog DG;
void calc(DG[], int);
void sort(DG[], int);
void display();
int main(){
DG dArray[10];
int x = 0;
char str[80], *i;
FILE *inFile;
inFile = fopen("dogfile.txt", "r");
if (inFile == NULL){
printf("Error opening file");
exit(1);
}
while(fgets(str, 80,inFile) != NULL){
i = strtok(str, ", ");
strcpy(dArray[x].name, i);
puts(dArray[x].name);
i = strtok(NULL, ", ");
dArray[x].weight = atoi(i);
printf("%d\n", dArray[x].weight);
i = strtok(NULL, ", ");
dArray[x].age = atoi(i);
printf("%d\n", dArray[x].age);
x++;
}
calc(dArray, x);
sort(dArray, x);
return 0;
}
void calc(DG dog[], int numDogs){
int y, i, total;
for(i = 0; i < numDogs; ++i){
if(dog[i].weight <= 20){
//sets the dog size to small
strcpy(dog[i].size, "Small");
for(y = 0; y < dog[i].age; ++y){
if(y == 0)
total += 15;
else if(y == 1)
total += 8;
else if(y == 2)
total += 5;
else
total += 4;
}
}
else if(dog[i].weight <= 50){
//sets the dog size to medium
strcpy(dog[i].size, "Medium");
for(y = 0; y < dog[i].age; ++y){
if(y == 0)
total += 14;
else if(y == 1)
total += 9;
else if(y == 2)
total += 7;
else
total += 5;
}
}
else{
//sets the dog size to Large
strcpy(dog[i].size, "Large");
for(y = 0; y < dog[i].age; ++y){
if(y == 0)
total += 12;
else if(y == 1)
total += 9;
else if(y == 2)
total += 8;
else
total += 7;
}
}
dog[i].ageDogYears = total;
total = 0;
}
}
void sort(DG dog[], int numDogs){
int sortType, i, y, temp;
printf("\n wlould you like to sort by name(N) or size(S): ");
scanf("%c", &sortType);
switch(sortType){
case 'N': case 'n':
for(i = 0; i < numDogs; ++i){
for(y = 0; y < (numDogs); ++y){
if(dog[y].weight > dog[y+1].weight){
temp = dog[y];
dog[y] = dog[y + 1];
dog[y + 1] = temp;
}
}
}
break;
default:
if((sortType != 's') && (sortType != 'S'))
printf("\n invalid input! Setting sort type to size.");
//sorting of dog names
}
}
Sample Input
Fluffy,23,6
Fido,65,7
Pepper,44,5
Bowser,75,10
Victor,10,2
Sassy,51,1
Any help would be much appretated! Thanks.
In my opinion, your error resides (despite of other comments I'll do below) in specifying %c as format descriptor to pass a pointer to int to match. You have to pass a pointer to char to make scanf(3) to select the proper place to put the character into. You probably are not getting the right character or no character at all (this leads to Undefined Behaviour in your program)
Some other problems are that you are using the weight field of the structure when requested to sort by name (on n input char) and other errors like this. This includes that you use y < (numDogs) in the inner loop limit condition (it must be y < (numDogs - 1), or you'll compare the y-esim with the y+1-esim element (out of array bounds)
Also, as you are using the same algorithm for both sorting options, I should include the switch statement inside the inner loop (where you do the comparison) as doing otherwise will force you to copy the same sorting code twice (for the overall sorting algorithm), as in:
for(i = 0; i < numDogs; ++i){
for(y = 0; y < (numDogs - 1); ++y){
int sortResultGreater;
switch (sortType) {
case 'n': case 'N':
sortResultGreater = strcmp(dog[y].name, dog[y+1].name) > 0;
break;
default: { /* this should be done as soon as you know the sorting type, not here inside the loop, of course */
static int not_already_printed = 1;
if (not_already_printed) {
printf("Error, sortType must be [nNsS], defaulting to n\n");
not_already_printed = 0; /* so we don't get here again */
}
} /* scope of not_already_printed finishes here */
/* no break used here to fallback to the next case */
case 's': case 'S':
sortResultGreater = dog[y].weight > dog[y+1].weight;
break;
} /* switch */
if(sortResultGreater){
temp = dog[y];
dog[y] = dog[y + 1];
dog[y + 1] = temp;
}
}
}

Resources