Multidimensional Array does not hold values - c

I have been trying to see where the problem is but couldnt find it. Every time, the values of array memory gives me 0, even though int count works and keeps counting as the struct data value, only array does not save the value.
#include<stdlib.h>
#include<stdio.h>
#define SIZE 1000
struct registers
{
int data;
} registerX;
void first(int *counter, struct registers* X1, int m[][2])
{
int value;
printf("Enter the value for the X\n");
scanf("%d", &value);
X1->data = value;
m[*counter][1] = X1->data;
*counter = ++*counter;
}
int main()
{
int memory[SIZE][2];
int choice;
int count = 0;
printf("Enter the instruction number:\n");
while(choice != 107)
{
scanf("%d", &choice);
if(choice == 101)
{
memory[count][0] = 101;
first(&count, &registerX, memory);
printf("%d\n", memory[count][1]);
printf("%d\n", memory[count][0]);
}
}
}

You have some problems in your code.
Firstly,choice in while(choice != 107) is uninitialized. To fix it,use a do...while loop instead of a while loop as you want the loop body to execute once before checking the condition.
Secondly,*counter = ++*counter; undefined behaviour has KerrekSB points out in his comment. To fix it,use (*counter)++;.
Lastly,you print uninitialized elements of your array in the last two printfs. The reason is that you increment *counter in the function which will also modify count in main as counter is a pointer which points to the address of count.

Related

Issues with printing structs in C

I'm incredibly new to this and have a school assignment I have to write a gradebook program that uses a custom struct to hold student IDs and grades. I have been trying unsuccessfully for days to figure out why it will not print properly, or when it does print (after a lot of shifting things around) it only prints the second set of input.
The gradebook.h section is the custom structure.
// gradebook.h
struct gradeID
{
int id;
char grades[25];
};
// Gradebook.h is a header file to define
// a global structure.
#include "gradebook.h"
#include <stdio.h>
#include <stdlib.h>
void sort(struct gradeID *, int);
int main(void)
{
// Variables and structure definitions
int ctr;
char contInput;
int i;
struct gradeID grade;
struct gradeID *identifier;
int *temps;
// Allocates 10 integers worth of memory for the program to use.
// If there is not enough memory, the program will print an error
// statement and terminate the program.
temps = (int *) malloc(10 * sizeof(int));
if (temps == 0)
{
printf("Not enough memory!\n");
exit(1);
}
// Prints basic instructions for the program
printf("\t\tGradebook Recorder\n");
printf("Input student IDs and grades.\n");
printf("These will be sorted by ID and printed.\n");
/* Creates a for loop that will continue until the program
hits the designated number of array elements. For the sake
of expediency, I have set this amount to 10, but it can be
changed as necessary.*/
for(i = 0; i < 10; i++)
{
printf("Input student ID:\n");
scanf(" %d", &grade.id);
printf("Input grade:\n");
scanf(" %s", grade.grades);
// This allows early exit of the program
printf("Do you have more grades to enter?\n");
printf("Y/N\n");
scanf(" %c", &contInput);
if(contInput == 'N' || contInput == 'n')
{
printf("Finalizing and printing input-\n\n");
break;
}
ctr++;
}
printf("Grades Sorted by Student ID:\n\n");
printf("\tStudent ID: Student Grade: \n");
for(i = 0; i < ctr; i++)
{
printf("\t%d", grade.id );
printf("\t%s", grade.grades);
}
identifier[i] = grade;
return(0);
free(temps);
}
void sort(struct gradeID identifier[], int counter)
{
int inner;
int outer;
struct gradeID temp;
// Loops for sorting
for(outer = 0; outer < counter - 1; ++outer)
{
for(inner = outer + 1; inner < counter; ++inner)
{
if(identifier[inner].id < identifier[outer].id)
{
temp = identifier[inner];
identifier[inner] = identifier[outer];
identifier[outer] = temp;
}
}
}
return;
}
The pointer identifier is uninitialized
struct gradeID *identifier;
So this statement
identifier[i] = grade;
independent on the value of i invokes undefined behavior.
In this for loop
for(i = 0; i < 10; i++)
{
printf("Input student ID:\n");
scanf(" %d", &grade.id);
printf("Input grade:\n");
scanf(" %s", grade.grades);
// This allows early exit of the program
printf("Do you have more grades to enter?\n");
printf("Y/N\n");
scanf(" %c", &contInput);
if(contInput == 'N' || contInput == 'n')
{
printf("Finalizing and printing input-\n\n");
break;
}
ctr++;
}
you are entering new data in the same object grade of the structure type. So the new data overrides the previous data stored in the object.
Moreover the variable ctr was not initialized
int ctr;
So this statement in the above for loop
ctr++;
also invokes undefined behavior.
The variable temps that points to a dynamically allocated array
temps = (int *) malloc(10 * sizeof(int));
is not used.
This statement
free(temps);
never gets the control because before it there is the return statement
return(0);
free(temps);
What you need is to define an array of the type struct gradeID as for example
struct gradeID grades[10];
and fill it with values.

