I have the following code:
//get distances
int a = -1;
int b = -1;
while ((a != 0) && (b != 0)) {
scanf("%d %d", &a, &b);
printf("The shortest path from %d to %d is %.1lf meters.\n", a, b, D[a][b]);
}
The loop seems to terminate after one input, despite the fact that a and b are not inputed as 0.
ie:
0 2
The shortest path from 0 to 2 is 237.7 meters.
Not really sure why it's doing that so any help would be appreciated.
Then it terminates
Full code in case needed
#include <stdio.h>
#include <stdlib.h>
#define INF 41e6
double** new2Ddouble(int n, int m);
void free2D(double **a);
int main() {
//get # of nodes
int size = 0;
scanf("%d", &size);
//create matrix
double **D = new2Ddouble(size, size);
//fill with inf for D[i][j]
int i;
int j;
for(i=0; i<size; i++) {
for(j=0; j<size;j++){
D[i][j] = INF;
}
}
//fill D[i][i] with INF
for(i=0;i<size;i++) D[i][i] = INF;
int exit = 0;
int I;
int J;
double d;
while(exit != 1) {
//populate values in matrix
scanf("%d %d %lf", &I, &J, &d);
if(I == 0 && J == 0 && d == 0){
//we can exit
exit = 1;
} else {
D[I][J] = d;
}
}
//calculate distances
/* Floyd-Warshall Algorithm */
int k;
for (k=0; k<size; ++k)
for (i=0; i<size; ++i)
for (j=0; j<size; ++j)
if (D[i][k]+D[k][j] < D[i][j])
D[i][j] = D[i][k]+D[k][j];
exit = 0;
//get distances
int a = -1;
int b = -1;
while ((a != 0) && (b != 0)) {
scanf("%d %d", &a, &b);
printf("The shortest path from %d to %d is %.1lf meters.\n", a, b, D[a][b]);
}
return 0;
}
double** new2Ddouble(int n, int m) {
int i;
double **ret = (double**) malloc(n*sizeof(double*));
double *a = (double*) malloc(n*m*sizeof(double));
for (i=0; i<n; ++i) ret[i] = &a[i*m];
return ret;
}
void free2D(double **a) { free(a[0]); free(a); }
scanf("%d %d", &a, &b);
In this line you are scanning values for a and b 0 and 2 respectively.
So once a new value is scanned to these variables then your while condition fails because as you have showed a is 0 and the second condition is never checked because 0 && (0|1) = 0
Once a=0 the condition fails and exits the loop.
while ((a != 0) && (b != 0))
This loop will terminate when a or b is zero and will continue when a and b are not zero. You enter a as 0 and as the condition a!=0 fails,your loop terminates.
there are a couple of problems with this line:
scanf("%d %d", &a, &b);
Note: scanf does not automatically consume white space,
so on the second iteration
the next input char is a newline.
so scanf fails
Note: all I/O statements
should have the returned value checked
to assure success of the operation
to fix those items, write it like so:
if( 2 != scanf(" %d %d", &a, &b) )
{
perror( "scanf failed" );
exit( EXIT_FAILURE );
}
the leading ' ' in the format string causes leading
white space, like the newline, to be consumed
the 'if' checks the returned value from
scanf to assure that all the input conversions were successful
Related
I am trying to read numbers from file, the function prints only the digits after the decimal point. any idea why this happens?
thanks!
float Read() {
int i, k, w, m, n, j;
float number;
float a[m];
FILE *fil1;
fil1 = fopen("numbers.txt", "r");
w = 0; k = 0;
while (fscanf(fil1, "%d", &n) != EOF) {
fscanf(fil1, "%f", &number);
a[k] = number;
printf("%d => %f \n", i, a[k]);
w++;k++;
}
}
You're scanning the file twice, you're basically skipping every second number. this should fix it.
float Read (){
int i,k,w,m,n,j;
float number;
float a[m];
FILE *fil1;
fil1 = fopen("numbers.txt","r");
w=0; k = 0;
while (fscanf(fil1, "%f", &n) != EOF){
a[k]=n;
printf ("%d => %f \n",i, a[k]);
w++;k++;}
change n to be float
and read it as float:
#include "stdio.h"
#pragma warning(disable : 4996)
float Read()
{
int k, w;
float n;
float a[100];
FILE* fil1;
fil1 = fopen("numbers.txt", "r");
w = 0; k = 0;
while (fscanf(fil1, "%f", &n) != EOF) {
a[k] = n;
printf("%f \n", a[k]);
w++; k++;
}
return 0;
}
The code will not produce a compiler error, but i am trying to update the memory allocation after every loop if the user types Y, and increase the size of the memory. But after the first while loop, when i try to print the list of numbers using the first for loop, it will just show one number which will be 0.00000. I can't get it to update (which is what I am trying to do in the second if loop). Any help is appreciated.
#include<stdio.h>
#include<stdlib.h>
int main()
{
double *userNum = (double*)malloc(sizeof(double));
double sum = 0;
char userChar = 'Y';
int i = 0;
int j = 0;
if (userNum == NULL) {
printf("Error with memory");
return 1;
}
while (userChar == 'Y' || userChar == 'y') {
printf("Enter a number\n");
scanf("%lf", userNum);
printf("List of numbers:\n");
for (j; j < (i + 1); j++) {
printf( "%lf\n", userNum[j]);
}
printf("More numbers (Y/N)? \n");
getchar();
scanf("%c", &userChar);
if (userChar == 'Y' || userChar == 'y') {
userNum = realloc(userNum, (i + 2) * sizeof(double));
i++;
}
}
return 0;
)
You need to reinitialize your loop counter to 0 when printing out the numbers :
for (j = 0; j < (i + 1); j++) {
printf("%lf\n", userNum[j]);
}
And you need to increment the position in userNum that you scan the numbers into :
scanf("%lf", &userNum[i]);
I'm having trouble outputting an invalid statement if the user inputs a letter instead of a number into a 2D array.
I tried using the isalpha function to check if the input is a number or a letter, but it gives me a segmentation fault. Not sure what's wrong any tips?
the following code is just the part that assigns the elements of the matrix.
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#define MAX 10
void display(int matrix[][MAX], int size);
int main() {
int n, degree;
int matrix[MAX][MAX];
printf("Enter the size of the matrix: "); // assigning size of the matrix
scanf("%d", &n);
if (n <= 1 || n >= 11) { // can't be bigger than a 10x10 matrix
printf("Invalid input.");
return 0;
}
for (int i = 0; i < n; ++i) { // assigning the elements of matrix
printf("Enter the row %d of the matrix: ", i);
for (int j = 0; j < n; ++j) {
scanf("%d", &matrix[i][j]);
if (!isalpha(matrix[i][j])) { // portion I'm having trouble with
continue;
} else {
printf("Invalid input.");
return 0;
}
}
}
...
As the value of n will be number, we can solve it using string instead of int.
char num[10];
int n;
scanf("%s", num);
if(num[0] < '0' || num[0] > '9' || strlen(num) > 2){
printf("invalid\n");
}
if(strlen(num) == 1) n = num[0] - '0';
if(strlen(num) == 2 && num[0] != 1 && num[1] != 0) printf("invalid\n");
else n = 10;
Also we can use strtol() function to convert the input string to number and then check for validity.You can check the following code for it. I have skipped the string input part. Also you have to add #include<stdlib.h> at the start for the strtol() function to work.
char *check;
long val = strtol (num, &check, 10);
if ((next == num) || (*check != '\0')) {
printf ("invalid\n");
}
if(val > 10 || val < 0) printf("invalid\n");
n = (int)val; //typecasting as strtol return long
You must check the return value of scanf(): It will tell you if the input was correctly converted according to the format string. scanf() returns the number of successful conversions, which should be 1 in your case. If the user types a letter, scanf() will return 0 and the target value will be left uninitialized. Detecting this situation and either aborting or restarting input is the callers responsibility.
Here is a modified version of your code that illustrates both possibilities:
#include <stdio.h>
#define MAX 10
void display(int matrix[][MAX], int size);
int main(void) {
int n, degree;
int matrix[MAX][MAX];
printf("Enter the size of the matrix: "); // assigning size of the matrix
if (scanf("%d", &n) != 1 || n < 2 || n > 10) {
// can't be bigger than a 10x10 matrix nor smaller than 2x2
// aborting on invalid input
printf("Invalid input.");
return 1;
}
for (int i = 0; i < n; i++) { // assigning the elements of matrix
printf("Enter the row %d of the matrix: ", i);
for (int j = 0; j < n; j++) {
if (scanf("%d", &matrix[i][j]) != 1) {
// restarting on invalid input
int c;
while ((c = getchar()) != '\n') {
if (c == EOF) {
printf("unexpected end of file\n");
return 1;
}
}
printf("invalid input, try again.\n");
j--;
}
}
}
...
The isdigit() library function of stdlib in c can be used to check if the condition can be checked.
Try this:
if (isalpha (matrix[i][j])) {
printf ("Invalid input.");
return 0;
}
So if anyone in the future wants to know what I did. here is the code I used to fix the if statement. I am not expecting to put any elements greater than 10000 so if a letter or punctuation is inputted the number generated will be larger than this number. Hence the if (matrix[i][j] > 10000). May not be the fanciest way to do this, but it works and it's simple.
for (int i = 0; i < n; ++i) { // assigning the elements of matrix
printf("Enter the row %d of the matrix: ", i);
for (int j = 0; j < n; ++j) {
scanf("%d", &matrix[i][j]);
if (matrix[i][j] > 10000) { // portion "fixed"
printf("Invlaid input");
return 0;
}
}
}
I used a print statement to check the outputs of several letter and character inputs. The lowest out put is around and above 30000. So 10000 I think is a safe condition.
I made a C program to check if a number is palindrome or not. I used the following code, but it shows numbers like 12321 as non palindrome. Can you please explain me the mistake in the program below?
#include <stdio.h>
int main()
{
int i, x, n, c, j;
int d=0;
printf ("enter total digits in number: ");
scanf ("%d", &i);
printf ("\nenter number: ");
scanf ("%d", &n);
j=n;
for (x=1; x<=i; x++)
{
c= j%10;
d=c*(10^(i-x))+d;
j=(j-c)/10;
}
if (d==n)
{
printf ("\npalindrome");
}
else
{
printf ("\nnon palindrome");
}
return 0;
}
^ is the xor operator.
In order to raise power, you need to include math.h and call pow
d = (c * pow(10, i - x)) + d;
this algorithm is as simple as human thinking, and it works
#include <stdio.h>
int main() {
int i=0,n,ok=1;
char buff[20];
printf("Enter an integer: ");
scanf("%d", &n); // i am ommiting error checking
n=sprintf(buff,"%d",n); //convert it to string, and getting the len in result
if(n<2) return 0;
i=n/2;
n--;
while(i && ok) {
i--;
//printf("%c == %c %s\n", buff[i],buff[n-i],(buff[i]==buff[n-i])?"true":"false");
ok &= (buff[i]==buff[n-i]);
}
printf("%s is %spalindrome\n",buff, ok?"":"not ");
return 0;
}
// Yet another way to check for palindrome.
#include <stdio.h>
#include <stdlib.h>
int main(int argc, char **argv)
{
int n, rn, tn;
printf("Enter an integer: ");
scanf("%d", &n);
// reverse the number by repeatedly extracting last digit, add to the
// previously computed partial reverse times 10, and keep dropping
// last digit by dividing by 10
for (rn = 0, tn = n; tn; tn /= 10) rn = rn * 10 + tn % 10;
if (rn == n) printf("%d is palindrome\n", n);
else printf("%d is not palindrome\n", n);
}
A loop like this might do:
int src; // user input
int n; // no of digits
int res = 0;
int tmp; // copy of src
// .... read the input: n and src ....
tmp = src;
for(int i = 0; i < n; i ++)
{
int digit = tmp % 10; // extract the rightmost digit
tmp /= 10; // and remove it from source
res = 10*res + digit; // apend it to the result
}
// ...and test if(res == src)...
EDIT: Tried some suggestions and didn't alter too much but it kind of works gives me incorrect data but atleast they aren't zeros. Thanks everyone for thier assistance.
I'm writing code for reading grades from a text file and store them in an array. My full code is rather large so I'm only posting the part I having the issue in; my while loop not changing the values in the array. The sample data is 65 99 87 76 89 37 -999 all on separate lines. My output shows me that the array values remained zero after the function should have changed their values. The other while loops were all failed attempts at the same task.
int readGrades(double grades[]){
FILE* gd;
int count = 0;
double ind;
gd = fopen("sample.txt", "r");
while(count < MAX){ //MAX is defined as 100/array is grades[MAX]
fscanf(gd, "%lf", &ind); //Should scan through items in the file
if(ind < 0) //End of sample data is -999 this breaks out of the loop
break;
grades[count] = ind; //changes values in the array (it doesn't change them from 0)
count++; } //increments the index of the array
/*while(fscanf(gd, "%lf", &ind)>0){
grades[count] = ind;
count++; }*/
/*do {
fscanf(gd, "%lf", &grades[count]);
printf("%.0lf", grades[count]);
if(fscanf(gd, "%lf", &grades[count])== -999){
break;
}
count++;
}while(fscanf(gd, "%lf", &grades[count])> 0);*/
fclose(gd);
return count+1;
}
Some extra info: The grades array has to be initialized as double filled w/ 0s. I just need to replace the zeros in grades[] with the data from the text file.
I've been working on this for over a day now and still have had 0 progress. I just don't understand why it doesn't change the values in the array.
EDIT: This is where I call readGrades with the array data.
int numGrades;
numGrades = readGrades(grades);
right inside main. the #define MAX 100 and double grades[MAX] are delcared outside main. I return count+1 as the function needs to return the number of data items read.
Someone asked for the full program:
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
int readGrades(double []);
void frequency(double [], int);
int maximum(double [], int);
int minimum(double [], int);
int deleteElement(double [], int, int);
double mean(double [], int);
double standardDeviation(double [], int);
#define MAX 100
double grades[MAX];
int loc;
int main(){
int numGrades;
printf("%lf", grades);
numGrades = readGrades(grades);
loc = minimum(grades, numGrades);
numGrades = deleteElement(grades, numGrades, loc);
printf("The data has been adjusted by removing the minimum %.2lf\n", grades[loc]);
loc = maximum(grades, numGrades);
numGrades = deleteElement(grades, numGrades, loc);
printf("The data has been adjusted by removing the maximum %.2lf\n", grades[loc]);
printf("The adjusted mean is %.2lf\n", mean(grades, numGrades));
printf("The adjusted standard deviation is %.2lf\n", standardDeviation(grades, numGrades));
printf("Here is a histogram of the adjusted data:\n");
frequency(grades, numGrades);
return 0;
}
int readGrades(double grades[]){
FILE* gd;
int count = 0;
double ind;
gd = fopen("sample.txt", "r");
while(count < MAX){
fscanf(gd, "%lf", &ind);
//double atod(ind);
if(ind < 0)
break;
grades[count] = ind;
count++;
}
/*while(fscanf(gd, "%lf", &ind)>0){
grades[count] = ind;
count++;
}*/
/*do {
fscanf(gd, "%lf", &grades[count]);
printf("%.0lf", grades[count]);
if(fscanf(gd, "%lf", &grades[count])== -999){
break;
}
count++;
}while(fscanf(gd, "%lf", &grades[count])> 0);*/
printf("%.0lf", grades[1]);
fclose(gd);
return count+1;
}
void frequency(double grades[], int numGrades){
int j, i, a=0, b=a+4;
for(j=0; j<numGrades-1; j++){
printf("%d - %d|", a, b);
for(i=0; i<numGrades; i++){
if(grades[i]<=b && grades[i]>=a){
printf("*");
}
}
printf("\n");
a+=5;
if(a==100){
break;
}
}
printf("%d|", a);
for(j=0; j<numGrades; j++){
if(grades[i]==100)
printf("*");
}
printf("\n");
}
int maximum(double grades[], int numGrades){
int i, h = 0;
for(i=1; i<numGrades; i++){
/*if(grades[i] == grades[h])
continue;*/
if(grades[i] > grades[h])
h = i;
}
return h;
}
int minimum(double grades[], int numGrades){
int i, h = 0;
for(i=1; i<numGrades; i++){
/*if(grades[i] == grades[h])
continue;*/
if(grades[i] < grades[h])
h = i;
}
return h;
}
int deleteElement(double grades[], int numGrades, int loc){
int i;
for(i=loc; i<numGrades-1; i++){
grades[i] = grades[i+1];
}
return numGrades-=1;
}
double mean(double grades[], int numGrades){
int i;
double ans, sum;
for(i = 0; i<numGrades; i++){
sum += grades[i];
}
ans = sum/numGrades;
return ans;
}
double standardDeviation(double grades[], int numGrades){
int i;
double avg, sd, ans;
avg = mean(grades, numGrades);
for(i=0; i<numGrades; i++){
sd += pow((avg - grades[i]), 2);
}
ans = sqrt(sd/numGrades);
return ans;
}
I appreciate you all helping me with this.
Check the result of the fopen and fscanf calls:
gd = fopen( "sample.txt", "r" );
if ( !gd )
{
fprintf( stderr, "error opening input file\n" );
return 0;
}
while( count < max && fscanf( gd, "%lf", &ind ) == 1 )
{
if ( ind < 0 )
break;
grades[count++] = ind;
}
if ( feof( gd ))
fprintf( stderr, "hit end of file\n" );
else if ( ferror( gd ))
fprintf( stderr, "error during read\n" );
program is completely perfect. I am sure there is the issue in printf, the way you are using it. You paste the line where you are printing the values. I hope you must be doing something like this
printf("%lf\n",grades[i]);
Just for the betterment reason, you don't even need to pass grades[] as argument because that is global variable. FYI, in readGrades() it creates a local variable of the name grades[] when you are passing as reference.
Also, in readGrades() function "return count" should be ok as you're already doing increment of count within while-loop itself.
Your code is completely OK as #Pawan said. this second line printf("%lf"s, grades); in the main is not needed and runs in a error (to me). If you have the sample.txt in the same "EXE" path wouldn't be any issue. If your sample.txt is in another folder you must reference it with full path.
this is the current output:
Printint values from loop:
65
99
87.000000
76.000000
89.000000
37.000000
99
The data has been adjusted by removing the minimum 0.00
The data has been adjusted by removing the maximum 87.00
The adjusted mean is 70.80
The adjusted standard deviation is 18.96
Here is a histogram of the adjusted data:
0 - 4|
5 - 4|
10 - 4|
15 - 4|
20|
if you cannot open the file try
if ( !gd ) {
fprintf( stderr, "error opening input file\n", strerror(errno));
return 0;
}
to see the error. I think another process has opened the file.