Related
When I add workers thru main in for loop, everything is fine. But when I add them with one of my functions insert_one_with_pointers or insert_multiple_workers, and check all workers with my third function display_all_workers, I see that something is wrong.
Their id values are not correct and sometimes the program crashes or it doesn't display them all of them, just the ones thet were inserted in the beginning in main.
I just started working with structures and functions so I'm not sure what exactly is causing this, but I think that it has to do with my probably incorrect usage of i. I've been trying to fix this for quite a while, but unsuccessfully.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
struct Worker {
int id;
char name[40];
int age;
};
void insert_one_with_pointers(struct Worker *niz, int i) {
niz[i].id = i + 1;
printf("\nWhat is name of %d. worker: ", i + 1);
scanf("%s", niz[i].name);
printf("What is age of %d. worker: ", i + 1);
scanf("%d", &niz[i].age);
}
void insert_multiple_workers(struct Worker niz[], int i, int number) {
int j;
for (j = i; j < number; j++) {
niz[j].id = j + 1;
printf("\nWhat is name of %d. worker: ", j + 1);
scanf("%s", niz[j].name);
printf("What is age of %d. worker: ", j + 1);
scanf("%d", &niz[j].age);
}
}
void display_all_workers(struct Worker niz[], int i) {
printf("\nAll workers:\n");
for (int j = 0; j < i; j++) {
printf("\nID: %d", niz[j].id);
printf("\nName: %s", niz[j].name);
printf("\nAge: %d", niz[j].age);
}
}
int main() {
int choice, i, m, number;
printf("Add a number of workers and then their info: ");
scanf("%d", &i);
struct Worker niz[i];
for (int j = 0; j < i; j++) {
niz[j].id = j + 1;
printf("\nWhat is name of %d. worker: ", j + 1);
scanf("%s", niz[j].name);
printf("What is age of %d. worker: ", j + 1);
scanf("%d", &niz[j].age);
}
while(1) {
printf("\nChoose a function:\n1 - Add a worker using pointers\n2 - Add n workers\n3 - Display all workers\n4 - Leave\n");
scanf("%d", &choice);
switch(choice) {
case 1:
insert_one_with_pointers(niz, i); i++;
break;
case 2:
printf("\nHow many workers do you want to insert? ");
scanf("%d", &m);
number = i + m;
insert_multiple_workers(niz, i, number);
break;
case 3:
display_all_workers(niz, i);
break;
case 4:
return 0;
}
}
return 0;
}
Edit: I followed everything that replies to my post said, which fixed most of it.
The final change was that I added i = i + m; below the call for function insert_more_workers in main. Now everything works as it should.
Continuing from my comment, the primary problem you face is that you set the number of workers (i) at the beginning of your program and you use that value to size your niz VLA (Variable Length Array). Once set, it cannot be changed. So when you attempt to add additional workers later using you menu, you attempt to write beyond the end of your array (resulting in Undefined Behavior) causing the problem output you see.
Your alternatives are either to dynamically allocate storage for your workers and keep track of how many you have allocated and how many you have filled, and when filled == allocated you reallocate more storage. Another option is simply to declare some reasonable max number of workers you will have and then declare an array of that many, keeping track of the number added and when the number of workers added equals the array size -- just indicate the array is full. (though you can't expand the number of workers here)
An additional note about using VLAs. Beginning with the C11 standard, compiler support for VLAs was made optional -- though I don't know of any compilers that don't continue to support them.
Weaknesses In Your Code
The most glaring weakness is your failure to check the return of scanf() when a numeric conversion is required. That invites problems. Why? scanf() can fail in two ways (1) a matching-failure where the input provided doesn't match the conversion specified. (e.g. user enters "twenty-one" for age instead of 21). When a matching failure occurs, character extraction from the input buffer ceases at the point of failure -- leaving "twenty-one" unread in the input buffer -- just waiting to bite you on your next attempted input.
In fact if a matching-failure occurs before you enter you menu while(1) loop -- your code locks into an infinite loop.
(2) scanf() can fail with an input-failure where EOF is reached before the first valid conversion takes place. (a user can cancel input by generating a manual EOF with Ctrl + d, or `Ctrl + z on windows) If you don't check the return, you cannot handle either case.
Another weakness with your approach is using scanf() for user-input. Why? Because in the matching-failure case, or after any use, characters are left in stdin unread. In the normal case the '\n' is left unread, and if your next input isn't taken with scanf() and you don't extract the unread character(s), your next input will fail. This is one of the (many) pitfalls associated with using scanf(). Instead, as a general proposition, all user-input should be taken using fgets() and then any conversions should be handled by sscanf() from the buffer filled by fgets(). That way, with a sufficiently sized buffer, you are guaranteed to consume each line of input regardless of whether the subsequent conversion fails. No characters are left unread to impact the next input attempt.
Alternatives Approach
While the two different input functions may be a homework requirement, there is no need for different input functions to read one, and multiple workers. Just write a single function that can handle both. Since your input function can succeed or fail, you need to provide a meaningful return to the caller, so the success or failure of your input function can be validated at the point it was called. void return type is only sufficient for functions that have no bearing on the continued operation of your code (like print functions, etc..).
In your switch() statement, you should handle menu entries that are out-of-range. What if the user slips and enters 5 or -32 or "foo" for that matter? We addressed the matching-failure above, but to handle input that is out-of-range, simply providing a default: case can suffice. For example:
default: fputs (" error: selection out of range.\n", stderr);
break;
Is all that is needed to cover:
Choose a function:
1 - Add a worker using pointers
2 - Add n workers
3 - Display all workers
4 - Leave
5
error: selection out of range.
To make your code more readable, understand that adjacent string-literals are joined together during compilation. This allows you to provide much more readable code. For example, your menu can be written as:
printf ("\nChoose a function:\n"
" 1 - Add a worker using pointers\n"
" 2 - Add n workers\n"
" 3 - Display all workers\n"
" 4 - Leave\n");
Your display_all_workers() function could also benefit from that approach reducing the number of calls to printf() from 3-to-1.
Putting all the suggestions above together, and using a standard array of 200 elements for your workers array, you could rewrite your code as:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MAXWRKRS 200 /* if you need a constant, #define one (or more) */
#define MAXC 1024
struct Worker
{
int id;
char name[40];
int age;
};
int insert_workers (struct Worker *workers, int *nworkers, int toadd)
{
char buf[MAXC] = "";
int i = 0, start_index = *nworkers;
size_t len = 0;
while (i < toadd) { /* loop nworkers times */
int current = i + start_index;
if (current == MAXWRKRS) { /* check array bounds */
puts ("(workers array full)");
return i;
}
printf ("\nWhat is name of %d. worker: ", current + 1);
if (!fgets (buf, MAXC, stdin)) { /* read all input into buf */
return i;
}
buf[(len = strcspn (buf, "\n"))] = 0; /* trim '\n', save length */
memcpy (workers[current].name, buf, len + 1);
for (;;) { /* loop continually until valid integer entered */
printf ("What is age of %d. worker: ", current + 1);
if (!fgets (buf, MAXC, stdin)) { /* read all input into buf */
return i;
}
/* parse needed information from buf with sscanf() */
if (sscanf (buf, "%d", &workers[current].age) != 1) { /* check return */
fputs (" error: invalid integer input.\n", stderr);
continue;
}
else {
workers[current].id = current + 1; /* set worker ID, done */
*nworkers += 1; /* all conditions met - update worker count */
break;
}
}
i++;
}
return i; /* return number of workers added (can validate in caller) */
}
void display_all_workers (struct Worker *workers, int nworkers)
{
puts("\nAll workers:");
for (int j = 0; j < nworkers; j++) {
printf ("\n ID : %d\n"
" Name : %s\n"
" Age : %d\n",
workers[j].id, workers[j].name, workers[j].age);
}
}
int main()
{
char buf[MAXC] = ""; /* buffer for all user input */
int i, nwrkrs = 0; /* tmp counter & number of workers */
struct Worker workers[MAXWRKRS]; /* array of workers */
printf("Add a number of workers and then their info: ");
if (!fgets (buf, MAXC, stdin)) {
puts ("(user canceled input)");
return 0;
}
if (sscanf (buf, "%d", &i) != 1) {
fputs ("errur: invalid integer input.\n", stderr);
return 1;
}
printf ("%d workers added\n\n", insert_workers (workers, &nwrkrs, i));
while(1) {
int choice;
printf ("\nChoose a function:\n"
" 1 - Add a worker using pointers\n"
" 2 - Add n workers\n"
" 3 - Display all workers\n"
" 4 - Leave\n");
if (!fgets (buf, MAXC, stdin)) {
puts ("(user canceled input)");
return 0;
}
if (sscanf (buf, "%d", &choice) != 1 ) {
fputs ("error: invalid integer input.\n", stderr);
continue;
}
switch (choice) {
case 1 : insert_workers (workers, &nwrkrs, 1);
break;
case 2 : printf("\nHow many workers do you want to insert? ");
if (!fgets (buf, MAXC, stdin)) {
puts ("(user canceled input)");
return 0;
}
if (sscanf (buf, "%d", &i) != 1) {
fputs ("error: invalid integer input.\n", stderr);
break;
}
insert_workers (workers, &nwrkrs, i);
break;
case 3 : display_all_workers (workers, nwrkrs);
break;
case 4 : return 0;
default: fputs (" error: selection out of range.\n", stderr);
break;
}
}
return 0;
}
(note: how the number of workers nworkers is passed as a pointer to the insert_workers() function so that the number of workers can be updated within the function when a valid name and age has been entered)
One immediate benefit of the use of fgets() for input is you can now enter names containing spaces. Another is that errors in numeric input are easily handled, e.g.
...
Choose a function:
1 - Add a worker using pointers
2 - Add n workers
3 - Display all workers
4 - Leave
1
What is name of 6. worker: Bugs Bunny
What is age of 6. worker: dunno - really
error: invalid integer input.
What is age of 6. worker: 101
...
The error handling shown in the example code isn't intended to be exhaustive, and there is much more that can be added. However, note by using fgets() and checking if the return is NULL (e.g. if (!fgets(...))) you are handling the case where a manual EOF is generated by the user to cancel input.
If you are still stuck with your code, or if you have further questions about the changes above or why one approach has advantages over another, just drop a comment below and I'm happy to help further.
Example Use/Output
Here is a short set of input/output from testing the code:
./bin/workers_fn_new
Add a number of workers and then their info: 2
What is name of 1. worker: Mickey Mouse
What is age of 1. worker: 99
What is name of 2. worker: Minnie Mouse
What is age of 2. worker: 97
2 workers added
Choose a function:
1 - Add a worker using pointers
2 - Add n workers
3 - Display all workers
4 - Leave
3
All workers:
ID : 1
Name : Mickey Mouse
Age : 99
ID : 2
Name : Minnie Mouse
Age : 97
Choose a function:
1 - Add a worker using pointers
2 - Add n workers
3 - Display all workers
4 - Leave
1
What is name of 3. worker: Pluto (the dog)
What is age of 3. worker: 92
Choose a function:
1 - Add a worker using pointers
2 - Add n workers
3 - Display all workers
4 - Leave
3
All workers:
ID : 1
Name : Mickey Mouse
Age : 99
ID : 2
Name : Minnie Mouse
Age : 97
ID : 3
Name : Pluto (the dog)
Age : 92
Choose a function:
1 - Add a worker using pointers
2 - Add n workers
3 - Display all workers
4 - Leave
2
How many workers do you want to insert? 2
What is name of 4. worker: Daffy Duck
What is age of 4. worker: 93
What is name of 5. worker: Daisy Duck
What is age of 5. worker: 91
Choose a function:
1 - Add a worker using pointers
2 - Add n workers
3 - Display all workers
4 - Leave
3
All workers:
ID : 1
Name : Mickey Mouse
Age : 99
ID : 2
Name : Minnie Mouse
Age : 97
ID : 3
Name : Pluto (the dog)
Age : 92
ID : 4
Name : Daffy Duck
Age : 93
ID : 5
Name : Daisy Duck
Age : 91
Choose a function:
1 - Add a worker using pointers
2 - Add n workers
3 - Display all workers
4 - Leave
1
What is name of 6. worker: Bugs Bunny
What is age of 6. worker: dunno - really
error: invalid integer input.
What is age of 6. worker: 101
Choose a function:
1 - Add a worker using pointers
2 - Add n workers
3 - Display all workers
4 - Leave
3
All workers:
ID : 1
Name : Mickey Mouse
Age : 99
ID : 2
Name : Minnie Mouse
Age : 97
ID : 3
Name : Pluto (the dog)
Age : 92
ID : 4
Name : Daffy Duck
Age : 93
ID : 5
Name : Daisy Duck
Age : 91
ID : 6
Name : Bugs Bunny
Age : 101
Choose a function:
1 - Add a worker using pointers
2 - Add n workers
3 - Display all workers
4 - Leave
4
I was attempting the CodeChef contest today where I came across this problem. I managed to do the code, but there's one error that I don’t know how to take all inputs in a single line separated by space. I checked thousands of answers on Stack Overflow, but I still didn’t get it. How can I fix this problem?
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
int main()
{
int t, n, a, b, c, x, y, z;
//printf("No. of test cases\n");
scanf("%d", &t);
for(int i=0; i<t; i++)
{
//printf("Enter three inputs\n");
scanf("%d\t%d\t%d", &a, &b, &c);
}
x = a + b;
y = b + c;
z = a + c;
if(x>y && x>z)
{
printf("%d", x);
}
else if(y>a && y>z)
{
printf("%d", y);
}
else
{
printf("%d", z);
}
}
It is the same and is not a big deal.
Just enter your first input and instead of pressing Enter, you press Space. Then enter your second input, press Space again, enter the third input, and then press Enter. It will definitely work.
I will show you two programs and then may be you see a way to read the values in a controlled way.
scanf() is controlled by the mask, the thing like "%d\t%d\t%d" in your code. And scanf() has the notion of white space, treating spaces and tabs and newlines as same thing. These sometimes makes a mess when reading keyboard input, because scanf() refuses to end and keeps reading trying to satisfy the supplied input mask. [See the first example program].
Fact is that these functions were written to consume tabular data, like CSV files --- Hence the name: scan formatted input. But stdin with a keyboard with 105 keys are not formatted input: The user can key anything in.
Always test the return of scanf()
scanf() returns a negative value for error, or the number of items read. In your case, it can return 0, 1, 2 or 3: there are three fields to be read in "%d\t%d\t%d"
Example 1
#include <stdio.h>
int main(void)
{
int A, B, C;
int res;
do
{
printf("\n==> Enter up to 3 integer numbers, separated by spaces: ");
res = scanf("%d %d %d", &A, &B, &C);
switch (res)
{
case 0:
printf("\nscanf() read no numbers\n");
break;
case 1:
printf("scanf() read a single value, A = %d\n", A);
break;
case 2:
printf(
"scanf() read two values, A = %d, B = %d\n", A, B);
break;
case 3: // Fall-through
default:
printf(
"scanf() read all 3 values, A = %d, B = %d, C = "
"%d\n",
A, B, C);
break;
}; // switch()
} while ( res != 0);
return 0;
}
This code uses scanf() on stdin as usual.
Some results from example 1
==> Enter up to 3 integer numbers, separated by spaces: 1 2 3
scanf() read all 3 values, A = 1, B = 2, C = 3
All good when the numbers come as expected...
==> Enter up to 3 integer numbers, separated by spaces: 1 2
3
But now scanf() reads 1 and 2, but the user entered a few newlines, that scanf() skips like white space and will forever until read a letter or the final digit
And note this one:
==> Enter up to 3 integer numbers, separated by spaces: 1 end
scanf() read a single value, A = 1
==> Enter up to 3 integer numbers, separated by spaces:
scanf() read no numbers
The user entered 1 end. As soon as the e is read scanf() returns 1 and A is set to 1, of course. But then the next call has the end letters and the newline to read, so the next call of scanf() reads these letters, returns 0 and the program ends.
This is the kind of outcome that surprise many beginners and even a few professionals sometimes.
And these is hard to control.
For these reason many times is better to read the whole line by other means, and use sscanf() to consume the data, as in example 2. The idea is that all data in the line is consumed, and sscanf() parses the data from memory.
I believe that the example is ok to understand.
Example 2
#include <stdio.h>
int main(void)
{
int A, B, C;
int res;
printf("Enter up to 3 integer numbers, separated by spaces or ENTER to exit: ");
char line[100] = {0};
char* p = line;
// read whole line, up to the possible '\n'
p = fgets( line,100,stdin);
if ( p[0] == '\n') return 0; // input empty
do
{
res = sscanf(line, "%d %d %d", &A, &B, &C);
switch (res)
{
case 0:
printf("scanf() read no numbers\n");
break;
case 1:
printf("scanf() read a single value, A = %d\n", A);
break;
case 2:
printf(
"scanf() read two values, A = %d, B = %d\n", A, B);
break;
case 3: // fall thru
default:
printf(
"scanf() read all 3 values, A = %d, B = %d, C = "
"%d\n",
A, B, C);
break;
}; // switch()
printf("Enter up to 3 integer numbers, separated by spaces or ENTER to exit: ");
p = fgets( line,100,stdin); // next line
if ( p[0] == '\n') return 0; // input empty
} while ( res != 0 );
return 0;
}
Output for example 2
Enter up to 3 integer numbers, separated by spaces or ENTER to exit: 1
scanf() read a single value, A = 1
Enter up to 3 integer numbers, separated by spaces or ENTER to exit: 1 2
scanf() read two values, A = 1, B = 2
Enter up to 3 integer numbers, separated by spaces or ENTER to exit: 1 2 3
scanf() read all 3 values, A = 1, B = 2, C = 3
Enter up to 3 integer numbers, separated by spaces or ENTER to exit: 1 2 end
scanf() read two values, A = 1, B = 2
Enter up to 3 integer numbers, separated by spaces or ENTER to exit: end
scanf() read no numbers
Enter up to 3 integer numbers, separated by spaces or ENTER to exit:
And things are a bit easier to control.
I wrote this code in C. What it basically do is it takes an input (number) for the user and, depending the number the user chose, it will run a for loop. The for loop will asks the user to input more numbers depending on the statement that it is asking. The code will then take those input from the user and apply it to the formula.
Let say the user inputs 2 at first. What it is supposed to do is go to through the loop twice and take the sum from the first and second time and added them together. Unfortunately, it doesn't do that and will only give back the first result from the loop separated by the second result.
This is the code:
#include <stdio.h>
int main(){
int i = 0;
int robotMany = 0;
int enginePower = 0;
int resistance = 0;
int weight = 0;
int height = 0;
printf("Depending the numbers of robot that you enter.You will need to do the following\n");
printf("Engine power\nResistance\nWeight\nHeight\n");
printf("Enter the amount of robots\n");
scanf("%d",&robotMany);
printf("You chose %d robot\n", robotMany);
//Depending the user input, it will run # of times.
for(i = 0; i < robotMany; i++){
//for loop begins
printf("Enter the engine power.(1-20)\n");
scanf("%d", &enginePower);
printf("Enter the resistance.(1-3)\n");
scanf("%d", &resistance);
printf("Enter the weight of the robot\n");
scanf("%d", &weight);
printf("Enter the height of Robot.\n");
scanf("%d", &height);
int product;
//take the user inputs and apply it to the formual.
product = (enginePower + resistance) * (weight - height);
printf("This is your total power\n");
printf("%d\n", product);
}
return 0;
}
You have a fundamental logic error in failing to keep a running total for the product calculated within each loop iteration.
However you have a larger problem in failing to validate the return of scanf (or any function you use for user-input). It is critical you validate EVERY user input, and even more so when using scanf to avoid invoking Undefined Behavior in your code. Why? If the user enters a stray character that does not match the conversion specifier in the format string, a matching failure occurs and character extraction from stdin ceases at that point leaving the offending character in the input buffer unread. In your case this would result in the same matching failure occurring for every call to scanf throughout the remainder of your program.
Take for example the user reaches for the '2' key but accidentally taps the 'w' key instead when entering robotMany. Not only does the input for robotMany fail, but since the 'w' is left in stdin unread, it causes input for enginePower, resistance, weight & height to fail as well. (if this occurs within a loop, your loop will likely go spinning out of control until the process is manually terminated)
That is why it is critical to always validate the return of any input function, but especially the scanf family of functions. To catch and handle any input failure (matching failure, input failure, or manually generated EOF), just check the return, e.g.
if (scanf ("%d", &robotMany) != 1) { /* VALIDATE EVERY USER INPUT! */
fputs ("error: invalid input, or user canceled - robotMany\n", stderr);
return 1;
}
On to your logic errors. First, you need a variable to track the sum of each product calculated on each trip through the loop. Since it appears this will be a total power, just add a totalpwr variable and initialize it to zero (as you have done a good job doing with all your variables), e.g.
int i = 0,
robotMany = 0,
enginePower = 0,
resistance = 0,
weight = 0,
height = 0,
totalpwr = 0; /* sum of product from each iteration */
Now within your loop, you want to add product to totalpwr each time it is computed, e.g.
/* Depending the user input, it will run # of times. */
for (i = 0; i < robotMany; i++) {
...
/* take the user inputs and apply it to the formula. */
int product = (enginePower + resistance) * (weight - height);
totalpwr += product; /* add product to total power */
}
To output the totalpwr, you will output the value after you exit the loop, e.g.
...
}
/* you output the total power required outside the loop */
printf ("\ntotal power required: %d\n", totalpwr);
return 0;
}
Putting it altogether in an example (without passing on the correctness of the product calculation or the range of values needed) you can do something similar to the following:
#include <stdio.h>
int main (void) {
int i = 0,
robotMany = 0,
enginePower = 0,
resistance = 0,
weight = 0,
height = 0,
totalpwr = 0; /* sum of product from each iteration */
/* you only need a single printf (fputs would do due to no conversion) */
printf ("Depending the numbers of robot that you enter, you will need "
"to enter:\n\n"
" Engine power | Resistance | Weight | Height\n\n"
"Enter the amount of robots: ");
if (scanf ("%d", &robotMany) != 1) { /* VALIDATE EVERY USER INPUT! */
fputs ("error: invalid input, or user canceled - robotMany\n", stderr);
return 1;
}
printf ("\nYou chose: %d robots\n\n", robotMany);
/* Depending the user input, it will run # of times. */
for (i = 0; i < robotMany; i++) {
printf ("Enter the engine power.(1-20): ");
if (scanf("%d", &enginePower) != 1) { /* validate! */
fputs ("error: invalid input - enginePower\n", stderr);
return 1;
}
printf ("Enter the resistance.(1-3): ");
if (scanf("%d", &resistance) != 1) { /* validate! */
fputs ("error: invalid input - resistance\n", stderr);
return 1;
}
printf ("Enter the weight of the robot: ");
if (scanf("%d", &weight) != 1) { /* validate! */
fputs ("error: invalid input - weight\n", stderr);
return 1;
}
printf ("Enter the height of Robot: ");
if (scanf("%d", &height) != 1) { /* validate! */
fputs ("error: invalid input - height\n", stderr);
return 1;
}
/* take the user inputs and apply it to the formula. */
int product = (enginePower + resistance) * (weight - height);
/* the following outputs the per-loop/per-robot product (you can remove) */
printf (" iteration %d product: %d\n\n", i+1, product);
totalpwr += product; /* add product to total power */
}
/* you output the total power required outside the loop */
printf ("\ntotal power required: %d\n", totalpwr);
return 0;
}
(note: only one printf is required to output multiple lines of output. There is no need to make repeated calls one after the other just to output separate lines. All sequential strings will be concatenated by the compiler)
Example Use/Output
$ ./bin/robotmany
Depending the numbers of robot that you enter, you will need to enter:
Engine power | Resistance | Weight | Height
Enter the amount of robots: 3
You chose: 3 robots
Enter the engine power.(1-20): 4
Enter the resistance.(1-3): 2
Enter the weight of the robot: 10
Enter the height of Robot: 31
iteration 1 product: -126
Enter the engine power.(1-20): 5
Enter the resistance.(1-3): 3
Enter the weight of the robot: 9
Enter the height of Robot: 31
iteration 2 product: -176
Enter the engine power.(1-20): 3
Enter the resistance.(1-3): 1
Enter the weight of the robot: 8
Enter the height of Robot: 31
iteration 3 product: -92
total power required: -394
You may want to add constraints on the weight and height entry to prevent a negative power-required result -- but that is left to you. Look things over and let me know if you have further questions.
Beginner programming including arrays and I'm having trouble just getting user input for the arrays. The printf functions I've included are just to check whether my arrays are working, the larger program I'm writing just needs to use these two arrays.
The input for the char array seems to work fine, I've tried a couple of different methods. However, the int array doesn't seem to work using the same diversity of methods I've used successfully with the char array. Not sure what I'm missing. Below is the code and the output when I run the program:
int main()
{
char grades[5]; // create array to store letter grades
int hours[5]; // array to store hours
puts("Please enter letter grades:"); // Input letter grades using fgets
fgets(grades, 5, stdin);
printf("Letter grade for course 3 is %c.\n", grades[2]);
int x = 0;
puts("Please enter course hours:\n");
for (x = 0; x < 5; x++)
{
scanf("%d", &hours[x]);
}
printf("Course hours for course 2 are: %d.\n", hours[1]);
return 0;
}
Output of this code:
Please enter letter grades:
ABCDF <- user input
Letter grade for course 3 is C.
Please enter course hours:
Course hours for course 2 are: -858993460.
Press any key to continue . . .
fgets(grades, 5, stdin); captures ABCD of the input leaving F in the input stream. scanf("%d", &hours[x]); can't parse an int from F though it tries five times. Each failure leaves the F in the input stream.
Make buffers large enough for typical input.
Use fgets for all input. Parse with sscanf or others. Use the return of sscanf to make sure the parsing was successful.
#include <stdio.h>
int main( void)
{
char grades[50] = ""; // create array to store letter grades
char line[50] = "";
int hours[5] = { 0}; // array to store hours
int result = 0;
puts("Please enter letter grades:"); // Input letter grades using fgets
fgets(grades, sizeof grades, stdin);
printf("Letter grade for course 3 is %c.\n", grades[2]);
int x = 0;
for (x = 0; x < 5; x++)
{
do {
printf("Please enter course %d hours:\n", x + 1);
fgets ( line, sizeof line, stdin);
result = sscanf( line, "%d", &hours[x]);
if ( result == EOF) {
printf ( "EOF\n");
return 0;
}
} while ( result != 1);
}
printf("Course hours for course 2 are: %d.\n", hours[1]);
return 0;
}
int main() {
int i, repeatName; // ints
char firstName[50]; // array to store users name
// get first name from user
printf("Please enter your first name: ");
scanf("%s", firstName);
// get amount of times user would like to repeat name
printf("How many times would you like to repeat your name?: ");
scanf("%i", &repeatName);
// tell user name has to be repeated at last one
if (repeatName < 1) {
printf("The name has to be repeated at least one (1) time. Try again: ");
scanf("%i", &repeatName);
}
// for loop to repeat name 'x' number of times
for (i = 0; i < repeatName; i++) {
printf("%s \n", firstName);
}
}
For example: If the user wanted to display their name 3 times it would say:
Your name
Your name
Your name
How can I get it to say:
Line 1 Your name
Line 2 Your name
Line 3 Your name
Use the i variable in the loop as the line number
for (i = 0; i < repeatName; ++i)
printf("Line %d %s\n", i + 1, firstName);
Be sure to add 1, because the loop index starts from 0. You want the first line to say "Line 1", not "Line 0", and so on.
Edit: When the line number is more than one digit, the output is not as pretty. To solve this, you can write
for (i = 0; i < repeatName; ++i)
printf("Line %-6d%s\n", i + 1, firstName);
This makes the line number take up at least 6 characters, and makes the number be left-justified:
Line 1 this is my string
Line 2 this is my string
Line 3 this is my string
Line 4 this is my string
Line 5 this is my string
Line 6 this is my string
Line 7 this is my string
Line 8 this is my string
Line 9 this is my string
Line 10 this is my string
There is no way to do that automatically, as far as I know. But you can make your i variable in the for loop act as a line counter too, since for each iteration you print a line:
// for loop to repeat name 'x' number of times
for (i = 0; i < repeatName; i++) {
printf("Line %d %s \n", i + 1 /* Lines are not 0 based */ , firstName);
}
Just add the loop index when you're printing:
for (i = 0; i < repeatName; i++) {
printf("Line %d %s \n", i+1, firstName);
}
Try This code
#include <stdio.h>
int main()
{
int i, repeatName; // ints
char firstName[50]; // array to store users name
// get first name from user
printf("Please enter your first name: ");
scanf("%s", firstName);
// get amount of times user would like to repeat name
printf("How many times would you like to repeat your name?: ");
scanf("%i", &repeatName);
// tell user name has to be repeated at last one
if (repeatName < 1) {
printf("The name has to be repeated at least one (1) time. Try again: ");
scanf("%i", &repeatName);
}
// for loop to repeat name 'x' number of times
for (i = 1; i <= repeatName; i++) {
printf("Line %d Your name %s \n",i,firstName);
}
}