Partial array output includes garbage - c

Most of my experience is limited to SQL scripting for DBA functions. I am a security specialist and provide help to others on those topics, but I am learning C to aid in those other endeavors. I've been reading books, writing small programs, and expanding the difficulty level as I go. This is the first time I've had to reach out for help. I apologize if this has been asked, but I did search first and didn't find anything.
So far, my programs have always returned only the valid data from partially filled arrays. This particular one is not behaving the same even though I'm using the same for statement I have previously used with success. At this point I must have tunnel vision because I cannot seem to see where this is failing.
If there are fewer than 20 inputs, the printf output displays the remaining values with garbage. It would be greatly appreciated if someone could provide some guidance on what I'm overlooking. Thank you in advance.
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
struct grade
{
int id;
int percent;
};
#define maxCount 100
int main()
{
int *grade;
struct grade gradeBook[maxCount];
int count = 0;
char YN;
int i;
for(i = 0; i < maxCount; i++)
{
printf("Enter ID: ");
scanf("%d", &gradeBook[i].id);
printf("Enter grade from 0-100: ");
scanf("%d", &gradeBook[i].percent);
count++;
// Prompt to continue, break if done
printf("Do you want to Continue? (Y/N)");
scanf(" %c", &YN);
if(YN == 'n' || YN == 'N')
{
break;
}
}
void sort(struct grade gradeBook[],int cnt)
{
int i, j;
struct grade temp;
for (i = 0; i < (cnt - 1); i++)
{
for (j = (i + 1); j < cnt; j++)
{
if(gradeBook[j].id < gradeBook[i].id)
{
temp = gradeBook[j];
gradeBook[j] = gradeBook[i];
gradeBook[i] = temp;
}
}
}
}
printf("Grades entered and ordered by ID: \n");
for (i = 0; i < count; i++)
{
printf("\nID:%d, Grade: %3d\n", gradeBook[i].id,gradeBook[i].percent);
}
return 0;
}

If there are fewer than 20 inputs, the printf output displays the remaining values with garbage
What else did you expect?
If you have fewer than 20 inputs, then the remaining inputs have not been given any value. You say "partial array input" but you literally asked the computer to loop over the entire array.
It's really not clear what else you expected to happen here.
Perhaps loop to count the second time instead.

Related

What's the problem with my code? In the third last line in score[i], the program said that i is undeclared

I just started learning C language. So, I am running into a lot of problems. I thought declaring i under for loop is enough, and I can use the value of i for outside too. But I think, that was not the case. Can someone explain the situation, please.
# include <stdio.h>
int main(void)
{
int x;
printf("Enter how many numbers in arrays you want to input : ");
scanf("%i", &x);
int score[x];
for(int i= 0; i <= x; i++)
{
printf("Enter the score : ");
scanf("%i", &score[i]);
}
// in the below line the output said "i" is undeclared.
float average = score[i] / x;
printf("The average score is : %f", average);
}
The answer is fairly simple
because of where you decalred i it is only visable to the for loop.
To make i visable to the whole function all you need to do is:
int i = 0;
for (; i <=x; i++){
printf("Enter the score : ");
scanf("%i", &score[i]);
}
this makes i avaliable throughout the function
i is declared in the initialization section of a for statement. That means the scope and lifetime of that variable is the expressions in the for statement itself as well as the block statement it contains. Once the loop is done, the variable no longer exists.
You need to declare i outside of the loop if you want to use it outside of the loop.
int i;
for(i= 0; i <= x; i++)
That being said, you don't actually need to use i outside of the loop.
There are security issues associated with using scanf so don't use it for anything serious. That said, I tried to re-write your program properly, and it still has pretty rubbish input validation.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define INPUTTEXTLEN 20
#define MAXINPUTINT 1000
int inputint() {
char inputtext[INPUTTEXTLEN + 1] = {0};
long inputval;
while (1) {
fgets(inputtext, INPUTTEXTLEN, stdin);
if (strlen(inputtext) > 0) {
inputval = atoi(inputtext);
if ((inputval < MAXINPUTINT) && (inputval >= 0)) break;
}
}
return (int)inputval;
}
int main(void)
{
int x = 0;
printf("Enter how many numbers in arrays you want to input : ");
//scanf("%i", &x);
while (x <= 0) {
x = inputint();
}
int score[x];
float average = 0;
for(int i= 0; i < x; i++)
{
printf("Enter the score : ");
//scanf("%i", &score[i]);
score[i] = inputint();
average += score[i];
}
average /= x;
printf("The average score is : %f\n", average);
}