Program stops after loop in function

My prog doesn't reach outArray function. it stops after loop of fillArray function. Why this happens. It looks strangely, cause it's simple void function and shouldn't return anything. This should continue run commands in main. And that stops as usual program without any problems and bugs
#include <stdio.h>
#define N 100
int enterNofArray();
void fillArray(int n, float arr[N]);
void outArray(int n, float arr[N]);
int main()
{
float arr[N], sum = 0.0, average;
int n;
//input
n = enterNofArray();
//compute
fillArray(n, &arr[N]);
//output
outArray(n, &arr[N]);
return 0;
}
int enterNofArray()
{
int n;
printf("Enter amount of array...\n");
scanf("%d", &n);
while (n < 1 || n > N)
{
printf("Incorrect!!\n");
printf("Enter in range 1 - 100...\n");
scanf("%d", &n);
}
return n;
}
void fillArray(int n, float arr[N])
{
int num;
for(int i = 0; i < n; i++)
{
printf("Enter number for array[%d times left]...\n", n - i);
scanf("%d", &num);
arr[i] = num;
}
}
void outArray(int n, float arr[N])
{
for(int i = 0; i < n; i++)
{
printf("%f ", arr[i]);
}
}
&arr[N] refers to the memory location (or lvalue) that contains the N-th (out of index!!!) element in the array.
That code invokes Undefined Behavior (UB).
So, you weren't actually passing the whole array to your functions, you were just attempting to pass the N-th element of that array... Read more about that expression here.
Change this:
fillArray(n, &arr[N]);
outArray(n, &arr[N]);
to this:
fillArray(n, arr);
outArray(n, arr);
Live Demo
The problem was that with your code n was corrupted, containing garbage value after the call to fillArray function. As a result, when outArray function was called, n had a garbage value, which resulted in an uncontrolled for-loop that ended in looping far further than the limits of your array, eventually accessing memory that you didn't own, thus causing a Segmentation Fault.
Not the cause of your problem, but I suggest you do scanf("%f", &num); in your fillArray function (after declaring num as a float of course), since you want to populate an array of floats.
Because you're send double pointer when you do this:
fillArray(n, &arr[N]);
outArray(n, &arr[N]);
Looks like:
fillArray(n, **arr);
outArray(n, **arr);
This happends so much when you work with Structures.

(C) Print an array of structs from a function that calls other function

