Unwanted output on second pass using strcpy - c

I'm reading a book called "C programming Absolute Beginners Guide."
The following program uses some if loops and strcpy to store some character arrays provided by the user. The first pass of strcpy works fine. The second produces garbage. I understand the array needs a \0 to end. According to the book, strcpy does this automatically. What am I missing?
#include <stdio.h>
#include <string.h>
main()
{
int ctr, numMovies, rating, favRating, leastRating;
char movieName[40], favorite[40], least[40];
favRating = 0;
leastRating = 0;
do {
printf("How many movies have you seen this year? ");
scanf(" %d", &numMovies);
if (numMovies < 1)
{
printf("No movies! How can you rank them?\nTry again\n\n");
}
} while (numMovies < 1 );
for (ctr = 1; ctr <= numMovies; ctr++)
{
printf("\nWhat's the name of the movie? ");
printf("(1-word titles only!) ");
scanf(" %s", movieName);
printf("On a scale of 1 to 10, what would ");
printf("you rate it? ");
scanf(" %d", &rating);
if (rating > favRating)
{
strcpy(favorite, movieName);
favRating = rating;
}
printf("%s", movieName);
if (rating < leastRating)
{
strcpy(least, movieName);
leastRating = rating;
}
}
printf("\nYour Favorite Movie was %s.\n", favorite);
printf("\nYour Least-favorite movie was %s.\n", least);
return 0;
}

Because you initialize leastRating to zero you won't have a least favorite unless the rating is negative. Not sure that's what you want.
The best suggestion is from #xing, add a include
#include <limits.h>
and initialize you best and worst like this;
favRating = INT_MIN;
leastRating = INT_MAX;

Related

How to give whitespace in string in structure in C Language [duplicate]

This question already has answers here:
How do you allow spaces to be entered using scanf?
(11 answers)
Closed 2 years ago.
Hello senior programmers! I am new in programming. I am having trouble making my program run efficiently. My code works perfectly fine when I do not give white space. But when I give white space while writing the name or route it doesn't work.
Example: Driver's Name: ALI ( work perfectly )
Example: Driver's Name: ALI ALI ( not working )
I want to write all the char with white space. I have already tried every possible way. I have commanded all the ways which I have tried. I am a beginner. It is my college assignment. Kindly, please help me, How can I fix this?
/*
You manage a travel agency and you want your n drivers to input their following details:
1. Name
2. Driving License No
3. Route
4. Kms
Your program should be able to take n as input(or you can take n=3 for simplicity) and your drivers will start inputting their details one by one.
Your program should print details of the drivers in a beautiful fashion.
User structures.
*/
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#define Max_Size 1000
#define max 1000
struct Drivers
{
char Name[150];
char Driving_License_No[150];
char Route[150];
char Kms[50];
int positionNo;
} drivers[Max_Size];
int main()
{
int totalDrivers;
char name[200];
printf("Enter the total numbers of drivers\n");
scanf("%d", &totalDrivers);
for (int i = 0; i < totalDrivers; i++)
{
drivers[i].positionNo=i+1;
printf("\nFor Driver Id no. %d,\n", drivers[i].positionNo);
printf("Enter the full name: ");
scanf("%s", &drivers[i].Name);
// scanf("%[^\n]",drivers->Name);
// scanf("%[^\n]s",drivers->Name);
// fgets(drivers.Name, 150, stdin);
// gets(Name);
// gets(driver.Name);
printf("Enter the Driving License no : ");
scanf("%s", &drivers[i].Driving_License_No);
printf("Enter the Driving Route : ");
scanf("%s", &drivers[i].Route);
printf("Enter the Driving KM's : ");
scanf("%s", &drivers[i].Kms);
}
printf("The Information of all drivers are given below\n");
for (int i = 1; i < totalDrivers; i++)
{
printf("\nDriver Id no.: %d\n", i + 1);
printf("Driver's Name: ");
puts(drivers[i].Name);
printf("Driving License no: %s", drivers[i].Driving_License_No);
printf("\n");
printf("Driving Route: %s", drivers[i].Route);
printf("\n");
printf("Driving KM's: %s", drivers[i].Kms);
printf("\n");
}
return 0;
}
There are multiple issues:
parsing a string with embedded white space can be done with %[^\n] in scanf().
you should tell printf the maximum number of characters to store into the destination arrays to avoid potential undefined behavior on invalid input.
&drivers[i].Name is not a char *, you should pass drivers[i].Name.
when printing the details, you start at 1 instead of 0.
to input multiple strings with embedded spaces, which is likely required here, you should use " %[^\n]" with an initial space to skip the pending newline and any initial spaces.
Here is a modified version:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#define Max_Size 1000
#define max 1000
struct Drivers {
char Name[150];
char Driving_License_No[150];
char Route[150];
char Kms[50];
int positionNo;
} drivers[Max_Size];
int main() {
int totalDrivers;
char name[200];
printf("Enter the total numbers of drivers\n");
if (scanf("%d", &totalDrivers) != 1)
return 1;
if (totalDrivers > Max_Size) // avoid overflowing the drivers array;
totalDrivers = Max_Size;
for (int i = 0; i < totalDrivers; i++) {
drivers[i].positionNo = i + 1;
printf("\nFor Driver Id no. %d,\n", drivers[i].positionNo);
printf("Enter the full name: ");
scanf(" %149[^\n]", drivers[i].Name);
printf("Enter the Driving License no: ");
scanf(" %149s", drivers[i].Driving_License_No);
printf("Enter the Driving Route: ");
scanf(" %149s", drivers[i].Route);
printf("Enter the Driving KM's: ");
scanf(" %49s", drivers[i].Kms);
}
printf("The Information of all drivers are given below\n");
for (int i = 0; i < totalDrivers; i++) {
printf("\n");
printf("Driver Id no.: %d\n", i + 1);
printf("Driver's Name: %s\n", drivers[i].Name);
printf("Driving License no: %s\n", drivers[i].Driving_License_No);
printf("Driving Route: %s\n", drivers[i].Route);
printf("Driving KM's: %s\n", drivers[i].Kms);
}
return 0;
}
See instead of using %s as format specifier you should use %[^\n] as the format specifier while taking input in scanf to take the input with white spaces.
printf("Enter the full name: ");
scanf("%[^\n]", drivers[i].Name);
In case of any query please feel free to ask.

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