Learning C basics and need some help:

Basically, I'm trying to create a program where you can read up to 100 inputs from the keyboard.
The inputs must be numbers between [1,100] and when "0" is entered, the program exits the loop and displays an array of all the numbers entered except the number zero.
I'm trying to work with "while,for,if" statements but it's a bit difficult to understand the logic.
Could you guys help me and give me some tips and feedback? Sorry for my ignorance but I'm programming for the first time.
#include <stdio.h>
int main(){
int long ship;
int array[100];
for(ship = 0; ship < 100; ship++){
printf("Repaired ship: ");
scanf("%li", &ship[array]);
while(ship[array] == 0){
printf("\n\t");
for(ship = 0; ship < 100; ship++)
printf("%li ", ship[array]);
printf("\n\nRepaired ships: %li", ship);
}
}
if(ship == 100){
printf("\n\t");
for(ship = 0; ship < 100; ship)
printf("%li ", ship[array]);
printf("\n\nRepaired ships: %li", ship);
}
return 0;
}
I have edited your code with some minor corrections.
In the comments below the code, I help clarify the changes.
Code:
#include <stdio.h>
int main(){
int ship;
int long array[100];
for(ship = 0; ship < 100; ship++)
{
printf("Repaired ship: ");
scanf("%ld", &array[ship]);
if(array[ship]==0)
break;
}
ship=0;
while(array[ship] != 0)
{
printf("\n\t");
printf("%ld ", array[ship]);
ship++;
}
printf("\n\nRepaired ships: %d", ship);
return 0;
}
The long int is not needed for ship as 100 is not that big of a value.
If required, the long int will be used for array.
The format specifier %ld is required for long int.
The for loop handles the input.
We don't need a for loop inside the while as it already deals with the output.
The use array[ship] type notation instead of ship[array] as the former is more common.
This if statement is not needed:
if(ship == 100){
printf("\n\t");
for(ship = 0; ship < 100; ship)
printf("%li ", ship[array]);
printf("\n\nRepaired ships: %li", ship);
}

If character then redo the function

In C code.
This is the part I want to work on below. I want to be able to do... if a character value then say "not a number", however, because it is an array and it increments I'm not sure how to do such, newbie here, so please explain and show me an example how to do if possible. Have to enter up to 10 values.
So if:
Employee 1 = c
"Not a Number. Try again."
Employee 1 = 5
Employee 2 = 55
Employee 3 = g
"Not a Number. Try again."
Employee 3...etc
void getSalaries(float sal[], int size)
{
int i = 0;
for(i = 0; i < size; i++)
{
printf("Enter salary for Employee #%d: ", i + 1);
if (scanf("%f", &sal[i]) != 1)
{
printf ("Not a number. Please try again.\n");
break;
}
}
}
If you want to repeat something, you need a loop. If you don't know how many times you'll want to loop in advance, it's probably going to be a while loop. The following structure will achieve your goal cleanly:
while (1) {
printf("Enter salary for Employee #%d: ", i + 1);
scanf("%f", &sal[i]);
if (...valid...)
break;
printf("Not a Number. Try again.\n");
}
The value returned by scanf will help you determine if the input was valid. I will leave consulting the documentation and finishing that part of your homework to you.
Some help to get you started, scanf returns the number of successfully read items (matching % marks in format string). So you can evaluate this number and take action accordingly.
int n=scanf("%f", &sal[i]);
if (n !=1){
// do something here
}
Hint: There is a common problem with using scanf,in that it wont recover from a "bad" input, unless you empty the buffer by "eating" the bad string.
If you want to convince your teacher that you have a VERY BIG BRAIN /s, you could do something like this;
#include <stdio.h>
#include <string.h>
void getSalaries (float sal[], int size)
{
char *scan_fmt[2] = {
"%f", // Get float
"%*s%f" // Eat previous bad input, and get float
};
char *cli_mess[2] = {
"Enter salary for Employee #%d: ",
"Try again, for Employee #%d: "
};
for (int i = 0, n=1; i < size; i += n==1){
printf (cli_mess[n!=1], i + 1);
n = scanf (scan_fmt[n!=1], &sal[i]);
}
}
int main ()
{
float s[3];
getSalaries (s, 3);
return 0;
}