I cooked a code for a program that asks the user to fill in information about a person (ReadDate/ReadPerson), then it asks for the range of people the user wants to print, and the function prints these people. (PrintRange)
I don't understand why the program is not working; it's stuck on the point when it should print the person... it's means there is probably a problem in either PrintPerson or PrintDate, or in the way I am calling these functions.
Here is my code:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef struct{
int day, month, year;
} Date;
typedef struct{
char *first_name, *last_name;
int id;
Date birthday;
} Person;
void ReadDate(Date *a)
{
printf("Enter the day: ");
scanf("%d", &a->day);
printf("Enter the month (1-12): ");
scanf("%d", &a->month);
printf("Enter the year: ");
scanf("%d", &a->year);
}
void ReadPerson(Person *b)
{
char temp_first_name[21];
char temp_last_name[21];
printf("Enter the first name: ");
gets(temp_first_name);
b->first_name = (char*)malloc(strlen(temp_first_name)+1);
strcpy(b->first_name,temp_first_name);
//need to check malloc (later)
printf("Enter the last name: ");
gets(temp_last_name);
b->last_name = (char*)malloc(strlen(temp_last_name)+1);
strcpy(b->last_name, temp_last_name);
//need to check malloc (later)
printf("Enter the id number: ");
scanf("%d",&b->id);
printf("Enter the birthday:\n");
ReadDate(&b->birthday);
}
int ReadAllDate (Person *b)
{
//Person* b;
int count=1;
char choice;
printf("Would you like to enter a person?(y,n)\n");
choice = getchar();
while(choice == 'y')
{
b = (Person*)malloc(1 * sizeof(Person));
getchar();
ReadPerson(b);
printf("Done!\n");
count++;
getchar();
printf("Would you like to add a person?(y,n)\n");
choice = getchar();
}
count--;
printf("The number of entered persons is %d\nBye\n", count);
return count;
}
void PrintPerson(Person b)
{
printf("%s %s %d\n", b.first_name, b.last_name, b.id);
}
void PrintDate(Date a)
{
printf("%d // %d // %d\n",a.day,a.month,a.year);
}
void PrintRange(Person *b,int count,int ind1,int ind2)
{
int i;
if (ind1<0 || ind1>ind2 || ind2>count)
{
printf("error! you slip out from the limits of the array.\n");
}
else
{
for (i=ind1; i<=ind2; i++)
{
PrintPerson(*(b+i));
PrintDate((b+i)->birthday);
}
}
}
int main(int argc, const char * argv[])
{
Person* b;
int count;
int ind1, ind2;
count = ReadAllDate(b);
printf("insert the first index (the smaller): ");
scanf("%d", &ind1);
printf("insert the second index (the bigger): ");
scanf("%d", &ind2);
PrintRange(b, count, ind1, ind2);
}
The problem is that nowhere you are actually creating an array of Person objects. The function ReadAllDate() never changes the value of the variable b in main(). Instead, for every person you read in, it allocates memory for it, and stores the pointer to that Person in the local variable b in ReadAllDate(). Every time it does it, it forgets the previous value of b.
In main(), the value of b is unitinialized all the time. When you are trying to print persons, it will most likely crash or print garbage.
I see other issues with your code:
Don't use gets(), always use fgets(). The former can write past the end of the buffer you are providing.
Don't do malloc(strlen(...))+strcpy(), use strdup().
Start with count = 0, that way you don't need the count-- in ReadAllDate(). As a computer programmer, it's best to count from zero instead of one.
Write b[i] instead of *(b+i), and b[i].birthday instead of (b+i)->birthday.

How to assign value to procedure's struct parameter?