Partial array output includes garbage

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.

New to programming. Need help adjusting code to allow for undetermined number of students

Need help adjusting code to allow for undetermined number of students. Tried to modify with help I received last week, but it seems like I am not doing it correctly.
#include <stdio.h>
int main ()
{
/* variable definition: */
char StudentName[100];
float ExamValue, Sum, Avg;
int students,exams;
// Loop through 5 Students
for (students=0; students <5 ; students++)
{
// reset Sum to 0
Sum =0.0;
printf("Enter Student Name \n");
scanf("%s", StudentName);
// Nested Loop for Exams
for (exams=0; exams < 3; exams++)
{
printf ("Enter exam grade: \n");
scanf("%f", &ExamValue);
Sum += ExamValue;
}
Avg = Sum/3.0;
printf( "Average for %s is %f\n",StudentName,Avg);
}
return 0;
}
Not sure how I need to go about changing the code. Any help will be greatly appreciated
Not sure I understand correctly, I understood you want to loop an undertemined amount of students.
I will assume you want to stop if certain keyword is added as a student name, let's say "quit".
Without changing your structure much, it would look like this.
#include <stdio.h>
#include <stdbool.h>
#include <string.h>
int main (){
char StudentName[100];
float ExamValue, Sum, Avg;
int students,exams;
bool in = true;
while (in) {
Sum =0.0;
printf("Enter Student Name \n");
scanf("%s", StudentName);
if( strcmp(StudentName, "Quit") == 0 || strcmp(StudentName, "quit") == 0){
in = false;
break;
}
for (exams=0; exams < 3; exams++){
printf ("Enter exam grade: \n");
scanf("%f", &ExamValue);
Sum += ExamValue;
}
Avg = Sum/3.0;
printf( "Average for %s is %f\n",StudentName,Avg);
}
return 0;
}

Can't nail the problems with this code

Ok so I got this thing going here.
I keep getting a few errors.
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <stdlib.h>
#include <cstdio>
//functions called
int get_lmt();
int get_total_trash();
void print_output(int, int);
//why is it void?
int main(void)
{
char hauler[100];
int t_trash=0, lmt=0;
printf("Hello \n What is your name: ");
fflush(stdin);
scanf("%s", &hauler);
t_trash = get_total_trash();
lmt = get_lmt();
printf("Name: %s\n", &hauler);
print_output(lmt, t_trash);
system("pause");
return 0;
}
int get_total_trash()
{
char yn = 'y';
int t_trash = 0, trash=0;
while (yn != 'n')
{
printf("What is your trash: ");
fflush(stdin);
scanf("%i", &trash);
t_trash = trash + t_trash;
printf("Do you have more trash tons? (y or n): ");
fflush(stdin);
scanf("%c", &yn);
}
return t_trash;
}
int get_lmt()
{
int lmt = 0;
printf("What was last months trash: ");
fflush(stdin);
scanf("%i", &lmt);
return lmt;
}
void print_output(int lmt, int t_trash)
{
float rate = 350.00, charge;
int sum=0, total=0;
if (lmt > t_trash)
{
printf("Total trash tons: %i\n", &t_trash);
printf("Last month's trash: %i\n", &lmt);
printf("Rate: $ %.2f\n", &rate);
}
else
{
printf("What is your tonnage rate: ");
fflush(stdin);
scanf("%.2f\n", &charge);
sum = t_trash - lmt;
total = sum * charge;
rate = rate + total;
printf("Total trash tons: %i\n", &t_trash);
printf("Last month's trash: %i\n", &lmt);
printf("Rate: $ %.2f\n", &rate);
}
}
Now what it should be doing is, The main should be calling the functions on screen as needed.
Now i did all of this with cout cin and it works fine no problems. But when I run this (this is modified to the printf and scanf) it says:
OK UPDATE: Got a ton of it to work. Just one more thing and I should be good. The outcome will not go as expected.
Instead of an output of
last months trash: 100 (asked at the end of the loop)
trash tonnage: 50 (accumulated in the loop)
rate: 350.00 (float variable)
(this is if last month trash was > this month.)
I get just bad numbers all around. It makes no mathematical sense.
Other then that it works fine.
Does the code the the last function look wrong to you guys?
Lots of problems with this code. Lots of them.
1) print_output defintiion takes in a char[100] (char*), print_output declatation takes a char
2) When you pass hauler into print_output, you are passing in hauler[100] (a char, and one pass the end of the array to boot)
3) printf("Name: %s\n", &hauler); hauler is of type char[100] (char*), so &hauler is char**.
there is probably more.

Resources