Having problems with 2D char arrays

So I've got an assignment where my program asks the brand (10 letters), model (10 letters), age (1986 - 2019) and cost (positive real number) of 10 cars and then wants the program to check which car is the oldest and to print out it's brand and model. I don't have a problem with the first part but with the second part.
The code is:
//First part
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define C 10
#define M 11
int main(void)
{
char brand[C][M];
char model[C][M];
int year[C];
float cost[C];
int i, len1, len2, min;
for(i=0; i<C; i++){
printf("Car %d\n", i+1);
do{
printf("Brand: ");
scanf("%s", brand[i]);
len1 = strlen(brand[i]);
} while(len1<0 || len1>10);
do{
printf("Model: ");
scanf("%s", model[i]);
len2 = strlen(model[i]);
} while(len2<0 || len2>10);
do{
printf("Year: ");
scanf("%d", &year[i]);
} while(year[i]<1986 || year[i]>2019);
do{
printf("Cost: ");
scanf("%d", &cost[i]);
} while(cost[i]<=0);
}
//Second part
year[0] = min;
for(i=0; i<10; i++)
if(year[i] < min){
min = year[i];
printf("\nThe oldest car is %s %s\n", brand[i], model[i]);
}
For some reason it either prints out gibberish in the place of brand[i] or if I lose the columns of the if statement prints out all the car brands and their models, where I only want the oldest one.
Aside from scanf not being recommended there are some problems with this code, first when you read the brand and model you do:
do{
printf("Brand: ");
scanf("%s", brand[i]);
len1 = strlen(brand[i]);
} while(len1<0 || len1>10);
The problem here is that you first write the string to brand[i] and then check if it's too long, but you have already written it into the array so if the string is longer than your space you already have a buffer overflow. Limit the size you can read with scanf using scanf("%10s, brand[i]) or better yet use fgets(brand[i], sizeof(brand[i]), stdin).
Next in the second part you use min without initializing it, and you overwrite the content of year[0] with it. You probably wanted something like:
min = 2020; // or a number that will be bigger than all your cars anyway
int older = 0;
i = 0;
for(i=0; i<C; i++){ // Use C here, you have it might as well use it instead of magic numbers
if(year[i] < min){
older = i;
min = year[i];
}
}
printf("\nThe oldest car is %s %s\n", brand[older], model[older]);
but bare in mind that this solution will print multiple cars if they are the oldest ones and have the same year

Expression must have class type error

I'm working on a homework assignment and I've hit a brick wall. I think I have all of the code that I need, I just need to get the program to compile. The object of the assignment is
Create a structure to hold student names and averages. The structure should contain a first name, last name and an integer grade average.
Then:
Write a program that will do the following:
1.) Create an array of pointers to these student structures.
2.) Prompt the user for names and averages.
3.) After you get the student’s information use malloc to provide the memory to store the information.
4.) Place the address of the student, returned by malloc, into the pointer array.
5.) AFTER the user indicates there are no more students:
Search the data entered and find the highest and lowest grade
average.
a)Print the name and grade for the highest grade
b)Print the name and grade for the lowest grade
c)Print the average of all grades entered
Here is my code:
#include "stdafx.h"
#include <string.h>
#include <stdlib.h>
#define SIZE 25
int enterStudents (int ePointArray[SIZE]);
void searchData (int *sPointArray, int *sHigh, int *sLow);
int calculateAvg (int, int *avgPointArray);
void printData (int, int *pHigh, int *pLow);
struct student
{
char firstName[20];
char lastName[20];
int average;
};
int main()
{
int pointArray[SIZE], high[3], low[3];
int i = 0, studentCounter, avgGrade;
for (i = 0; i < SIZE; i++)
pointArray[i] = 0;
studentCounter = enterStudents(pointArray);
searchData(pointArray, high, low);
avgGrade = calculateAvg(studentCounter, pointArray);
printData(avgGrade, high, low);
return 0;
}
int enterStudents (int ePointArray[SIZE])
{
char tempFname[20], tempLname[20], yesNo[2] = "y";
int tempAvg, counter = 0;
int *studPtr;
struct student aStud={"\0", "\0", 0};
while( counter < SIZE && strcmp(yesNo, "y")==0)
{
printf(" Enter first name: ");
scanf("%s", tempFname);
printf(" Enter last name: ");
scanf("%s", tempLname);
printf(" Enter grade average:");
scanf("%d", tempAvg);
strcpy(aStud.firstName, tempFname);
strcpy(aStud.lastName, tempLname);
aStud.average = tempAvg;
studPtr = malloc(sizeof(struct student));
ePointArray[counter] = *studPtr;
counter++;
printf("/n");
printf(" Do you have more students? yes or no:");
scanf("%s", yesNo);
}
return counter;
}
void searchData (int sPointArray[SIZE], int sHigh[3], int sLow[3])
{
int searchCounter = 0;
while( searchCounter = 0)
{
if( *sPointArray[searchCounter].average > *sPointArray[searchCounter+1].average)
{
sHigh[0] = &sPointArray[searchCounter].firstName;
sHigh[1] = &sPointArray[searchCounter].lastName;
sHigh[2] = &sPointArray[searchCounter].average;
}
if( *sPointArray[searchCounter].average < *sPointArray[searchCounter+1].average)
{
sLow[0] = &sPointArray[searchCounter].firstName;
sLow[1] = &sPointArray[searchCounter].lastName;
sLow[3] = &sPointArray[searchCounter].average;
}
searchCounter++;
}
}
int calculateAvg( int totalStudents, int avgPointArray[SIZE])
{
int sum = 0;
int avgCounter;
double overallAvg;
for( avgCounter = 0; avgCounter < totalStudents; avgCounter++)
sum = sum + *avgPointArray[avgCounter].average;
overallAvg = sum/totalStudents;
return overallAvg;
}
void printData (int pAverage, int pHigh[3], int pLow[3])
{
printf(" Highest Grade: %s %s %d", pHigh[0], pHigh[1], pHigh[3]);
printf("/n");
printf(" Lowest Grade: %s %s %d", pLow[0], pLow[2], pLow[3]);
printf("/n");
printf(" Average Grade: %d",pAverage);
}
The main chunk of problems come from the searchData function. In the if statements, every occurrence of *sPointArray and &sPointArray is underlined in red and the error reads
"Error: expression must have class type"
The same thing also happens in the calculateAvg function with *avgPointArray in the for loop. I know that the error is a fairly common problem for noobie C programmers (i.e myself) and that it generally has to do with writing the code as a function instead of a statement or something like that, but I can't for the life of me find where I have went wrong. Any help would be highly appreciated. I've been working at this for so long my vision is blurring.
Also, for anyone who solves this in like two seconds and wants proof that I'm a true idiot, there is an error in the enterStudents function where it says StudPtr = malloc(sizeof...). The error shows under the assignment symbol and says
"Error: a value of type "void*" cannot be assigned to an entity of type "int*".
I understand this concept in theory, but some advice for how to fix it would be highly appreciated.
Thank you in advance for any help.
You declare the sPointArray as an array of integers, but use it as an array of structures.

Resources