I'm making a program to input some data to array of struct. When I tried to assign temporary struct temp to procedure's struct parameter *daf, the program's always force closed. Here's my code:
#include <stdio.h>
typedef struct {
int num;
char name[50];
float value;
} Mhs;
typedef Mhs ListMhs[50];
void inputData(int nEf, ListMhs *daf);
int main() {
ListMhs listmhs;
inputData(5, &listmhs);
return 0;
}
void inputData(int nEf, ListMhs *daf) {
int i;
ListMhs temp;
for (i=0; i<nEf; i++) {
printf("Num: ");
scanf("%d", &temp[i].num);
printf("Name: ");
scanf("%s", &temp[i].name);
printf("Value: ");
scanf("%f", &temp[i].value);
}
//assign value
for (i=0; i<nEf; i++) {
*daf[i] = temp[i];
}
}
Your problem lies in the line *daf[i] = temp[i];
[] has higher precedence than *
So it should be (*daf)[i] = temp[i];
The original line *daf[i] = temp[i]; is actually *(daf[i]) = temp[i];and was trying to treat daf as an array of ListMhs and taking the ith element of it and then dereferencing it. Obviously as you were only passing in a pointer to one ListMhs, as soon as i was greater than 0 you would have problems. The program probably tried to write to protected memory after the second or third iteration, which is why it hard crashed. If you had a debugger of some sort attached you would have probably got a more helpful error.
Here is the list of C++ operator precedence: http://en.cppreference.com/w/cpp/language/operator_precedence

Endless loop in C; for loop seems valid

I am a student trying to learn c coming from c++. I wrote the following code and it compiles fine; however, when I execute it I get an endless loop when calling the print function. I looked over the code and it seems to be valid to me, so why is it printing an endless loop?
#include <stdio.h>
#include <stdlib.h>
struct student
{
int id;
int score;
};
void generate(struct student *students, int n)
{
int randomId = rand () % n + 1;
int randomTestScore = rand() % 100 + 1;
students->id = randomId;
students->score = randomTestScore;
}
void sort(struct student *students, int n)
{
/*using insertion sort*/
for (unsigned int i = 1; i < n; ++i)
{
int next = students[i].score;
int j = i;
while(j > 0 && students[j-1].score > next)
{
students[j].score = students[j-1].score;
j--;
}
students[j].score = next;
}
}
void print(struct student *students, int n)
{
for (unsigned int i = 0; i < n; i++)
{
printf("Student at position No: %d Test Score: %d\n", i+1, students[i].score);
}
}
int main()
{
/*user enters num of students to create scores for*/
int num_students;
printf("Enter Num of students\n");
scanf("%d", num_students);
/*allocate memory for the amount of students user wants*/
struct student *userStudents = malloc(num_students*sizeof(struct student));
printf("Randomly filling students IDs & Test Scores...\n");
for (unsigned int i = 0; i < num_students; ++i)
{
generate(&userStudents[i], num_students);
}
printf("Array of students before sorting:\n");
print(userStudents, num_students);
printf("\nNow, sorting students by test scores...\n\n");
sort(userStudents, num_students);
printf("Array of students after sorting:\n");
print(userStudents, num_students);
return 0;
}
To use scanf() correctly it needs to alter the passed variable in place, and since there is no pass by refrence in c, you need to pass the address of the variable, so scanf() is able to modify it though a pointer, hence you need to use the & operator, but that is not enough.
The scanf() family of functions, return a value that must be checked before you can access the scanned values, you should never ignore that value, under any circumstances you should check for it.
What your code is doing is called undefined behavior, it's interpreting the passed integer as if it was a pointer, which is undefined behavior.
To prevent that you can activate compiler warnings, many compilers know what kind of parameter the *f functions expect, i.e. the functions which take a string as a format to be parsed and to allow the function to correctly grab the rest of the parameters passed via variable arguments to it.
The correct way to call scanf() in your program is
if (scanf("%d", &num_students) != 1)
return 1;
that is, from main() and hence it's ending the program, because you can't continue after that condition was true, in that case what actually happens is that num_students is not initialized, that would once again cause undefined behavior.
Change the call to scanf to:
/*
* correct way of calling scanf, passing the address of the wanted variable
*/
scanf("%d", &num_students);
^
This elliminates segmentation faults and makes the code runs OK on my machine.
I had a previous hint that you'd need to change your declaration of userStudents to a pointer to pointers, however I was incorrect. You are clearly correctly allocating enough contiguous memory to hold all of your structs pointed by *userStudents.

Resources