I'm working on a C programming project for school and it was working fine but now all of a sudden when it's trying to access a number in a block of memory under numbers_array[j] it will not access index 2 of the array and keeps giving me the error in the title
I have been debugging for about an hour and cannot figure what is wrong. It will factor number at index 0 and index 1 fine but after that the program crashes. Any idea what is wrong?
The error can be found in the loop after the declaration of factor_struct under the comment Requirement 2.
My code for a number factoring program is as follows:
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <ctype.h>
#define TRUE 1
#define FALSE 0
/* Requirement 2:
Creating a struct with serveral pieces of data */
struct factor_struct {
int number, count;
clock_t start;
clock_t end;
double time_to_factor;
double times_array[];
};
/* Function header decleration */
void factor(struct factor_struct *fs);
/* The main program loop */
int main(int argc, const char * argv[]) {
/* Intializing the variables we'll be using during the run loop */
int input, number, continue_loop_one = TRUE, continue_loop_two = TRUE;
int *numbers_array;
/* Printing the welcome message to the screen */
printf("Welcome to Factor Factory!\n\n");
/* Asking how many numbers the user would like to factor*/
printf("How many different numbers would you like to factor?\n");
/* Start of LOOP_1: Ask user to input the amount of numbers to factor.
This will let us allocate the proper amount of memory */
LOOP_1: do {
printf("Please enter a number from 1 to 10: ");
scanf("%d", &input);
printf("\n");
/* Check if user input is between 1 and 10, if not return to start of LOOP_1 */
if(input < 1 || input > 10) {
printf("%d isn't a valid number...don't play games with me human. Try again! \n\n", input);
/* Need to flush the incorrect input from the buffer or else scanf will cause a continuous loop*/
fflush(stdin);
goto LOOP_1;
}
/* Break out of the loop and continue our program */
continue_loop_one = FALSE;
} while (continue_loop_one == TRUE);
/* Requirement 4:
Intialize our numbers array with the correct amount of memory */
numbers_array = (int*) calloc(input, sizeof(int));
/* Check if memory was allocated properly */
if (numbers_array == NULL) {
printf("Error: Memory not allocated. Closing program...\n");
exit(0);
}
/* Requirement 1:
Asking the user to enter the numbers that we will be using our algorithm for to get their factors */
LOOP_2: do {
printf("Excellent! Lets get started...");
printf("enter %d number(s) between 2 and 1,000,000,000.\n", input);
/* Variable to track how many numbers have been input just incase a user enters an invalid number*/
int entered_number_count = 0;
LOOP_3: for(int i = 0 + entered_number_count; i < input; i++) {
printf("Number %d: ", i + 1);
scanf("%d", &number);
if (number < 2 || number > 1000000000) {
printf("%d isn't a valid number...don't play games with me human. Try again! \n\n", number);
fflush(stdin);
goto LOOP_3;
}
/* Assinging a number to the value at the proper memory location in the numbers_array */
numbers_array[i] = number;
/* Incrementing the amount of entered numbers */
entered_number_count++;
}
/* Break out the loop and continue our program */
continue_loop_two = FALSE;
} while(continue_loop_two == TRUE);
printf("\n");
/* Requirement 2:
Declaring our factor_struct for use */
struct factor_struct fs;
fs.count = 0;
/* For each number in the array, assign it to fs.number and factor it by passing it to our factor function
Each pass over the array will reassign fs.number */
for(int j = 0; j < input; j++) {
fs.number = numbers_array[j]; // **ERROR APPEARS IF INDEX J > 1**
factor(&fs);
fs.count++;
}
/* Requirement 3:
Using a pointer to move through time_array which will calculate
the total time to factor all numbers */
double total_time = 0.0;
double *ptr = fs.times_array;
for(; *ptr; ++ptr) { total_time += *ptr; }
printf("Total computation time: %f seconds. \n\n", total_time);
/* Ask the user if they would like to continue or quit the program*/
printf("Would you like to continue factoring numbers?\n");
printf("Enter 'y' to continue or 'q' to quit: ");
/* Control loop that handles the continue or quit commands */
char c;
while(c != 'q') {
scanf("%c", &c);
if(c == 'y') {
printf("\n");
goto LOOP_1;
}
}
/* Thank the user and quit the program */
printf("\n");
printf("Thank you for using Factor Factory!\n");
printf("Closing program...\n\n");
/* Requirement 4:
Deallocating the memory for the numbers_array */
free(numbers_array);
return 0;
}
/* Requirement 5:
Taking data and passing it through the facotring algorithm */
void factor(struct factor_struct *fs) {
/* Marking the starting time of the function */
fs->start = clock();
printf("Factors of %d: ", fs->number);
/* Algorithm for finding all factors of our number */
for(int i = 1; i <= fs->number/2; i++) {
if (fs->number % i == 0) {
printf("%d ", i);
}
}
printf("%d\n", fs->number);
/* Marking the ending time of the function */
fs->end = clock();
/* Calculating the total time it took to find all factors*/
fs->time_to_factor = (double)(fs->end - fs->start) / CLOCKS_PER_SEC;
fs->times_array[fs->count] = fs->time_to_factor;
}
This question already has answers here:
scanf() leaves the newline character in the buffer
(7 answers)
Closed 2 years ago.
I'm pretty new in C.
My problem is the code keep looping at that line ( you can check the code) while what i wanted is for it to loop the whole for statement, not a single line.
English is not my first language so i'm truly sorry
#include <stdio.h>
int hw;
int uts;
int uas;
float hasil_uts;
float hasil_uas;
float hasil_hw;
char opsi;
int main (void) {
int n1; //Homework
int c1;
for (c1=0;opsi != 'n';c1++) {
printf ("Input : ");
scanf ("%d",&hw);
n1 += 1;
hasil_hw += hw;
printf ("\nInput another marks? (y/n)"); // it loops here when it run
scanf ("%c",&opsi);
}
return 0;
}
you have to add one space in scanf like this scanf (" %c",&opsi); ,otherwise you will take \n as your character in scanf.
also note that you are using uninitialized variable n1 and hasil_hw. you have to add n1=0 and hasil_hw=0 to your code.
also as mentioned in comments you should check scanf returned value.
look
int hw;
int uts;
int uas;
float hasil_uts;
float hasil_uas;
float hasil_hw=0;
char opsi;
int main(void) {
int n1=0; //Homework
int c1;
for (c1 = 0; opsi != 'n'; c1++) {
printf("Input : ");
if ( scanf("%d", &hw) != 1)
{
fputs ("error: invalid value.\n", stderr);
return 1;
}
n1 += 1;
hasil_hw += hw;
printf("\nInput another marks? (y/n)"); // it loops here when it run
if (scanf(" %c", &opsi) != 1)//add space before %c
{
fputs ("error: invalid value.\n", stderr);
return 1;
}
}
return 0;
}
I have to write a program for recording the measured temperatures,
into which new measurements can be entered, or display statistics calculated from previous measurements. In the case of printing statistics, it is necessary to find and display the lowest and highest recorded temperature and calculate the average temperature.
#include <stdio.h>
int least_in_array(int array[], int n)
{
int i, least=array[0];
for(i=0; i<n; i++)
{
if(array[i]<least)
{
least=array[i];
}
}
return least;
}
int largest_in_array (int array[], int n)
{
int i, largest=array[0];
for(i=0; i<n; i++)
{
if(array[i]>largest)
{
largest=array[i];
}
}
return largest;
}
float average_array(int array[], int n)
{
int amount=0, i;
for(i=0; i<n; i++)
{
amount+=array[i];
}
return (1.0*amount)/n;
}
int main() {
int choose;
struct Data1 {
int dayInMonth;
int month;
float temperature;
} da;
printf("New measurement(1) or statistic(2)?\n");
scanf("%d", &choose);
if(choose==1) {
printf("Enter the day in month : ");
scanf("%d", &da.dayInMonth);
printf("Enter month : ");
scanf("%d", &da.month);
printf("Enter temperature (*C) : ");
scanf("%f", &da.temperature);
printf("Data saved!");
printf("-----------\n");
return 0;
}
if(choose==2) {
//printf("Least temperatures in quarter: %d", least_in_array(dayInMonth) );
return 0;
}
else {
printf("----------------\n");
printf("Wrong choose!\n");
}
return 0;
}
In case 2, I commented line where I get an error. Can anyone give me any advice to fix this problem?
|71|error: 'dayInMonth' undeclared (first use in this function)
|71|error: too few arguments to function 'least_in_array'
Since it is Christmas Eve, lets help out fellow man... who obviously is badly in need. For code that is supposed to pass an array to least_in_array, largest_in_array and average_array -- you have no array! That somewhat puts you behind the eight-ball from the word "Go!".
Your thought to use a stuct to capture and coordinate dayInMonth, month and temperature is 100% correct. (but note: C-style generally avoids camelCase variable names in favor of all lowercase). Also, defining struct Data1 within main() prevents your functions above that point from knowing what struct Data1 is, so you need to move your struct definition to the top of the file. (or provide a forward declaration, but we will save that for later) For now, let's just move your Data1 to the top (I used a typedef to alleviate having to prefix each use with stuct and renamed Data1 data:
#define NDAYS 365
typedef struct {
int day,
month;
double temperature;
} data;
Note the defined constant NDAYS. Since you are going to need an array, and since a dynamically allocated and reallocated approach seem well beyond your needs here, let's just define a constant, a maximum, for the number of elements we will have in our array.
Now, before we go further, let's think about our array. If we are going to use a struct to hold the associated date and temperature measurement, then we are going to need an array of... what?? An array of struct. And with our constant NDAYS, we will declare a maximum of 365 elements in our array. So how would this work? We have our stuct typedeffed to data, so if we want an array of data we need:
data da[NDAYS] = {{0, 0, 0.0}};
Note: the older initializer format initializing each field was used as it is unclear whether you could be using a C89 compiler. C99 and later added named initializers , e.g. {{.day = 0}} and any uninitialized elements are implicitly initialized to zero.
Now we have an array of data and can capture measurements. Of course you are responsible for keeping track of the indexes you fill. A simple counter, incremented each time a successful measurement in entered is all you need (ndx is used below)
How do we make least_in_array, largest_in_array and average_array work with an array of data? Recall, we moved the definition of the struct to the beginning of the source file, so now each function knows what data is. We simply need to pass our array of data as a parameter, e.g.
float least_in_array (data *array, int n)
{
int i;
float least = INT_MAX; /* sufficiently high temp */
for (i = 0; i < n; i++)
if (array[i].temperature < least)
least = array[i].temperature;
return least;
}
(note, each of the quantities of least_in_array, largest_in_array and average_array refer to the temperature values and therefore need to return type float.)
The remainder of putting together largest_in_array and average_array follows the same pattern.
The crux of your remaining problems relate to handling user input, and the particular pitfalls associated with taking user input with scanf. It can be done, but you must always validate the return, and test for user cancellation of input by testing for EOF (the result of the user pressing Ctrl+d (or Ctrl+z on windoze)).
You must validate that the number of expected conversions did in fact take place, or you must handle the error, and most importantly, you must account for any characters left in the input buffer (e.g. stdin), otherwise, if an invalid entry is made and you don't remove it from stdin, you will loop forever... (with scanf if a matching or input failure occurs -- no additional character are processed -- leaving them where? (oh, in stdin)
You can make this fairly easy on yourself if you declare a few helper functions to empty stdin, and make the normal process of getting an integer or float from the user relatively safe. For example, to empty stdin, you simply read all remaining characters until a '\n' or EOF is encountered, e.g.
/** simple function to empty all characters that remain
* in stdin. Needed when using scanf for user input.
*/
void empty_stdin()
{
int c = getchar();
while (c != '\n' && c != EOF)
c = getchar();
}
To ask the user for an int or float, you simply validate the return, check the number of successful conversion (what scanf returns), check whether EOF was generated by the user, and finally handle the error if invalid input was given and empty_stdin as required. You generally want to loop until the user either provides valid input, or cancels. (an invalid input does you no good).
For example, getting integer input can be handled as follows. (note: I put it in a function to keep from repeating this block of code for each input you take in the main body of your code...
/** abbreviated function to read integer value from user.
* returns value on success, exits if user cancels.
* empties stdin after call to scanf.
*/
int getint ()
{
int n = 0;
for (;;) { /* loop until valid input or EOF */
int rtn = 0; /* variable to capture return of scanf */
rtn = scanf ("%d", &n);
if (rtn == 1) { /* we got an integer */
empty_stdin();
break;
}
else if (rtn == EOF) { /* if user cancels, exit */
fprintf (stderr, "user canceled input.\n");
exit (EXIT_FAILURE);
}
if (rtn == 0) /* handle error */
fprintf (stderr, "getint() error: invalid integer input.\n");
empty_stdin(); /* empty all chars remaining in stdin */
}
return n;
}
(taking input for a float works the same way).
Lastly, you generally want to avoid using float in most cases, using double instead, just due to loss of precision and limitations for representing floating-point numbers with a 23-bit mantissa. However, here we are taking temperature, and float will suffice for this code.
Putting it altogether, you could do something like the following. Note, I have left your functions before main() as you had them, and added the helper function definitions after main(), but provided declarations before main() so they are visible to main() :
#include <stdio.h>
#include <stdlib.h>
#include <limits.h>
#define NDAYS 365
typedef struct {
int day,
month;
double temperature;
} data;
float least_in_array (data *array, int n)
{
int i;
float least = INT_MAX; /* sufficiently high temp */
for (i = 0; i < n; i++)
if (array[i].temperature < least)
least = array[i].temperature;
return least;
}
float largest_in_array (data *array, int n)
{
int i;
float largest = INT_MIN; /* sufficiently low temp */
for (i = 0; i < n; i++)
if (array[i].temperature > largest)
largest = array[i].temperature;
return largest;
}
float average_array (data *array, int n)
{
int i;
float sum = 0.0;
for (i = 0; i < n; i++)
sum += array[i].temperature;
return sum / (float)n;
}
void empty_stdin();
int getint();
float getfloat();
int main (void) {
int ndx = 0;
float max = 0.0, min = 0.0, avg = 0.0;
data da[NDAYS] = {{0, 0, 0.0}};
for (;;) {
int choose = 0;
printf ("\n (1) New measurement\n"
" (2) Statistics\n"
" (3) Exit\n\n"
" choice: ");
choose = getint();
putchar ('\n');
switch (choose) {
case 1: if (ndx == NDAYS) {
fprintf (stderr, "error: array full.\n");
break;
}
printf (" Enter day in month : ");
da[ndx].day = getint();
printf (" Enter month : ");
da[ndx].month = getint();
printf (" Enter temperature : ");
da[ndx].temperature = getfloat();
printf (" da[%3d] saved\n"
" ----------------------------\n", ndx++);
break;
case 2: if (ndx == 0) {
fprintf (stderr, "error: no measurements taken.\n");
break;
}
min = least_in_array (da, ndx);
max = largest_in_array (da, ndx);
avg = average_array (da, ndx);
printf (" minimum temp : %.2f\n"
" maximum temp : %.2f\n"
" average temp : %.2f\n"
" ----------------------------\n",
min, max, avg);
break;
case 3:
goto done;
break;
default:
fprintf (stderr, "error: invalid choice.\n");
empty_stdin();
break;
}
}
done:;
return 0;
}
/** simple function to empty all characters that remain
* in stdin. Needed when using scanf for user input.
*/
void empty_stdin()
{
int c = getchar();
while (c != '\n' && c != EOF)
c = getchar();
}
/** abbreviated function to read integer value from user.
* returns value on success, exits if user cancels.
* empties stdin after call to scanf.
*/
int getint ()
{
int n = 0;
for (;;) { /* loop until valid input or EOF */
int rtn = 0; /* variable to capture return of scanf */
rtn = scanf ("%d", &n);
if (rtn == 1) { /* we got an integer */
empty_stdin();
break;
}
else if (rtn == EOF) { /* if user cancels, exit */
fprintf (stderr, "user canceled input.\n");
exit (EXIT_FAILURE);
}
if (rtn == 0) /* handle error */
fprintf (stderr, "getint() error: invalid integer input.\n");
empty_stdin(); /* empty all chars remaining in stdin */
}
return n;
}
/** abbreviated function to read float value from user.
* returns value on success, exits if user cancels.
* empties stdin after call to scanf.
*/
float getfloat ()
{
float v = 0.0;
for (;;) { /* loop until valid input or EOF */
int rtn = 0; /* variable to capture return of scanf */
rtn = scanf ("%f", &v);
if (rtn == 1) { /* we got an float */
empty_stdin();
break;
}
else if (rtn == EOF) { /* if user cancels, exit */
fprintf (stderr, "user canceled input.\n");
exit (EXIT_FAILURE);
}
if (rtn == 0) /* handle error */
fprintf (stderr, "getint() error: invalid float input.\n");
empty_stdin(); /* empty all chars remaining in stdin */
}
return v;
}
Note: how the array bounds are limited to 365 or less in your take measurement part of the code, and how a check is made that there is at least one measurement present before any statistics can be provided. You always need to validate each step of the process. Look for corner-cases, think about what could go wrong with input (what if a cat stepped on the keyboard), and then go provide validations and checks to handle each case. The validations above are just the bare minimum, there are always more you can add to more fully report and handle each error condition.
Example Use/Output
$ ./bin/tempmxmnavg
(1) New measurement
(2) Statistics
(3) Exit
choice: 2
error: no measurements taken.
(1) New measurement
(2) Statistics
(3) Exit
choice: 1
Enter day in month : 8
Enter month : 2
Enter temperature : 20.0
da[ 0] saved
----------------------------
(1) New measurement
(2) Statistics
(3) Exit
choice: 1
Enter day in month : 9
Enter month : 2
Enter temperature : 30.0
da[ 1] saved
----------------------------
(1) New measurement
(2) Statistics
(3) Exit
choice: 1
Enter day in month : 10
Enter month : 2
Enter temperature : 70.0
da[ 2] saved
----------------------------
(1) New measurement
(2) Statistics
(3) Exit
choice: 2
minimum temp : 20.00
maximum temp : 70.00
average temp : 40.00
----------------------------
(1) New measurement
(2) Statistics
(3) Exit
choice: 3
Look things over and let me know if you have any further questions (although given the evening, I won't be here much longer...)
I am in a intro to C programming course and I am a bit confused.
My input is not working correctly. When I run the program, the program will take the first input, then skip the rest of the prompts for inputs and generate a total.
What is going on? I am completely lost.
int main(void) {
/* declarations: */
double y, m1, s1, s2, m2, i;
char g; /* Do not remove this line */
/*Print the title of the program*/
printf(" MILEAGE SPEED INTERPOLATION\n");
printf("______________________________________________________________________\n");
printf("Enter in your first speed:\n"); //this is s1
scanf("%.1f", &s1);
printf("Enter in your mileage:\n"); //m will be mileage 1
scanf("%.1f", &m1); //mileage is y
printf("Enter in your second speed:\n"); //this is s2
scanf("%.1f", &s2);
printf("Enter in your second mileage:\n");
scanf("%.1f", &m2);
/*Get the needed input*/
/*get the interpolation from the user*/
printf("Enter your interpolation:\n"); //number between 1 and 2
scanf("%.lf", &i);
printf("______________________________________________________________________\n");
/*Statements that perform the desired task*/
// This equation is calculating from rpm to knots
y = m1 + (i - s1) * (m2 - m1) / (s2 - s1); //This will do the equation for us.
/* Printing of the results*/
// Trying to print the answer from above equation
printf("Your estimated value is %f: ", y);
/*Keeps the window open. Please do not alter this.*/
printf("\n\nEnter to q to quit.\n");
do {
g = getchar();
} while (g != 'q');
return 0;
}
You must use "%lf" for double with scanf()
if (scanf("%lf", &s1) != 1)
return -1; /* Bad input */
and you can't specify precision, instead you can specify a maximum number of characters.
Program to limit the user's input to one decimal point in C.
For example:
Enter grade: 5 //Acceptable
Enter grade: 8.5 //Acceptable
Enter grade: 6.467 //Not acceptable, Re-enter grade
#include <stdio.h>
#include <math.h>
main()
{
double grade[8];
int i;
for (i = 0; i < 8; i++) {
printf("Insert grade: ");
scanf("%f", &grade[i]);
}
}
You will have to input the data as string, then check it only has one decimal place.
It is not possible to input a floating-point value and then check for decimal places; since the floating point values are stored internally with binary places and hold an approximation of the value that was input, in most cases.
The input code could look like:
char temp[20];
if ( 1 != scanf("%19s", temp) )
return EXIT_FAILURE;
// code to check for decimal place goes here - I'm purposefully not
// showing it as this looks like homework!
// once we have checked that the input is correct, then convert to double
grade[i] = strtod(temp, NULL);
#include <stdio.h> // printf(), scanf()
#include <math.h> // floor()
main()
{
double grade[8];
int i;
for (i = 0; i < 8; i++)
{
do
{
printf("Insert grade: ");
scanf("%lf", &grade[i]);
grade[i] *= 10;
if (grade[i] != floor(grade[i])) // Prints error message, if user types more than one decimal point
{
printf("Grade must have one decimal point.\nPlease re-enter grade.\n");
}
}while (grade[i] != floor(grade[i])); // Checks decimal point
}
}
Use fgets() to read the line into a buffer and then test that buffer.
char buf[99];
fgets(buf, sizeof buf, stdin);
// parse the line as a float - look for problems
char *endptr;
float f = strtof(buf, &endptr);
if (buf == endptr || *endptr != '\n') Fail_NonFloatInput();
// look for .
char *dot = strchr(buf, '.');
if (dot && isdigit(dot[1]) && isdigit(dot[2])) Fail_TooMuchPrecisison();
}
Alternatively code could try:
long long i;
int f;
if (2 != scanf("%lld.%1d", &i, &f)) Bad_Input();
float fl = i + f/10.0;
But that fails float input like 123456789012345678901234567890.0.
As #Matt McNabb says, read as text first.
You can use printf format specifiers to specificy the number of positions you are interested.
A format specifier follows this prototype: [see compatibility note below]
%[flags][width][.precision][length]specifier
Example from the cplusplus.com
#include <stdio.h>
int main()
{
printf ("floats: %4.2f %+.0e %E \n", 3.1416, 3.1416, 3.1416);
return 0
}
Output
floats: 3.14 +3e+000 3.141600E+000
More examples here http://www.cplusplus.com/reference/cstdio/printf/